X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FADT%2FScopedHashTable.h;h=efddd9f9b857576af2f7df97e7778d6751c9f26f;hb=ac39a035351a20928e087617e412aa6ce510181f;hp=a02ccb147b95689beba60cb9ce0a4ffe0170f286;hpb=d10e467ad961f7c3b548ee2f2de8a576a245e25a;p=oota-llvm.git diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index a02ccb147b9..efddd9f9b85 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -31,12 +31,13 @@ #ifndef LLVM_ADT_SCOPEDHASHTABLE_H #define LLVM_ADT_SCOPEDHASHTABLE_H -#include #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" namespace llvm { -template +template , + typename AllocatorTy = MallocAllocator> class ScopedHashTable; template @@ -45,52 +46,76 @@ class ScopedHashTableVal { ScopedHashTableVal *NextForKey; K Key; V Val; + ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {} public: - ScopedHashTableVal(ScopedHashTableVal *nextInScope, - ScopedHashTableVal *nextForKey, const K &key, const V &val) - : NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) { - } - + const K &getKey() const { return Key; } const V &getValue() const { return Val; } V &getValue() { return Val; } - + ScopedHashTableVal *getNextForKey() { return NextForKey; } const ScopedHashTableVal *getNextForKey() const { return NextForKey; } -public: ScopedHashTableVal *getNextInScope() { return NextInScope; } + + template + static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope, + ScopedHashTableVal *nextForKey, + const K &key, const V &val, + AllocatorTy &Allocator) { + ScopedHashTableVal *New = Allocator.template Allocate(); + // Set up the value. + new (New) ScopedHashTableVal(key, val); + New->NextInScope = nextInScope; + New->NextForKey = nextForKey; + return New; + } + + template + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~ScopedHashTableVal(); + Allocator.Deallocate(this); + } }; -template +template , + typename AllocatorTy = MallocAllocator> class ScopedHashTableScope { /// HT - The hashtable that we are active for. - ScopedHashTable &HT; - + ScopedHashTable &HT; + /// PrevScope - This is the scope that we are shadowing in HT. ScopedHashTableScope *PrevScope; /// LastValInScope - This is the last value that was inserted for this scope /// or null if none have been inserted yet. - ScopedHashTableVal *LastValInScope; - void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT - ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT + ScopedHashTableVal *LastValInScope; + void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; + ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; public: - ScopedHashTableScope(ScopedHashTable &HT); + ScopedHashTableScope(ScopedHashTable &HT); ~ScopedHashTableScope(); + + ScopedHashTableScope *getParentScope() { return PrevScope; } + const ScopedHashTableScope *getParentScope() const { return PrevScope; } private: - friend class ScopedHashTable; - ScopedHashTableVal *getLastValInScope() { return LastValInScope; } - void setLastValInScope(ScopedHashTableVal *Val) { LastValInScope = Val; } + friend class ScopedHashTable; + ScopedHashTableVal *getLastValInScope() { + return LastValInScope; + } + void setLastValInScope(ScopedHashTableVal *Val) { + LastValInScope = Val; + } }; -template +template > class ScopedHashTableIterator { - ScopedHashTableVal *Node; + ScopedHashTableVal *Node; public: - ScopedHashTableIterator(ScopedHashTableVal *node) : Node(node){} - + ScopedHashTableIterator(ScopedHashTableVal *node) : Node(node) {} + V &operator*() const { assert(Node && "Dereference end()"); return Node->getValue(); @@ -98,14 +123,14 @@ public: V *operator->() const { return &Node->getValue(); } - + bool operator==(const ScopedHashTableIterator &RHS) const { return Node == RHS.Node; } bool operator!=(const ScopedHashTableIterator &RHS) const { return Node != RHS.Node; } - + inline ScopedHashTableIterator& operator++() { // Preincrement assert(Node && "incrementing past end()"); Node = Node->getNextForKey(); @@ -117,56 +142,94 @@ public: }; -template +template class ScopedHashTable { - DenseMap*> TopLevelMap; - ScopedHashTableScope *CurScope; +public: + /// ScopeTy - This is a helpful typedef that allows clients to get easy access + /// to the name of the scope for this hash table. + typedef ScopedHashTableScope ScopeTy; +private: + typedef ScopedHashTableVal ValTy; + DenseMap TopLevelMap; + ScopeTy *CurScope; + + AllocatorTy Allocator; + ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED - friend class ScopedHashTableScope; + friend class ScopedHashTableScope; public: ScopedHashTable() : CurScope(0) {} + ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {} ~ScopedHashTable() { assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); } + + /// Access to the allocator. + typedef typename ReferenceAdder::result AllocatorRefTy; + typedef typename ReferenceAdder::result AllocatorCRefTy; + AllocatorRefTy getAllocator() { return Allocator; } + AllocatorCRefTy getAllocator() const { return Allocator; } + + bool count(const K &Key) const { + return TopLevelMap.count(Key); + } + + V lookup(const K &Key) { + typename DenseMap::iterator I = TopLevelMap.find(Key); + if (I != TopLevelMap.end()) + return I->second->getValue(); + + return V(); + } + void insert(const K &Key, const V &Val) { - assert(CurScope && "No scope active!"); - - ScopedHashTableVal *&KeyEntry = TopLevelMap[Key]; - - KeyEntry = new ScopedHashTableVal(CurScope->getLastValInScope(), - KeyEntry, Key, Val); - CurScope->setLastValInScope(KeyEntry); + insertIntoScope(CurScope, Key, Val); } - - typedef ScopedHashTableIterator iterator; + + typedef ScopedHashTableIterator iterator; iterator end() { return iterator(0); } iterator begin(const K &Key) { - typename DenseMap*>::iterator I = + typename DenseMap::iterator I = TopLevelMap.find(Key); if (I == TopLevelMap.end()) return end(); return iterator(I->second); } + + ScopeTy *getCurScope() { return CurScope; } + const ScopeTy *getCurScope() const { return CurScope; } + + /// insertIntoScope - This inserts the specified key/value at the specified + /// (possibly not the current) scope. While it is ok to insert into a scope + /// that isn't the current one, it isn't ok to insert *underneath* an existing + /// value of the specified key. + void insertIntoScope(ScopeTy *S, const K &Key, const V &Val) { + assert(S && "No scope active!"); + ScopedHashTableVal *&KeyEntry = TopLevelMap[Key]; + KeyEntry = ValTy::Create(S->getLastValInScope(), KeyEntry, Key, Val, + Allocator); + S->setLastValInScope(KeyEntry); + } }; /// ScopedHashTableScope ctor - Install this as the current scope for the hash /// table. -template -ScopedHashTableScope::ScopedHashTableScope(ScopedHashTable &ht) - : HT(ht) { +template +ScopedHashTableScope:: + ScopedHashTableScope(ScopedHashTable &ht) : HT(ht) { PrevScope = HT.CurScope; HT.CurScope = this; LastValInScope = 0; } -template -ScopedHashTableScope::~ScopedHashTableScope() { +template +ScopedHashTableScope::~ScopedHashTableScope() { assert(HT.CurScope == this && "Scope imbalance!"); HT.CurScope = PrevScope; - + // Pop and delete all values corresponding to this scope. while (ScopedHashTableVal *ThisEntry = LastValInScope) { // Pop this value out of the TopLevelMap. @@ -174,17 +237,17 @@ ScopedHashTableScope::~ScopedHashTableScope() { assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry && "Scope imbalance!"); HT.TopLevelMap.erase(ThisEntry->getKey()); - } else { - ScopedHashTableVal *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; + } else { + ScopedHashTableVal *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; assert(KeyEntry == ThisEntry && "Scope imbalance!"); KeyEntry = ThisEntry->getNextForKey(); } - + // Pop this value out of the scope. LastValInScope = ThisEntry->getNextInScope(); - + // Delete this entry. - delete ThisEntry; + ThisEntry->Destroy(HT.getAllocator()); } }