xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/ADT/ImmutableSet.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 //===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the ImutAVLTree and ImmutableSet classes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_ADT_IMMUTABLESET_H
14 #define LLVM_ADT_IMMUTABLESET_H
15 
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/FoldingSet.h"
18 #include "llvm/ADT/IntrusiveRefCntPtr.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/iterator.h"
21 #include "llvm/Support/Allocator.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include <cassert>
24 #include <cstdint>
25 #include <functional>
26 #include <iterator>
27 #include <new>
28 #include <vector>
29 
30 namespace llvm {
31 
32 //===----------------------------------------------------------------------===//
33 // Immutable AVL-Tree Definition.
34 //===----------------------------------------------------------------------===//
35 
36 template <typename ImutInfo> class ImutAVLFactory;
37 template <typename ImutInfo> class ImutIntervalAVLFactory;
38 template <typename ImutInfo> class ImutAVLTreeInOrderIterator;
39 template <typename ImutInfo> class ImutAVLTreeGenericIterator;
40 
41 template <typename ImutInfo >
42 class ImutAVLTree {
43 public:
44   using key_type_ref = typename ImutInfo::key_type_ref;
45   using value_type = typename ImutInfo::value_type;
46   using value_type_ref = typename ImutInfo::value_type_ref;
47   using Factory = ImutAVLFactory<ImutInfo>;
48   using iterator = ImutAVLTreeInOrderIterator<ImutInfo>;
49 
50   friend class ImutAVLFactory<ImutInfo>;
51   friend class ImutIntervalAVLFactory<ImutInfo>;
52   friend class ImutAVLTreeGenericIterator<ImutInfo>;
53 
54   //===----------------------------------------------------===//
55   // Public Interface.
56   //===----------------------------------------------------===//
57 
58   /// Return a pointer to the left subtree.  This value
59   ///  is NULL if there is no left subtree.
getLeft()60   ImutAVLTree *getLeft() const { return left; }
61 
62   /// Return a pointer to the right subtree.  This value is
63   ///  NULL if there is no right subtree.
getRight()64   ImutAVLTree *getRight() const { return right; }
65 
66   /// getHeight - Returns the height of the tree.  A tree with no subtrees
67   ///  has a height of 1.
getHeight()68   unsigned getHeight() const { return height; }
69 
70   /// getValue - Returns the data value associated with the tree node.
getValue()71   const value_type& getValue() const { return value; }
72 
73   /// find - Finds the subtree associated with the specified key value.
74   ///  This method returns NULL if no matching subtree is found.
find(key_type_ref K)75   ImutAVLTree* find(key_type_ref K) {
76     ImutAVLTree *T = this;
77     while (T) {
78       key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue());
79       if (ImutInfo::isEqual(K,CurrentKey))
80         return T;
81       else if (ImutInfo::isLess(K,CurrentKey))
82         T = T->getLeft();
83       else
84         T = T->getRight();
85     }
86     return nullptr;
87   }
88 
89   /// getMaxElement - Find the subtree associated with the highest ranged
90   ///  key value.
getMaxElement()91   ImutAVLTree* getMaxElement() {
92     ImutAVLTree *T = this;
93     ImutAVLTree *Right = T->getRight();
94     while (Right) { T = Right; Right = T->getRight(); }
95     return T;
96   }
97 
98   /// size - Returns the number of nodes in the tree, which includes
99   ///  both leaves and non-leaf nodes.
size()100   unsigned size() const {
101     unsigned n = 1;
102     if (const ImutAVLTree* L = getLeft())
103       n += L->size();
104     if (const ImutAVLTree* R = getRight())
105       n += R->size();
106     return n;
107   }
108 
109   /// begin - Returns an iterator that iterates over the nodes of the tree
110   ///  in an inorder traversal.  The returned iterator thus refers to the
111   ///  the tree node with the minimum data element.
begin()112   iterator begin() const { return iterator(this); }
113 
114   /// end - Returns an iterator for the tree that denotes the end of an
115   ///  inorder traversal.
end()116   iterator end() const { return iterator(); }
117 
isElementEqual(value_type_ref V)118   bool isElementEqual(value_type_ref V) const {
119     // Compare the keys.
120     if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()),
121                            ImutInfo::KeyOfValue(V)))
122       return false;
123 
124     // Also compare the data values.
125     if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()),
126                                ImutInfo::DataOfValue(V)))
127       return false;
128 
129     return true;
130   }
131 
isElementEqual(const ImutAVLTree * RHS)132   bool isElementEqual(const ImutAVLTree* RHS) const {
133     return isElementEqual(RHS->getValue());
134   }
135 
136   /// isEqual - Compares two trees for structural equality and returns true
137   ///   if they are equal.  This worst case performance of this operation is
138   //    linear in the sizes of the trees.
isEqual(const ImutAVLTree & RHS)139   bool isEqual(const ImutAVLTree& RHS) const {
140     if (&RHS == this)
141       return true;
142 
143     iterator LItr = begin(), LEnd = end();
144     iterator RItr = RHS.begin(), REnd = RHS.end();
145 
146     while (LItr != LEnd && RItr != REnd) {
147       if (&*LItr == &*RItr) {
148         LItr.skipSubTree();
149         RItr.skipSubTree();
150         continue;
151       }
152 
153       if (!LItr->isElementEqual(&*RItr))
154         return false;
155 
156       ++LItr;
157       ++RItr;
158     }
159 
160     return LItr == LEnd && RItr == REnd;
161   }
162 
163   /// isNotEqual - Compares two trees for structural inequality.  Performance
164   ///  is the same is isEqual.
isNotEqual(const ImutAVLTree & RHS)165   bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); }
166 
167   /// contains - Returns true if this tree contains a subtree (node) that
168   ///  has an data element that matches the specified key.  Complexity
169   ///  is logarithmic in the size of the tree.
contains(key_type_ref K)170   bool contains(key_type_ref K) { return (bool) find(K); }
171 
172   /// foreach - A member template the accepts invokes operator() on a functor
173   ///  object (specified by Callback) for every node/subtree in the tree.
174   ///  Nodes are visited using an inorder traversal.
175   template <typename Callback>
foreach(Callback & C)176   void foreach(Callback& C) {
177     if (ImutAVLTree* L = getLeft())
178       L->foreach(C);
179 
180     C(value);
181 
182     if (ImutAVLTree* R = getRight())
183       R->foreach(C);
184   }
185 
186   /// validateTree - A utility method that checks that the balancing and
187   ///  ordering invariants of the tree are satisfied.  It is a recursive
188   ///  method that returns the height of the tree, which is then consumed
189   ///  by the enclosing validateTree call.  External callers should ignore the
190   ///  return value.  An invalid tree will cause an assertion to fire in
191   ///  a debug build.
validateTree()192   unsigned validateTree() const {
193     unsigned HL = getLeft() ? getLeft()->validateTree() : 0;
194     unsigned HR = getRight() ? getRight()->validateTree() : 0;
195     (void) HL;
196     (void) HR;
197 
198     assert(getHeight() == ( HL > HR ? HL : HR ) + 1
199             && "Height calculation wrong");
200 
201     assert((HL > HR ? HL-HR : HR-HL) <= 2
202            && "Balancing invariant violated");
203 
204     assert((!getLeft() ||
205             ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()),
206                              ImutInfo::KeyOfValue(getValue()))) &&
207            "Value in left child is not less that current value");
208 
209     assert((!getRight() ||
210              ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()),
211                               ImutInfo::KeyOfValue(getRight()->getValue()))) &&
212            "Current value is not less that value of right child");
213 
214     return getHeight();
215   }
216 
217   //===----------------------------------------------------===//
218   // Internal values.
219   //===----------------------------------------------------===//
220 
221 private:
222   Factory *factory;
223   ImutAVLTree *left;
224   ImutAVLTree *right;
225   ImutAVLTree *prev = nullptr;
226   ImutAVLTree *next = nullptr;
227 
228   unsigned height : 28;
229   bool IsMutable : 1;
230   bool IsDigestCached : 1;
231   bool IsCanonicalized : 1;
232 
233   value_type value;
234   uint32_t digest = 0;
235   uint32_t refCount = 0;
236 
237   //===----------------------------------------------------===//
238   // Internal methods (node manipulation; used by Factory).
239   //===----------------------------------------------------===//
240 
241 private:
242   /// ImutAVLTree - Internal constructor that is only called by
243   ///   ImutAVLFactory.
ImutAVLTree(Factory * f,ImutAVLTree * l,ImutAVLTree * r,value_type_ref v,unsigned height)244   ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
245               unsigned height)
246     : factory(f), left(l), right(r), height(height), IsMutable(true),
247       IsDigestCached(false), IsCanonicalized(false), value(v)
248   {
249     if (left) left->retain();
250     if (right) right->retain();
251   }
252 
253   /// isMutable - Returns true if the left and right subtree references
254   ///  (as well as height) can be changed.  If this method returns false,
255   ///  the tree is truly immutable.  Trees returned from an ImutAVLFactory
256   ///  object should always have this method return true.  Further, if this
257   ///  method returns false for an instance of ImutAVLTree, all subtrees
258   ///  will also have this method return false.  The converse is not true.
isMutable()259   bool isMutable() const { return IsMutable; }
260 
261   /// hasCachedDigest - Returns true if the digest for this tree is cached.
262   ///  This can only be true if the tree is immutable.
hasCachedDigest()263   bool hasCachedDigest() const { return IsDigestCached; }
264 
265   //===----------------------------------------------------===//
266   // Mutating operations.  A tree root can be manipulated as
267   // long as its reference has not "escaped" from internal
268   // methods of a factory object (see below).  When a tree
269   // pointer is externally viewable by client code, the
270   // internal "mutable bit" is cleared to mark the tree
271   // immutable.  Note that a tree that still has its mutable
272   // bit set may have children (subtrees) that are themselves
273   // immutable.
274   //===----------------------------------------------------===//
275 
276   /// markImmutable - Clears the mutable flag for a tree.  After this happens,
277   ///   it is an error to call setLeft(), setRight(), and setHeight().
markImmutable()278   void markImmutable() {
279     assert(isMutable() && "Mutable flag already removed.");
280     IsMutable = false;
281   }
282 
283   /// markedCachedDigest - Clears the NoCachedDigest flag for a tree.
markedCachedDigest()284   void markedCachedDigest() {
285     assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
286     IsDigestCached = true;
287   }
288 
289   /// setHeight - Changes the height of the tree.  Used internally by
290   ///  ImutAVLFactory.
setHeight(unsigned h)291   void setHeight(unsigned h) {
292     assert(isMutable() && "Only a mutable tree can have its height changed.");
293     height = h;
294   }
295 
computeDigest(ImutAVLTree * L,ImutAVLTree * R,value_type_ref V)296   static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R,
297                                 value_type_ref V) {
298     uint32_t digest = 0;
299 
300     if (L)
301       digest += L->computeDigest();
302 
303     // Compute digest of stored data.
304     FoldingSetNodeID ID;
305     ImutInfo::Profile(ID,V);
306     digest += ID.ComputeHash();
307 
308     if (R)
309       digest += R->computeDigest();
310 
311     return digest;
312   }
313 
computeDigest()314   uint32_t computeDigest() {
315     // Check the lowest bit to determine if digest has actually been
316     // pre-computed.
317     if (hasCachedDigest())
318       return digest;
319 
320     uint32_t X = computeDigest(getLeft(), getRight(), getValue());
321     digest = X;
322     markedCachedDigest();
323     return X;
324   }
325 
326   //===----------------------------------------------------===//
327   // Reference count operations.
328   //===----------------------------------------------------===//
329 
330 public:
retain()331   void retain() { ++refCount; }
332 
release()333   void release() {
334     assert(refCount > 0);
335     if (--refCount == 0)
336       destroy();
337   }
338 
destroy()339   void destroy() {
340     if (left)
341       left->release();
342     if (right)
343       right->release();
344     if (IsCanonicalized) {
345       if (next)
346         next->prev = prev;
347 
348       if (prev)
349         prev->next = next;
350       else
351         factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
352     }
353 
354     // We need to clear the mutability bit in case we are
355     // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes().
356     IsMutable = false;
357     factory->freeNodes.push_back(this);
358   }
359 };
360 
361 template <typename ImutInfo>
362 struct IntrusiveRefCntPtrInfo<ImutAVLTree<ImutInfo>> {
363   static void retain(ImutAVLTree<ImutInfo> *Tree) { Tree->retain(); }
364   static void release(ImutAVLTree<ImutInfo> *Tree) { Tree->release(); }
365 };
366 
367 //===----------------------------------------------------------------------===//
368 // Immutable AVL-Tree Factory class.
369 //===----------------------------------------------------------------------===//
370 
371 template <typename ImutInfo >
372 class ImutAVLFactory {
373   friend class ImutAVLTree<ImutInfo>;
374 
375   using TreeTy = ImutAVLTree<ImutInfo>;
376   using value_type_ref = typename TreeTy::value_type_ref;
377   using key_type_ref = typename TreeTy::key_type_ref;
378   using CacheTy = DenseMap<unsigned, TreeTy*>;
379 
380   CacheTy Cache;
381   uintptr_t Allocator;
382   std::vector<TreeTy*> createdNodes;
383   std::vector<TreeTy*> freeNodes;
384 
385   bool ownsAllocator() const {
386     return (Allocator & 0x1) == 0;
387   }
388 
389   BumpPtrAllocator& getAllocator() const {
390     return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1);
391   }
392 
393   //===--------------------------------------------------===//
394   // Public interface.
395   //===--------------------------------------------------===//
396 
397 public:
398   ImutAVLFactory()
399     : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {}
400 
401   ImutAVLFactory(BumpPtrAllocator& Alloc)
402     : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {}
403 
404   ~ImutAVLFactory() {
405     if (ownsAllocator()) delete &getAllocator();
406   }
407 
408   TreeTy* add(TreeTy* T, value_type_ref V) {
409     T = add_internal(V,T);
410     markImmutable(T);
411     recoverNodes();
412     return T;
413   }
414 
415   TreeTy* remove(TreeTy* T, key_type_ref V) {
416     T = remove_internal(V,T);
417     markImmutable(T);
418     recoverNodes();
419     return T;
420   }
421 
422   TreeTy* getEmptyTree() const { return nullptr; }
423 
424 protected:
425   //===--------------------------------------------------===//
426   // A bunch of quick helper functions used for reasoning
427   // about the properties of trees and their children.
428   // These have succinct names so that the balancing code
429   // is as terse (and readable) as possible.
430   //===--------------------------------------------------===//
431 
432   bool            isEmpty(TreeTy* T) const { return !T; }
433   unsigned        getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; }
434   TreeTy*         getLeft(TreeTy* T) const { return T->getLeft(); }
435   TreeTy*         getRight(TreeTy* T) const { return T->getRight(); }
436   value_type_ref  getValue(TreeTy* T) const { return T->value; }
437 
438   // Make sure the index is not the Tombstone or Entry key of the DenseMap.
439   static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); }
440 
441   unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
442     unsigned hl = getHeight(L);
443     unsigned hr = getHeight(R);
444     return (hl > hr ? hl : hr) + 1;
445   }
446 
447   static bool compareTreeWithSection(TreeTy* T,
448                                      typename TreeTy::iterator& TI,
449                                      typename TreeTy::iterator& TE) {
450     typename TreeTy::iterator I = T->begin(), E = T->end();
451     for ( ; I!=E ; ++I, ++TI) {
452       if (TI == TE || !I->isElementEqual(&*TI))
453         return false;
454     }
455     return true;
456   }
457 
458   //===--------------------------------------------------===//
459   // "createNode" is used to generate new tree roots that link
460   // to other trees.  The function may also simply move links
461   // in an existing root if that root is still marked mutable.
462   // This is necessary because otherwise our balancing code
463   // would leak memory as it would create nodes that are
464   // then discarded later before the finished tree is
465   // returned to the caller.
466   //===--------------------------------------------------===//
467 
468   TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) {
469     BumpPtrAllocator& A = getAllocator();
470     TreeTy* T;
471     if (!freeNodes.empty()) {
472       T = freeNodes.back();
473       freeNodes.pop_back();
474       assert(T != L);
475       assert(T != R);
476     } else {
477       T = (TreeTy*) A.Allocate<TreeTy>();
478     }
479     new (T) TreeTy(this, L, R, V, incrementHeight(L,R));
480     createdNodes.push_back(T);
481     return T;
482   }
483 
484   TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) {
485     return createNode(newLeft, getValue(oldTree), newRight);
486   }
487 
488   void recoverNodes() {
489     for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) {
490       TreeTy *N = createdNodes[i];
491       if (N->isMutable() && N->refCount == 0)
492         N->destroy();
493     }
494     createdNodes.clear();
495   }
496 
497   /// balanceTree - Used by add_internal and remove_internal to
498   ///  balance a newly created tree.
499   TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) {
500     unsigned hl = getHeight(L);
501     unsigned hr = getHeight(R);
502 
503     if (hl > hr + 2) {
504       assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2");
505 
506       TreeTy *LL = getLeft(L);
507       TreeTy *LR = getRight(L);
508 
509       if (getHeight(LL) >= getHeight(LR))
510         return createNode(LL, L, createNode(LR,V,R));
511 
512       assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1");
513 
514       TreeTy *LRL = getLeft(LR);
515       TreeTy *LRR = getRight(LR);
516 
517       return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R));
518     }
519 
520     if (hr > hl + 2) {
521       assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2");
522 
523       TreeTy *RL = getLeft(R);
524       TreeTy *RR = getRight(R);
525 
526       if (getHeight(RR) >= getHeight(RL))
527         return createNode(createNode(L,V,RL), R, RR);
528 
529       assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1");
530 
531       TreeTy *RLL = getLeft(RL);
532       TreeTy *RLR = getRight(RL);
533 
534       return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR));
535     }
536 
537     return createNode(L,V,R);
538   }
539 
540   /// add_internal - Creates a new tree that includes the specified
541   ///  data and the data from the original tree.  If the original tree
542   ///  already contained the data item, the original tree is returned.
543   TreeTy* add_internal(value_type_ref V, TreeTy* T) {
544     if (isEmpty(T))
545       return createNode(T, V, T);
546     assert(!T->isMutable());
547 
548     key_type_ref K = ImutInfo::KeyOfValue(V);
549     key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
550 
551     if (ImutInfo::isEqual(K,KCurrent))
552       return createNode(getLeft(T), V, getRight(T));
553     else if (ImutInfo::isLess(K,KCurrent))
554       return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T));
555     else
556       return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T)));
557   }
558 
559   /// remove_internal - Creates a new tree that includes all the data
560   ///  from the original tree except the specified data.  If the
561   ///  specified data did not exist in the original tree, the original
562   ///  tree is returned.
563   TreeTy* remove_internal(key_type_ref K, TreeTy* T) {
564     if (isEmpty(T))
565       return T;
566 
567     assert(!T->isMutable());
568 
569     key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));
570 
571     if (ImutInfo::isEqual(K,KCurrent)) {
572       return combineTrees(getLeft(T), getRight(T));
573     } else if (ImutInfo::isLess(K,KCurrent)) {
574       return balanceTree(remove_internal(K, getLeft(T)),
575                                             getValue(T), getRight(T));
576     } else {
577       return balanceTree(getLeft(T), getValue(T),
578                          remove_internal(K, getRight(T)));
579     }
580   }
581 
582   TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
583     if (isEmpty(L))
584       return R;
585     if (isEmpty(R))
586       return L;
587     TreeTy* OldNode;
588     TreeTy* newRight = removeMinBinding(R,OldNode);
589     return balanceTree(L, getValue(OldNode), newRight);
590   }
591 
592   TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) {
593     assert(!isEmpty(T));
594     if (isEmpty(getLeft(T))) {
595       Noderemoved = T;
596       return getRight(T);
597     }
598     return balanceTree(removeMinBinding(getLeft(T), Noderemoved),
599                        getValue(T), getRight(T));
600   }
601 
602   /// markImmutable - Clears the mutable bits of a root and all of its
603   ///  descendants.
604   void markImmutable(TreeTy* T) {
605     if (!T || !T->isMutable())
606       return;
607     T->markImmutable();
608     markImmutable(getLeft(T));
609     markImmutable(getRight(T));
610   }
611 
612 public:
613   TreeTy *getCanonicalTree(TreeTy *TNew) {
614     if (!TNew)
615       return nullptr;
616 
617     if (TNew->IsCanonicalized)
618       return TNew;
619 
620     // Search the hashtable for another tree with the same digest, and
621     // if find a collision compare those trees by their contents.
622     unsigned digest = TNew->computeDigest();
623     TreeTy *&entry = Cache[maskCacheIndex(digest)];
624     do {
625       if (!entry)
626         break;
627       for (TreeTy *T = entry ; T != nullptr; T = T->next) {
628         // Compare the Contents('T') with Contents('TNew')
629         typename TreeTy::iterator TI = T->begin(), TE = T->end();
630         if (!compareTreeWithSection(TNew, TI, TE))
631           continue;
632         if (TI != TE)
633           continue; // T has more contents than TNew.
634         // Trees did match!  Return 'T'.
635         if (TNew->refCount == 0)
636           TNew->destroy();
637         return T;
638       }
639       entry->prev = TNew;
640       TNew->next = entry;
641     }
642     while (false);
643 
644     entry = TNew;
645     TNew->IsCanonicalized = true;
646     return TNew;
647   }
648 };
649 
650 //===----------------------------------------------------------------------===//
651 // Immutable AVL-Tree Iterators.
652 //===----------------------------------------------------------------------===//
653 
654 template <typename ImutInfo> class ImutAVLTreeGenericIterator {
655   SmallVector<uintptr_t,20> stack;
656 
657 public:
658   using iterator_category = std::bidirectional_iterator_tag;
659   using value_type = ImutAVLTree<ImutInfo>;
660   using difference_type = std::ptrdiff_t;
661   using pointer = value_type *;
662   using reference = value_type &;
663 
664   enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
665                    Flags=0x3 };
666 
667   using TreeTy = ImutAVLTree<ImutInfo>;
668 
669   ImutAVLTreeGenericIterator() = default;
670   ImutAVLTreeGenericIterator(const TreeTy *Root) {
671     if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root));
672   }
673 
674   TreeTy &operator*() const {
675     assert(!stack.empty());
676     return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags);
677   }
678   TreeTy *operator->() const { return &*this; }
679 
680   uintptr_t getVisitState() const {
681     assert(!stack.empty());
682     return stack.back() & Flags;
683   }
684 
685   bool atEnd() const { return stack.empty(); }
686 
687   bool atBeginning() const {
688     return stack.size() == 1 && getVisitState() == VisitedNone;
689   }
690 
691   void skipToParent() {
692     assert(!stack.empty());
693     stack.pop_back();
694     if (stack.empty())
695       return;
696     switch (getVisitState()) {
697       case VisitedNone:
698         stack.back() |= VisitedLeft;
699         break;
700       case VisitedLeft:
701         stack.back() |= VisitedRight;
702         break;
703       default:
704         llvm_unreachable("Unreachable.");
705     }
706   }
707 
708   bool operator==(const ImutAVLTreeGenericIterator &x) const {
709     return stack == x.stack;
710   }
711 
712   bool operator!=(const ImutAVLTreeGenericIterator &x) const {
713     return !(*this == x);
714   }
715 
716   ImutAVLTreeGenericIterator &operator++() {
717     assert(!stack.empty());
718     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
719     assert(Current);
720     switch (getVisitState()) {
721       case VisitedNone:
722         if (TreeTy* L = Current->getLeft())
723           stack.push_back(reinterpret_cast<uintptr_t>(L));
724         else
725           stack.back() |= VisitedLeft;
726         break;
727       case VisitedLeft:
728         if (TreeTy* R = Current->getRight())
729           stack.push_back(reinterpret_cast<uintptr_t>(R));
730         else
731           stack.back() |= VisitedRight;
732         break;
733       case VisitedRight:
734         skipToParent();
735         break;
736       default:
737         llvm_unreachable("Unreachable.");
738     }
739     return *this;
740   }
741 
742   ImutAVLTreeGenericIterator &operator--() {
743     assert(!stack.empty());
744     TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags);
745     assert(Current);
746     switch (getVisitState()) {
747       case VisitedNone:
748         stack.pop_back();
749         break;
750       case VisitedLeft:
751         stack.back() &= ~Flags; // Set state to "VisitedNone."
752         if (TreeTy* L = Current->getLeft())
753           stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight);
754         break;
755       case VisitedRight:
756         stack.back() &= ~Flags;
757         stack.back() |= VisitedLeft;
758         if (TreeTy* R = Current->getRight())
759           stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
760         break;
761       default:
762         llvm_unreachable("Unreachable.");
763     }
764     return *this;
765   }
766 };
767 
768 template <typename ImutInfo> class ImutAVLTreeInOrderIterator {
769   using InternalIteratorTy = ImutAVLTreeGenericIterator<ImutInfo>;
770 
771   InternalIteratorTy InternalItr;
772 
773 public:
774   using iterator_category = std::bidirectional_iterator_tag;
775   using value_type = ImutAVLTree<ImutInfo>;
776   using difference_type = std::ptrdiff_t;
777   using pointer = value_type *;
778   using reference = value_type &;
779 
780   using TreeTy = ImutAVLTree<ImutInfo>;
781 
782   ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
783     if (Root)
784       ++*this; // Advance to first element.
785   }
786 
787   ImutAVLTreeInOrderIterator() : InternalItr() {}
788 
789   bool operator==(const ImutAVLTreeInOrderIterator &x) const {
790     return InternalItr == x.InternalItr;
791   }
792 
793   bool operator!=(const ImutAVLTreeInOrderIterator &x) const {
794     return !(*this == x);
795   }
796 
797   TreeTy &operator*() const { return *InternalItr; }
798   TreeTy *operator->() const { return &*InternalItr; }
799 
800   ImutAVLTreeInOrderIterator &operator++() {
801     do ++InternalItr;
802     while (!InternalItr.atEnd() &&
803            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
804 
805     return *this;
806   }
807 
808   ImutAVLTreeInOrderIterator &operator--() {
809     do --InternalItr;
810     while (!InternalItr.atBeginning() &&
811            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft);
812 
813     return *this;
814   }
815 
816   void skipSubTree() {
817     InternalItr.skipToParent();
818 
819     while (!InternalItr.atEnd() &&
820            InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft)
821       ++InternalItr;
822   }
823 };
824 
825 /// Generic iterator that wraps a T::TreeTy::iterator and exposes
826 /// iterator::getValue() on dereference.
827 template <typename T>
828 struct ImutAVLValueIterator
829     : iterator_adaptor_base<
830           ImutAVLValueIterator<T>, typename T::TreeTy::iterator,
831           typename std::iterator_traits<
832               typename T::TreeTy::iterator>::iterator_category,
833           const typename T::value_type> {
834   ImutAVLValueIterator() = default;
835   explicit ImutAVLValueIterator(typename T::TreeTy *Tree)
836       : ImutAVLValueIterator::iterator_adaptor_base(Tree) {}
837 
838   typename ImutAVLValueIterator::reference operator*() const {
839     return this->I->getValue();
840   }
841 };
842 
843 //===----------------------------------------------------------------------===//
844 // Trait classes for Profile information.
845 //===----------------------------------------------------------------------===//
846 
847 /// Generic profile template.  The default behavior is to invoke the
848 /// profile method of an object.  Specializations for primitive integers
849 /// and generic handling of pointers is done below.
850 template <typename T>
851 struct ImutProfileInfo {
852   using value_type = const T;
853   using value_type_ref = const T&;
854 
855   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
856     FoldingSetTrait<T>::Profile(X,ID);
857   }
858 };
859 
860 /// Profile traits for integers.
861 template <typename T>
862 struct ImutProfileInteger {
863   using value_type = const T;
864   using value_type_ref = const T&;
865 
866   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
867     ID.AddInteger(X);
868   }
869 };
870 
871 #define PROFILE_INTEGER_INFO(X)\
872 template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {};
873 
874 PROFILE_INTEGER_INFO(char)
875 PROFILE_INTEGER_INFO(unsigned char)
876 PROFILE_INTEGER_INFO(short)
877 PROFILE_INTEGER_INFO(unsigned short)
878 PROFILE_INTEGER_INFO(unsigned)
879 PROFILE_INTEGER_INFO(signed)
880 PROFILE_INTEGER_INFO(long)
881 PROFILE_INTEGER_INFO(unsigned long)
882 PROFILE_INTEGER_INFO(long long)
883 PROFILE_INTEGER_INFO(unsigned long long)
884 
885 #undef PROFILE_INTEGER_INFO
886 
887 /// Profile traits for booleans.
888 template <>
889 struct ImutProfileInfo<bool> {
890   using value_type = const bool;
891   using value_type_ref = const bool&;
892 
893   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
894     ID.AddBoolean(X);
895   }
896 };
897 
898 /// Generic profile trait for pointer types.  We treat pointers as
899 /// references to unique objects.
900 template <typename T>
901 struct ImutProfileInfo<T*> {
902   using value_type = const T*;
903   using value_type_ref = value_type;
904 
905   static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
906     ID.AddPointer(X);
907   }
908 };
909 
910 //===----------------------------------------------------------------------===//
911 // Trait classes that contain element comparison operators and type
912 //  definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap.  These
913 //  inherit from the profile traits (ImutProfileInfo) to include operations
914 //  for element profiling.
915 //===----------------------------------------------------------------------===//
916 
917 /// ImutContainerInfo - Generic definition of comparison operations for
918 ///   elements of immutable containers that defaults to using
919 ///   std::equal_to<> and std::less<> to perform comparison of elements.
920 template <typename T>
921 struct ImutContainerInfo : public ImutProfileInfo<T> {
922   using value_type = typename ImutProfileInfo<T>::value_type;
923   using value_type_ref = typename ImutProfileInfo<T>::value_type_ref;
924   using key_type = value_type;
925   using key_type_ref = value_type_ref;
926   using data_type = bool;
927   using data_type_ref = bool;
928 
929   static key_type_ref KeyOfValue(value_type_ref D) { return D; }
930   static data_type_ref DataOfValue(value_type_ref) { return true; }
931 
932   static bool isEqual(key_type_ref LHS, key_type_ref RHS) {
933     return std::equal_to<key_type>()(LHS,RHS);
934   }
935 
936   static bool isLess(key_type_ref LHS, key_type_ref RHS) {
937     return std::less<key_type>()(LHS,RHS);
938   }
939 
940   static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
941 };
942 
943 /// ImutContainerInfo - Specialization for pointer values to treat pointers
944 ///  as references to unique objects.  Pointers are thus compared by
945 ///  their addresses.
946 template <typename T>
947 struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
948   using value_type = typename ImutProfileInfo<T*>::value_type;
949   using value_type_ref = typename ImutProfileInfo<T*>::value_type_ref;
950   using key_type = value_type;
951   using key_type_ref = value_type_ref;
952   using data_type = bool;
953   using data_type_ref = bool;
954 
955   static key_type_ref KeyOfValue(value_type_ref D) { return D; }
956   static data_type_ref DataOfValue(value_type_ref) { return true; }
957 
958   static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; }
959 
960   static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; }
961 
962   static bool isDataEqual(data_type_ref, data_type_ref) { return true; }
963 };
964 
965 //===----------------------------------------------------------------------===//
966 // Immutable Set
967 //===----------------------------------------------------------------------===//
968 
969 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
970 class ImmutableSet {
971 public:
972   using value_type = typename ValInfo::value_type;
973   using value_type_ref = typename ValInfo::value_type_ref;
974   using TreeTy = ImutAVLTree<ValInfo>;
975 
976 private:
977   IntrusiveRefCntPtr<TreeTy> Root;
978 
979 public:
980   /// Constructs a set from a pointer to a tree root.  In general one
981   /// should use a Factory object to create sets instead of directly
982   /// invoking the constructor, but there are cases where make this
983   /// constructor public is useful.
984   explicit ImmutableSet(TreeTy *R) : Root(R) {}
985 
986   class Factory {
987     typename TreeTy::Factory F;
988     const bool Canonicalize;
989 
990   public:
991     Factory(bool canonicalize = true)
992       : Canonicalize(canonicalize) {}
993 
994     Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
995       : F(Alloc), Canonicalize(canonicalize) {}
996 
997     Factory(const Factory& RHS) = delete;
998     void operator=(const Factory& RHS) = delete;
999 
1000     /// getEmptySet - Returns an immutable set that contains no elements.
1001     ImmutableSet getEmptySet() {
1002       return ImmutableSet(F.getEmptyTree());
1003     }
1004 
1005     /// add - Creates a new immutable set that contains all of the values
1006     ///  of the original set with the addition of the specified value.  If
1007     ///  the original set already included the value, then the original set is
1008     ///  returned and no memory is allocated.  The time and space complexity
1009     ///  of this operation is logarithmic in the size of the original set.
1010     ///  The memory allocated to represent the set is released when the
1011     ///  factory object that created the set is destroyed.
1012     LLVM_NODISCARD ImmutableSet add(ImmutableSet Old, value_type_ref V) {
1013       TreeTy *NewT = F.add(Old.Root.get(), V);
1014       return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1015     }
1016 
1017     /// remove - Creates a new immutable set that contains all of the values
1018     ///  of the original set with the exception of the specified value.  If
1019     ///  the original set did not contain the value, the original set is
1020     ///  returned and no memory is allocated.  The time and space complexity
1021     ///  of this operation is logarithmic in the size of the original set.
1022     ///  The memory allocated to represent the set is released when the
1023     ///  factory object that created the set is destroyed.
1024     LLVM_NODISCARD ImmutableSet remove(ImmutableSet Old, value_type_ref V) {
1025       TreeTy *NewT = F.remove(Old.Root.get(), V);
1026       return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT);
1027     }
1028 
1029     BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
1030 
1031     typename TreeTy::Factory *getTreeFactory() const {
1032       return const_cast<typename TreeTy::Factory *>(&F);
1033     }
1034   };
1035 
1036   friend class Factory;
1037 
1038   /// Returns true if the set contains the specified value.
1039   bool contains(value_type_ref V) const {
1040     return Root ? Root->contains(V) : false;
1041   }
1042 
1043   bool operator==(const ImmutableSet &RHS) const {
1044     return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1045   }
1046 
1047   bool operator!=(const ImmutableSet &RHS) const {
1048     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1049                             : Root != RHS.Root;
1050   }
1051 
1052   TreeTy *getRoot() {
1053     if (Root) { Root->retain(); }
1054     return Root.get();
1055   }
1056 
1057   TreeTy *getRootWithoutRetain() const { return Root.get(); }
1058 
1059   /// isEmpty - Return true if the set contains no elements.
1060   bool isEmpty() const { return !Root; }
1061 
1062   /// isSingleton - Return true if the set contains exactly one element.
1063   ///   This method runs in constant time.
1064   bool isSingleton() const { return getHeight() == 1; }
1065 
1066   template <typename Callback>
1067   void foreach(Callback& C) { if (Root) Root->foreach(C); }
1068 
1069   template <typename Callback>
1070   void foreach() { if (Root) { Callback C; Root->foreach(C); } }
1071 
1072   //===--------------------------------------------------===//
1073   // Iterators.
1074   //===--------------------------------------------------===//
1075 
1076   using iterator = ImutAVLValueIterator<ImmutableSet>;
1077 
1078   iterator begin() const { return iterator(Root.get()); }
1079   iterator end() const { return iterator(); }
1080 
1081   //===--------------------------------------------------===//
1082   // Utility methods.
1083   //===--------------------------------------------------===//
1084 
1085   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1086 
1087   static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) {
1088     ID.AddPointer(S.Root.get());
1089   }
1090 
1091   void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1092 
1093   //===--------------------------------------------------===//
1094   // For testing.
1095   //===--------------------------------------------------===//
1096 
1097   void validateTree() const { if (Root) Root->validateTree(); }
1098 };
1099 
1100 // NOTE: This may some day replace the current ImmutableSet.
1101 template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
1102 class ImmutableSetRef {
1103 public:
1104   using value_type = typename ValInfo::value_type;
1105   using value_type_ref = typename ValInfo::value_type_ref;
1106   using TreeTy = ImutAVLTree<ValInfo>;
1107   using FactoryTy = typename TreeTy::Factory;
1108 
1109 private:
1110   IntrusiveRefCntPtr<TreeTy> Root;
1111   FactoryTy *Factory;
1112 
1113 public:
1114   /// Constructs a set from a pointer to a tree root.  In general one
1115   /// should use a Factory object to create sets instead of directly
1116   /// invoking the constructor, but there are cases where make this
1117   /// constructor public is useful.
1118   ImmutableSetRef(TreeTy *R, FactoryTy *F) : Root(R), Factory(F) {}
1119 
1120   static ImmutableSetRef getEmptySet(FactoryTy *F) {
1121     return ImmutableSetRef(0, F);
1122   }
1123 
1124   ImmutableSetRef add(value_type_ref V) {
1125     return ImmutableSetRef(Factory->add(Root.get(), V), Factory);
1126   }
1127 
1128   ImmutableSetRef remove(value_type_ref V) {
1129     return ImmutableSetRef(Factory->remove(Root.get(), V), Factory);
1130   }
1131 
1132   /// Returns true if the set contains the specified value.
1133   bool contains(value_type_ref V) const {
1134     return Root ? Root->contains(V) : false;
1135   }
1136 
1137   ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const {
1138     return ImmutableSet<ValT>(
1139         canonicalize ? Factory->getCanonicalTree(Root.get()) : Root.get());
1140   }
1141 
1142   TreeTy *getRootWithoutRetain() const { return Root.get(); }
1143 
1144   bool operator==(const ImmutableSetRef &RHS) const {
1145     return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
1146   }
1147 
1148   bool operator!=(const ImmutableSetRef &RHS) const {
1149     return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
1150                             : Root != RHS.Root;
1151   }
1152 
1153   /// isEmpty - Return true if the set contains no elements.
1154   bool isEmpty() const { return !Root; }
1155 
1156   /// isSingleton - Return true if the set contains exactly one element.
1157   ///   This method runs in constant time.
1158   bool isSingleton() const { return getHeight() == 1; }
1159 
1160   //===--------------------------------------------------===//
1161   // Iterators.
1162   //===--------------------------------------------------===//
1163 
1164   using iterator = ImutAVLValueIterator<ImmutableSetRef>;
1165 
1166   iterator begin() const { return iterator(Root.get()); }
1167   iterator end() const { return iterator(); }
1168 
1169   //===--------------------------------------------------===//
1170   // Utility methods.
1171   //===--------------------------------------------------===//
1172 
1173   unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
1174 
1175   static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) {
1176     ID.AddPointer(S.Root.get());
1177   }
1178 
1179   void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
1180 
1181   //===--------------------------------------------------===//
1182   // For testing.
1183   //===--------------------------------------------------===//
1184 
1185   void validateTree() const { if (Root) Root->validateTree(); }
1186 };
1187 
1188 } // end namespace llvm
1189 
1190 #endif // LLVM_ADT_IMMUTABLESET_H
1191