mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172025 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			249 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===--- ImmutableIntervalMap.h - Immutable (functional) map  ---*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file defines the ImmutableIntervalMap class.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef LLVM_ADT_IMMUTABLEINTERVALMAP_H
 | |
| #define LLVM_ADT_IMMUTABLEINTERVALMAP_H
 | |
| 
 | |
| #include "llvm/ADT/ImmutableMap.h"
 | |
| 
 | |
| namespace llvm {
 | |
| 
 | |
| class Interval {
 | |
| private:
 | |
|   int64_t Start;
 | |
|   int64_t End;
 | |
| 
 | |
| public:
 | |
|   Interval(int64_t S, int64_t E) : Start(S), End(E) {}
 | |
| 
 | |
|   int64_t getStart() const { return Start; }
 | |
|   int64_t getEnd() const { return End; }
 | |
| };
 | |
| 
 | |
| template <typename T>
 | |
| struct ImutIntervalInfo {
 | |
|   typedef const std::pair<Interval, T> value_type;
 | |
|   typedef const value_type &value_type_ref;
 | |
|   typedef const Interval key_type;
 | |
|   typedef const Interval &key_type_ref;
 | |
|   typedef const T data_type;
 | |
|   typedef const T &data_type_ref;
 | |
| 
 | |
|   static key_type_ref KeyOfValue(value_type_ref V) {
 | |
|     return V.first;
 | |
|   }
 | |
| 
 | |
|   static data_type_ref DataOfValue(value_type_ref V) {
 | |
|     return V.second;
 | |
|   }
 | |
| 
 | |
|   static bool isEqual(key_type_ref L, key_type_ref R) {
 | |
|     return L.getStart() == R.getStart() && L.getEnd() == R.getEnd();
 | |
|   }
 | |
| 
 | |
|   static bool isDataEqual(data_type_ref L, data_type_ref R) {
 | |
|     return ImutContainerInfo<T>::isEqual(L,R);
 | |
|   }
 | |
| 
 | |
|   static bool isLess(key_type_ref L, key_type_ref R) {
 | |
|     // Assume L and R does not overlap.
 | |
|     if (L.getStart() < R.getStart()) {
 | |
|       assert(L.getEnd() < R.getStart());
 | |
|       return true;
 | |
|     } else if (L.getStart() == R.getStart()) {
 | |
|       assert(L.getEnd() == R.getEnd());
 | |
|       return false;
 | |
|     } else {
 | |
|       assert(L.getStart() > R.getEnd());
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static bool isContainedIn(key_type_ref K, key_type_ref L) {
 | |
|     if (K.getStart() >= L.getStart() && K.getEnd() <= L.getEnd())
 | |
|       return true;
 | |
|     else
 | |
|       return false;
 | |
|   }
 | |
| 
 | |
|   static void Profile(FoldingSetNodeID &ID, value_type_ref V) {
 | |
|     ID.AddInteger(V.first.getStart());
 | |
|     ID.AddInteger(V.first.getEnd());
 | |
|     ImutProfileInfo<T>::Profile(ID, V.second);
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename ImutInfo>
 | |
| class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> {
 | |
|   typedef ImutAVLTree<ImutInfo> TreeTy;
 | |
|   typedef typename ImutInfo::value_type     value_type;
 | |
|   typedef typename ImutInfo::value_type_ref value_type_ref;
 | |
|   typedef typename ImutInfo::key_type       key_type;
 | |
|   typedef typename ImutInfo::key_type_ref   key_type_ref;
 | |
|   typedef typename ImutInfo::data_type      data_type;
 | |
|   typedef typename ImutInfo::data_type_ref  data_type_ref;
 | |
| 
 | |
| public:
 | |
|   ImutIntervalAVLFactory(BumpPtrAllocator &Alloc) 
 | |
|     : ImutAVLFactory<ImutInfo>(Alloc) {}
 | |
| 
 | |
|   TreeTy *Add(TreeTy *T, value_type_ref V) {
 | |
|     T = add_internal(V,T);
 | |
|     this->MarkImmutable(T);
 | |
|     return T;
 | |
|   }
 | |
| 
 | |
|   TreeTy *Find(TreeTy *T, key_type_ref K) {
 | |
|     if (!T)
 | |
|       return NULL;
 | |
| 
 | |
|     key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T));
 | |
| 
 | |
|     if (ImutInfo::isContainedIn(K, CurrentKey))
 | |
|       return T;
 | |
|     else if (ImutInfo::isLess(K, CurrentKey))
 | |
|       return Find(this->getLeft(T), K);
 | |
|     else
 | |
|       return Find(this->getRight(T), K);
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   TreeTy *add_internal(value_type_ref V, TreeTy *T) {
 | |
|     key_type_ref K = ImutInfo::KeyOfValue(V);
 | |
|     T = removeAllOverlaps(T, K);
 | |
|     if (this->isEmpty(T))
 | |
|       return this->CreateNode(NULL, V, NULL);
 | |
| 
 | |
|     assert(!T->isMutable());
 | |
| 
 | |
|     key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T));
 | |
| 
 | |
|     if (ImutInfo::isLess(K, KCurrent))
 | |
|       return this->Balance(add_internal(V, this->Left(T)), this->Value(T), 
 | |
|                                         this->Right(T));
 | |
|     else
 | |
|       return this->Balance(this->Left(T), this->Value(T), 
 | |
|                            add_internal(V, this->Right(T)));
 | |
|   }
 | |
| 
 | |
|   // Remove all overlaps from T.
 | |
|   TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) {
 | |
|     bool Changed;
 | |
|     do {
 | |
|       Changed = false;
 | |
|       T = removeOverlap(T, K, Changed);
 | |
|       this->markImmutable(T);
 | |
|     } while (Changed);
 | |
| 
 | |
|     return T;
 | |
|   }
 | |
| 
 | |
|   // Remove one overlap from T.
 | |
|   TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) {
 | |
|     if (!T)
 | |
|       return NULL;
 | |
|     Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T));
 | |
| 
 | |
|     // If current key does not overlap the inserted key.
 | |
|     if (CurrentK.getStart() > K.getEnd())
 | |
|       return this->Balance(removeOverlap(this->Left(T), K, Changed),
 | |
|                            this->Value(T), this->Right(T));
 | |
|     else if (CurrentK.getEnd() < K.getStart())
 | |
|       return this->Balance(this->Left(T), this->Value(T), 
 | |
|                            removeOverlap(this->Right(T), K, Changed));
 | |
| 
 | |
|     // Current key overlaps with the inserted key.
 | |
|     // Remove the current key.
 | |
|     Changed = true;
 | |
|     data_type_ref OldData = ImutInfo::DataOfValue(this->Value(T));
 | |
|     T = this->Remove_internal(CurrentK, T);
 | |
|     // Add back the unoverlapped part of the current key.
 | |
|     if (CurrentK.getStart() < K.getStart()) {
 | |
|       if (CurrentK.getEnd() <= K.getEnd()) {
 | |
|         Interval NewK(CurrentK.getStart(), K.getStart()-1);
 | |
|         return add_internal(std::make_pair(NewK, OldData), T);
 | |
|       } else {
 | |
|         Interval NewK1(CurrentK.getStart(), K.getStart()-1);
 | |
|         T = add_internal(std::make_pair(NewK1, OldData), T); 
 | |
| 
 | |
|         Interval NewK2(K.getEnd()+1, CurrentK.getEnd());
 | |
|         return add_internal(std::make_pair(NewK2, OldData), T);
 | |
|       }
 | |
|     } else {
 | |
|       if (CurrentK.getEnd() > K.getEnd()) {
 | |
|         Interval NewK(K.getEnd()+1, CurrentK.getEnd());
 | |
|         return add_internal(std::make_pair(NewK, OldData), T);
 | |
|       } else
 | |
|         return T;
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| /// ImmutableIntervalMap maps an interval [start, end] to a value. The intervals
 | |
| /// in the map are guaranteed to be disjoint.
 | |
| template <typename ValT>
 | |
| class ImmutableIntervalMap 
 | |
|   : public ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> > {
 | |
| 
 | |
|   typedef typename ImutIntervalInfo<ValT>::value_type      value_type;
 | |
|   typedef typename ImutIntervalInfo<ValT>::value_type_ref  value_type_ref;
 | |
|   typedef typename ImutIntervalInfo<ValT>::key_type        key_type;
 | |
|   typedef typename ImutIntervalInfo<ValT>::key_type_ref    key_type_ref;
 | |
|   typedef typename ImutIntervalInfo<ValT>::data_type       data_type;
 | |
|   typedef typename ImutIntervalInfo<ValT>::data_type_ref   data_type_ref;
 | |
|   typedef ImutAVLTree<ImutIntervalInfo<ValT> > TreeTy;
 | |
| 
 | |
| public:
 | |
|   explicit ImmutableIntervalMap(TreeTy *R) 
 | |
|     : ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> >(R) {}
 | |
| 
 | |
|   class Factory {
 | |
|     ImutIntervalAVLFactory<ImutIntervalInfo<ValT> > F;
 | |
| 
 | |
|   public:
 | |
|     Factory(BumpPtrAllocator& Alloc) : F(Alloc) {}
 | |
| 
 | |
|     ImmutableIntervalMap getEmptyMap() { 
 | |
|       return ImmutableIntervalMap(F.getEmptyTree()); 
 | |
|     }
 | |
| 
 | |
|     ImmutableIntervalMap add(ImmutableIntervalMap Old, 
 | |
|                              key_type_ref K, data_type_ref D) {
 | |
|       TreeTy *T = F.add(Old.Root, std::pair<key_type, data_type>(K, D));
 | |
|       return ImmutableIntervalMap(F.getCanonicalTree(T));
 | |
|     }
 | |
| 
 | |
|     ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) {
 | |
|       TreeTy *T = F.remove(Old.Root, K);
 | |
|       return ImmutableIntervalMap(F.getCanonicalTree(T));
 | |
|     }
 | |
| 
 | |
|     data_type *lookup(ImmutableIntervalMap M, key_type_ref K) {
 | |
|       TreeTy *T = F.Find(M.getRoot(), K);
 | |
|       if (T)
 | |
|         return &T->getValue().second;
 | |
|       else
 | |
|         return 0;
 | |
|     }
 | |
|   };
 | |
| 
 | |
| private:
 | |
|   // For ImmutableIntervalMap, the lookup operation has to be done by the 
 | |
|   // factory.
 | |
|   data_type* lookup(key_type_ref K) const;
 | |
| };
 | |
| 
 | |
| } // end namespace llvm
 | |
| 
 | |
| #endif
 |