Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

794 lines
29 KiB

  1. //===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines a hash set that can be used to remove duplication of nodes
  11. // in a graph. This code was originally created by Chris Lattner for use with
  12. // SelectionDAGCSEMap, but was isolated to provide use across the llvm code set.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #ifndef LLVM_ADT_FOLDINGSET_H
  16. #define LLVM_ADT_FOLDINGSET_H
  17. #include "llvm/ADT/SmallVector.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include "llvm/Support/DataTypes.h"
  20. namespace llvm {
  21. class APFloat;
  22. class APInt;
  23. class BumpPtrAllocator;
  24. /// This folding set used for two purposes:
  25. /// 1. Given information about a node we want to create, look up the unique
  26. /// instance of the node in the set. If the node already exists, return
  27. /// it, otherwise return the bucket it should be inserted into.
  28. /// 2. Given a node that has already been created, remove it from the set.
  29. ///
  30. /// This class is implemented as a single-link chained hash table, where the
  31. /// "buckets" are actually the nodes themselves (the next pointer is in the
  32. /// node). The last node points back to the bucket to simplify node removal.
  33. ///
  34. /// Any node that is to be included in the folding set must be a subclass of
  35. /// FoldingSetNode. The node class must also define a Profile method used to
  36. /// establish the unique bits of data for the node. The Profile method is
  37. /// passed a FoldingSetNodeID object which is used to gather the bits. Just
  38. /// call one of the Add* functions defined in the FoldingSetImpl::NodeID class.
  39. /// NOTE: That the folding set does not own the nodes and it is the
  40. /// responsibility of the user to dispose of the nodes.
  41. ///
  42. /// Eg.
  43. /// class MyNode : public FoldingSetNode {
  44. /// private:
  45. /// std::string Name;
  46. /// unsigned Value;
  47. /// public:
  48. /// MyNode(const char *N, unsigned V) : Name(N), Value(V) {}
  49. /// ...
  50. /// void Profile(FoldingSetNodeID &ID) const {
  51. /// ID.AddString(Name);
  52. /// ID.AddInteger(Value);
  53. /// }
  54. /// ...
  55. /// };
  56. ///
  57. /// To define the folding set itself use the FoldingSet template;
  58. ///
  59. /// Eg.
  60. /// FoldingSet<MyNode> MyFoldingSet;
  61. ///
  62. /// Four public methods are available to manipulate the folding set;
  63. ///
  64. /// 1) If you have an existing node that you want add to the set but unsure
  65. /// that the node might already exist then call;
  66. ///
  67. /// MyNode *M = MyFoldingSet.GetOrInsertNode(N);
  68. ///
  69. /// If The result is equal to the input then the node has been inserted.
  70. /// Otherwise, the result is the node existing in the folding set, and the
  71. /// input can be discarded (use the result instead.)
  72. ///
  73. /// 2) If you are ready to construct a node but want to check if it already
  74. /// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to
  75. /// check;
  76. ///
  77. /// FoldingSetNodeID ID;
  78. /// ID.AddString(Name);
  79. /// ID.AddInteger(Value);
  80. /// void *InsertPoint;
  81. ///
  82. /// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint);
  83. ///
  84. /// If found then M with be non-NULL, else InsertPoint will point to where it
  85. /// should be inserted using InsertNode.
  86. ///
  87. /// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new
  88. /// node with FindNodeOrInsertPos;
  89. ///
  90. /// InsertNode(N, InsertPoint);
  91. ///
  92. /// 4) Finally, if you want to remove a node from the folding set call;
  93. ///
  94. /// bool WasRemoved = RemoveNode(N);
  95. ///
  96. /// The result indicates whether the node existed in the folding set.
  97. class FoldingSetNodeID;
  98. //===----------------------------------------------------------------------===//
  99. /// FoldingSetImpl - Implements the folding set functionality. The main
  100. /// structure is an array of buckets. Each bucket is indexed by the hash of
  101. /// the nodes it contains. The bucket itself points to the nodes contained
  102. /// in the bucket via a singly linked list. The last node in the list points
  103. /// back to the bucket to facilitate node removal.
  104. ///
  105. class FoldingSetImpl {
  106. protected:
  107. /// Buckets - Array of bucket chains.
  108. ///
  109. void **Buckets;
  110. /// NumBuckets - Length of the Buckets array. Always a power of 2.
  111. ///
  112. unsigned NumBuckets;
  113. /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes
  114. /// is greater than twice the number of buckets.
  115. unsigned NumNodes;
  116. public:
  117. explicit FoldingSetImpl(unsigned Log2InitSize = 6);
  118. virtual ~FoldingSetImpl();
  119. //===--------------------------------------------------------------------===//
  120. /// Node - This class is used to maintain the singly linked bucket list in
  121. /// a folding set.
  122. ///
  123. class Node {
  124. private:
  125. // NextInFoldingSetBucket - next link in the bucket list.
  126. void *NextInFoldingSetBucket;
  127. public:
  128. Node() : NextInFoldingSetBucket(0) {}
  129. // Accessors
  130. void *getNextInBucket() const { return NextInFoldingSetBucket; }
  131. void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; }
  132. };
  133. /// clear - Remove all nodes from the folding set.
  134. void clear();
  135. /// RemoveNode - Remove a node from the folding set, returning true if one
  136. /// was removed or false if the node was not in the folding set.
  137. bool RemoveNode(Node *N);
  138. /// GetOrInsertNode - If there is an existing simple Node exactly
  139. /// equal to the specified node, return it. Otherwise, insert 'N' and return
  140. /// it instead.
  141. Node *GetOrInsertNode(Node *N);
  142. /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
  143. /// return it. If not, return the insertion token that will make insertion
  144. /// faster.
  145. Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos);
  146. /// InsertNode - Insert the specified node into the folding set, knowing that
  147. /// it is not already in the folding set. InsertPos must be obtained from
  148. /// FindNodeOrInsertPos.
  149. void InsertNode(Node *N, void *InsertPos);
  150. /// InsertNode - Insert the specified node into the folding set, knowing that
  151. /// it is not already in the folding set.
  152. void InsertNode(Node *N) {
  153. Node *Inserted = GetOrInsertNode(N);
  154. (void)Inserted;
  155. assert(Inserted == N && "Node already inserted!");
  156. }
  157. /// size - Returns the number of nodes in the folding set.
  158. unsigned size() const { return NumNodes; }
  159. /// empty - Returns true if there are no nodes in the folding set.
  160. bool empty() const { return NumNodes == 0; }
  161. private:
  162. /// GrowHashTable - Double the size of the hash table and rehash everything.
  163. ///
  164. void GrowHashTable();
  165. protected:
  166. /// GetNodeProfile - Instantiations of the FoldingSet template implement
  167. /// this function to gather data bits for the given node.
  168. virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0;
  169. /// NodeEquals - Instantiations of the FoldingSet template implement
  170. /// this function to compare the given node with the given ID.
  171. virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
  172. FoldingSetNodeID &TempID) const=0;
  173. /// ComputeNodeHash - Instantiations of the FoldingSet template implement
  174. /// this function to compute a hash value for the given node.
  175. virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0;
  176. };
  177. //===----------------------------------------------------------------------===//
  178. template<typename T> struct FoldingSetTrait;
  179. /// DefaultFoldingSetTrait - This class provides default implementations
  180. /// for FoldingSetTrait implementations.
  181. ///
  182. template<typename T> struct DefaultFoldingSetTrait {
  183. static void Profile(const T &X, FoldingSetNodeID &ID) {
  184. X.Profile(ID);
  185. }
  186. static void Profile(T &X, FoldingSetNodeID &ID) {
  187. X.Profile(ID);
  188. }
  189. // Equals - Test if the profile for X would match ID, using TempID
  190. // to compute a temporary ID if necessary. The default implementation
  191. // just calls Profile and does a regular comparison. Implementations
  192. // can override this to provide more efficient implementations.
  193. static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
  194. FoldingSetNodeID &TempID);
  195. // ComputeHash - Compute a hash value for X, using TempID to
  196. // compute a temporary ID if necessary. The default implementation
  197. // just calls Profile and does a regular hash computation.
  198. // Implementations can override this to provide more efficient
  199. // implementations.
  200. static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID);
  201. };
  202. /// FoldingSetTrait - This trait class is used to define behavior of how
  203. /// to "profile" (in the FoldingSet parlance) an object of a given type.
  204. /// The default behavior is to invoke a 'Profile' method on an object, but
  205. /// through template specialization the behavior can be tailored for specific
  206. /// types. Combined with the FoldingSetNodeWrapper class, one can add objects
  207. /// to FoldingSets that were not originally designed to have that behavior.
  208. template<typename T> struct FoldingSetTrait
  209. : public DefaultFoldingSetTrait<T> {};
  210. template<typename T, typename Ctx> struct ContextualFoldingSetTrait;
  211. /// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but
  212. /// for ContextualFoldingSets.
  213. template<typename T, typename Ctx>
  214. struct DefaultContextualFoldingSetTrait {
  215. static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
  216. X.Profile(ID, Context);
  217. }
  218. static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
  219. FoldingSetNodeID &TempID, Ctx Context);
  220. static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID,
  221. Ctx Context);
  222. };
  223. /// ContextualFoldingSetTrait - Like FoldingSetTrait, but for
  224. /// ContextualFoldingSets.
  225. template<typename T, typename Ctx> struct ContextualFoldingSetTrait
  226. : public DefaultContextualFoldingSetTrait<T, Ctx> {};
  227. //===--------------------------------------------------------------------===//
  228. /// FoldingSetNodeIDRef - This class describes a reference to an interned
  229. /// FoldingSetNodeID, which can be a useful to store node id data rather
  230. /// than using plain FoldingSetNodeIDs, since the 32-element SmallVector
  231. /// is often much larger than necessary, and the possibility of heap
  232. /// allocation means it requires a non-trivial destructor call.
  233. class FoldingSetNodeIDRef {
  234. const unsigned *Data;
  235. size_t Size;
  236. public:
  237. FoldingSetNodeIDRef() : Data(0), Size(0) {}
  238. FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
  239. /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
  240. /// used to lookup the node in the FoldingSetImpl.
  241. unsigned ComputeHash() const;
  242. bool operator==(FoldingSetNodeIDRef) const;
  243. /// Used to compare the "ordering" of two nodes as defined by the
  244. /// profiled bits and their ordering defined by memcmp().
  245. bool operator<(FoldingSetNodeIDRef) const;
  246. const unsigned *getData() const { return Data; }
  247. size_t getSize() const { return Size; }
  248. };
  249. //===--------------------------------------------------------------------===//
  250. /// FoldingSetNodeID - This class is used to gather all the unique data bits of
  251. /// a node. When all the bits are gathered this class is used to produce a
  252. /// hash value for the node.
  253. ///
  254. class FoldingSetNodeID {
  255. /// Bits - Vector of all the data bits that make the node unique.
  256. /// Use a SmallVector to avoid a heap allocation in the common case.
  257. SmallVector<unsigned, 32> Bits;
  258. public:
  259. FoldingSetNodeID() {}
  260. FoldingSetNodeID(FoldingSetNodeIDRef Ref)
  261. : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
  262. /// Add* - Add various data types to Bit data.
  263. ///
  264. void AddPointer(const void *Ptr);
  265. void AddInteger(signed I);
  266. void AddInteger(unsigned I);
  267. void AddInteger(long I);
  268. void AddInteger(unsigned long I);
  269. void AddInteger(long long I);
  270. void AddInteger(unsigned long long I);
  271. void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
  272. void AddString(StringRef String);
  273. void AddNodeID(const FoldingSetNodeID &ID);
  274. template <typename T>
  275. inline void Add(const T &x) { FoldingSetTrait<T>::Profile(x, *this); }
  276. /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID
  277. /// object to be used to compute a new profile.
  278. inline void clear() { Bits.clear(); }
  279. /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used
  280. /// to lookup the node in the FoldingSetImpl.
  281. unsigned ComputeHash() const;
  282. /// operator== - Used to compare two nodes to each other.
  283. ///
  284. bool operator==(const FoldingSetNodeID &RHS) const;
  285. bool operator==(const FoldingSetNodeIDRef RHS) const;
  286. /// Used to compare the "ordering" of two nodes as defined by the
  287. /// profiled bits and their ordering defined by memcmp().
  288. bool operator<(const FoldingSetNodeID &RHS) const;
  289. bool operator<(const FoldingSetNodeIDRef RHS) const;
  290. /// Intern - Copy this node's data to a memory region allocated from the
  291. /// given allocator and return a FoldingSetNodeIDRef describing the
  292. /// interned data.
  293. FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const;
  294. };
  295. // Convenience type to hide the implementation of the folding set.
  296. typedef FoldingSetImpl::Node FoldingSetNode;
  297. template<class T> class FoldingSetIterator;
  298. template<class T> class FoldingSetBucketIterator;
  299. // Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which
  300. // require the definition of FoldingSetNodeID.
  301. template<typename T>
  302. inline bool
  303. DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID,
  304. unsigned IDHash, FoldingSetNodeID &TempID) {
  305. FoldingSetTrait<T>::Profile(X, TempID);
  306. return TempID == ID;
  307. }
  308. template<typename T>
  309. inline unsigned
  310. DefaultFoldingSetTrait<T>::ComputeHash(T &X, FoldingSetNodeID &TempID) {
  311. FoldingSetTrait<T>::Profile(X, TempID);
  312. return TempID.ComputeHash();
  313. }
  314. template<typename T, typename Ctx>
  315. inline bool
  316. DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X,
  317. const FoldingSetNodeID &ID,
  318. unsigned IDHash,
  319. FoldingSetNodeID &TempID,
  320. Ctx Context) {
  321. ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
  322. return TempID == ID;
  323. }
  324. template<typename T, typename Ctx>
  325. inline unsigned
  326. DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
  327. FoldingSetNodeID &TempID,
  328. Ctx Context) {
  329. ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
  330. return TempID.ComputeHash();
  331. }
  332. //===----------------------------------------------------------------------===//
  333. /// FoldingSet - This template class is used to instantiate a specialized
  334. /// implementation of the folding set to the node class T. T must be a
  335. /// subclass of FoldingSetNode and implement a Profile function.
  336. ///
  337. template<class T> class FoldingSet : public FoldingSetImpl {
  338. private:
  339. /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
  340. /// way to convert nodes into a unique specifier.
  341. virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const {
  342. T *TN = static_cast<T *>(N);
  343. FoldingSetTrait<T>::Profile(*TN, ID);
  344. }
  345. /// NodeEquals - Instantiations may optionally provide a way to compare a
  346. /// node with a specified ID.
  347. virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
  348. FoldingSetNodeID &TempID) const {
  349. T *TN = static_cast<T *>(N);
  350. return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
  351. }
  352. /// ComputeNodeHash - Instantiations may optionally provide a way to compute a
  353. /// hash value directly from a node.
  354. virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const {
  355. T *TN = static_cast<T *>(N);
  356. return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
  357. }
  358. public:
  359. explicit FoldingSet(unsigned Log2InitSize = 6)
  360. : FoldingSetImpl(Log2InitSize)
  361. {}
  362. typedef FoldingSetIterator<T> iterator;
  363. iterator begin() { return iterator(Buckets); }
  364. iterator end() { return iterator(Buckets+NumBuckets); }
  365. typedef FoldingSetIterator<const T> const_iterator;
  366. const_iterator begin() const { return const_iterator(Buckets); }
  367. const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
  368. typedef FoldingSetBucketIterator<T> bucket_iterator;
  369. bucket_iterator bucket_begin(unsigned hash) {
  370. return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
  371. }
  372. bucket_iterator bucket_end(unsigned hash) {
  373. return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
  374. }
  375. /// GetOrInsertNode - If there is an existing simple Node exactly
  376. /// equal to the specified node, return it. Otherwise, insert 'N' and
  377. /// return it instead.
  378. T *GetOrInsertNode(Node *N) {
  379. return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
  380. }
  381. /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
  382. /// return it. If not, return the insertion token that will make insertion
  383. /// faster.
  384. T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
  385. return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
  386. }
  387. };
  388. //===----------------------------------------------------------------------===//
  389. /// ContextualFoldingSet - This template class is a further refinement
  390. /// of FoldingSet which provides a context argument when calling
  391. /// Profile on its nodes. Currently, that argument is fixed at
  392. /// initialization time.
  393. ///
  394. /// T must be a subclass of FoldingSetNode and implement a Profile
  395. /// function with signature
  396. /// void Profile(llvm::FoldingSetNodeID &, Ctx);
  397. template <class T, class Ctx>
  398. class ContextualFoldingSet : public FoldingSetImpl {
  399. // Unfortunately, this can't derive from FoldingSet<T> because the
  400. // construction vtable for FoldingSet<T> requires
  401. // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
  402. // requires a single-argument T::Profile().
  403. private:
  404. Ctx Context;
  405. /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
  406. /// way to convert nodes into a unique specifier.
  407. virtual void GetNodeProfile(FoldingSetImpl::Node *N,
  408. FoldingSetNodeID &ID) const {
  409. T *TN = static_cast<T *>(N);
  410. ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context);
  411. }
  412. virtual bool NodeEquals(FoldingSetImpl::Node *N,
  413. const FoldingSetNodeID &ID, unsigned IDHash,
  414. FoldingSetNodeID &TempID) const {
  415. T *TN = static_cast<T *>(N);
  416. return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
  417. Context);
  418. }
  419. virtual unsigned ComputeNodeHash(FoldingSetImpl::Node *N,
  420. FoldingSetNodeID &TempID) const {
  421. T *TN = static_cast<T *>(N);
  422. return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context);
  423. }
  424. public:
  425. explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
  426. : FoldingSetImpl(Log2InitSize), Context(Context)
  427. {}
  428. Ctx getContext() const { return Context; }
  429. typedef FoldingSetIterator<T> iterator;
  430. iterator begin() { return iterator(Buckets); }
  431. iterator end() { return iterator(Buckets+NumBuckets); }
  432. typedef FoldingSetIterator<const T> const_iterator;
  433. const_iterator begin() const { return const_iterator(Buckets); }
  434. const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
  435. typedef FoldingSetBucketIterator<T> bucket_iterator;
  436. bucket_iterator bucket_begin(unsigned hash) {
  437. return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
  438. }
  439. bucket_iterator bucket_end(unsigned hash) {
  440. return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
  441. }
  442. /// GetOrInsertNode - If there is an existing simple Node exactly
  443. /// equal to the specified node, return it. Otherwise, insert 'N'
  444. /// and return it instead.
  445. T *GetOrInsertNode(Node *N) {
  446. return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
  447. }
  448. /// FindNodeOrInsertPos - Look up the node specified by ID. If it
  449. /// exists, return it. If not, return the insertion token that will
  450. /// make insertion faster.
  451. T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
  452. return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
  453. }
  454. };
  455. //===----------------------------------------------------------------------===//
  456. /// FoldingSetVectorIterator - This implements an iterator for
  457. /// FoldingSetVector. It is only necessary because FoldingSetIterator provides
  458. /// a value_type of T, while the vector in FoldingSetVector exposes
  459. /// a value_type of T*. Fortunately, FoldingSetIterator doesn't expose very
  460. /// much besides operator* and operator->, so we just wrap the inner vector
  461. /// iterator and perform the extra dereference.
  462. template <class T, class VectorIteratorT>
  463. class FoldingSetVectorIterator {
  464. // Provide a typedef to workaround the lack of correct injected class name
  465. // support in older GCCs.
  466. typedef FoldingSetVectorIterator<T, VectorIteratorT> SelfT;
  467. VectorIteratorT Iterator;
  468. public:
  469. FoldingSetVectorIterator(VectorIteratorT I) : Iterator(I) {}
  470. bool operator==(const SelfT &RHS) const {
  471. return Iterator == RHS.Iterator;
  472. }
  473. bool operator!=(const SelfT &RHS) const {
  474. return Iterator != RHS.Iterator;
  475. }
  476. T &operator*() const { return **Iterator; }
  477. T *operator->() const { return *Iterator; }
  478. inline SelfT &operator++() {
  479. ++Iterator;
  480. return *this;
  481. }
  482. SelfT operator++(int) {
  483. SelfT tmp = *this;
  484. ++*this;
  485. return tmp;
  486. }
  487. };
  488. //===----------------------------------------------------------------------===//
  489. /// FoldingSetVector - This template class combines a FoldingSet and a vector
  490. /// to provide the interface of FoldingSet but with deterministic iteration
  491. /// order based on the insertion order. T must be a subclass of FoldingSetNode
  492. /// and implement a Profile function.
  493. template <class T, class VectorT = SmallVector<T*, 8> >
  494. class FoldingSetVector {
  495. FoldingSet<T> Set;
  496. VectorT Vector;
  497. public:
  498. explicit FoldingSetVector(unsigned Log2InitSize = 6)
  499. : Set(Log2InitSize) {
  500. }
  501. typedef FoldingSetVectorIterator<T, typename VectorT::iterator> iterator;
  502. iterator begin() { return Vector.begin(); }
  503. iterator end() { return Vector.end(); }
  504. typedef FoldingSetVectorIterator<const T, typename VectorT::const_iterator>
  505. const_iterator;
  506. const_iterator begin() const { return Vector.begin(); }
  507. const_iterator end() const { return Vector.end(); }
  508. /// clear - Remove all nodes from the folding set.
  509. void clear() { Set.clear(); Vector.clear(); }
  510. /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
  511. /// return it. If not, return the insertion token that will make insertion
  512. /// faster.
  513. T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
  514. return Set.FindNodeOrInsertPos(ID, InsertPos);
  515. }
  516. /// GetOrInsertNode - If there is an existing simple Node exactly
  517. /// equal to the specified node, return it. Otherwise, insert 'N' and
  518. /// return it instead.
  519. T *GetOrInsertNode(T *N) {
  520. T *Result = Set.GetOrInsertNode(N);
  521. if (Result == N) Vector.push_back(N);
  522. return Result;
  523. }
  524. /// InsertNode - Insert the specified node into the folding set, knowing that
  525. /// it is not already in the folding set. InsertPos must be obtained from
  526. /// FindNodeOrInsertPos.
  527. void InsertNode(T *N, void *InsertPos) {
  528. Set.InsertNode(N, InsertPos);
  529. Vector.push_back(N);
  530. }
  531. /// InsertNode - Insert the specified node into the folding set, knowing that
  532. /// it is not already in the folding set.
  533. void InsertNode(T *N) {
  534. Set.InsertNode(N);
  535. Vector.push_back(N);
  536. }
  537. /// size - Returns the number of nodes in the folding set.
  538. unsigned size() const { return Set.size(); }
  539. /// empty - Returns true if there are no nodes in the folding set.
  540. bool empty() const { return Set.empty(); }
  541. };
  542. //===----------------------------------------------------------------------===//
  543. /// FoldingSetIteratorImpl - This is the common iterator support shared by all
  544. /// folding sets, which knows how to walk the folding set hash table.
  545. class FoldingSetIteratorImpl {
  546. protected:
  547. FoldingSetNode *NodePtr;
  548. FoldingSetIteratorImpl(void **Bucket);
  549. void advance();
  550. public:
  551. bool operator==(const FoldingSetIteratorImpl &RHS) const {
  552. return NodePtr == RHS.NodePtr;
  553. }
  554. bool operator!=(const FoldingSetIteratorImpl &RHS) const {
  555. return NodePtr != RHS.NodePtr;
  556. }
  557. };
  558. template<class T>
  559. class FoldingSetIterator : public FoldingSetIteratorImpl {
  560. public:
  561. explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {}
  562. T &operator*() const {
  563. return *static_cast<T*>(NodePtr);
  564. }
  565. T *operator->() const {
  566. return static_cast<T*>(NodePtr);
  567. }
  568. inline FoldingSetIterator &operator++() { // Preincrement
  569. advance();
  570. return *this;
  571. }
  572. FoldingSetIterator operator++(int) { // Postincrement
  573. FoldingSetIterator tmp = *this; ++*this; return tmp;
  574. }
  575. };
  576. //===----------------------------------------------------------------------===//
  577. /// FoldingSetBucketIteratorImpl - This is the common bucket iterator support
  578. /// shared by all folding sets, which knows how to walk a particular bucket
  579. /// of a folding set hash table.
  580. class FoldingSetBucketIteratorImpl {
  581. protected:
  582. void *Ptr;
  583. explicit FoldingSetBucketIteratorImpl(void **Bucket);
  584. FoldingSetBucketIteratorImpl(void **Bucket, bool)
  585. : Ptr(Bucket) {}
  586. void advance() {
  587. void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket();
  588. uintptr_t x = reinterpret_cast<uintptr_t>(Probe) & ~0x1;
  589. Ptr = reinterpret_cast<void*>(x);
  590. }
  591. public:
  592. bool operator==(const FoldingSetBucketIteratorImpl &RHS) const {
  593. return Ptr == RHS.Ptr;
  594. }
  595. bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const {
  596. return Ptr != RHS.Ptr;
  597. }
  598. };
  599. template<class T>
  600. class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl {
  601. public:
  602. explicit FoldingSetBucketIterator(void **Bucket) :
  603. FoldingSetBucketIteratorImpl(Bucket) {}
  604. FoldingSetBucketIterator(void **Bucket, bool) :
  605. FoldingSetBucketIteratorImpl(Bucket, true) {}
  606. T &operator*() const { return *static_cast<T*>(Ptr); }
  607. T *operator->() const { return static_cast<T*>(Ptr); }
  608. inline FoldingSetBucketIterator &operator++() { // Preincrement
  609. advance();
  610. return *this;
  611. }
  612. FoldingSetBucketIterator operator++(int) { // Postincrement
  613. FoldingSetBucketIterator tmp = *this; ++*this; return tmp;
  614. }
  615. };
  616. //===----------------------------------------------------------------------===//
  617. /// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary
  618. /// types in an enclosing object so that they can be inserted into FoldingSets.
  619. template <typename T>
  620. class FoldingSetNodeWrapper : public FoldingSetNode {
  621. T data;
  622. public:
  623. explicit FoldingSetNodeWrapper(const T &x) : data(x) {}
  624. virtual ~FoldingSetNodeWrapper() {}
  625. template<typename A1>
  626. explicit FoldingSetNodeWrapper(const A1 &a1)
  627. : data(a1) {}
  628. template <typename A1, typename A2>
  629. explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2)
  630. : data(a1,a2) {}
  631. template <typename A1, typename A2, typename A3>
  632. explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3)
  633. : data(a1,a2,a3) {}
  634. template <typename A1, typename A2, typename A3, typename A4>
  635. explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3,
  636. const A4 &a4)
  637. : data(a1,a2,a3,a4) {}
  638. template <typename A1, typename A2, typename A3, typename A4, typename A5>
  639. explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3,
  640. const A4 &a4, const A5 &a5)
  641. : data(a1,a2,a3,a4,a5) {}
  642. void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); }
  643. T &getValue() { return data; }
  644. const T &getValue() const { return data; }
  645. operator T&() { return data; }
  646. operator const T&() const { return data; }
  647. };
  648. //===----------------------------------------------------------------------===//
  649. /// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores
  650. /// a FoldingSetNodeID value rather than requiring the node to recompute it
  651. /// each time it is needed. This trades space for speed (which can be
  652. /// significant if the ID is long), and it also permits nodes to drop
  653. /// information that would otherwise only be required for recomputing an ID.
  654. class FastFoldingSetNode : public FoldingSetNode {
  655. FoldingSetNodeID FastID;
  656. protected:
  657. explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
  658. public:
  659. void Profile(FoldingSetNodeID &ID) const {
  660. ID.AddNodeID(FastID);
  661. }
  662. };
  663. //===----------------------------------------------------------------------===//
  664. // Partial specializations of FoldingSetTrait.
  665. template<typename T> struct FoldingSetTrait<T*> {
  666. static inline void Profile(T *X, FoldingSetNodeID &ID) {
  667. ID.AddPointer(X);
  668. }
  669. };
  670. } // End of namespace llvm.
  671. #endif