LLVM API Documentation

ScopedHashTable.h

Go to the documentation of this file.
00001 //===- ScopedHashTable.h - A simple scoped hash table ---------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements an efficient scoped hash table, which is useful for
00011 // things like dominator-based optimizations.  This allows clients to do things
00012 // like this:
00013 //
00014 //  ScopedHashTable<int, int> HT;
00015 //  {
00016 //    ScopedHashTableScope<int, int> Scope1(HT);
00017 //    HT.insert(0, 0);
00018 //    HT.insert(1, 1);
00019 //    {
00020 //      ScopedHashTableScope<int, int> Scope2(HT);
00021 //      HT.insert(0, 42);
00022 //    }
00023 //  }
00024 //
00025 // Looking up the value for "0" in the Scope2 block will return 42.  Looking
00026 // up the value for 0 before 42 is inserted or after Scope2 is popped will
00027 // return 0.
00028 //
00029 //===----------------------------------------------------------------------===//
00030 
00031 #ifndef LLVM_ADT_SCOPEDHASHTABLE_H
00032 #define LLVM_ADT_SCOPEDHASHTABLE_H
00033 
00034 #include <cassert>
00035 #include "llvm/ADT/DenseMap.h"
00036 
00037 namespace llvm {
00038 
00039 template <typename K, typename V>
00040 class ScopedHashTable;
00041 
00042 template <typename K, typename V>
00043 class ScopedHashTableVal {
00044   ScopedHashTableVal *NextInScope;
00045   ScopedHashTableVal *NextForKey;
00046   K Key;
00047   V Val;
00048 public:
00049   ScopedHashTableVal(ScopedHashTableVal *nextInScope,
00050                      ScopedHashTableVal *nextForKey, const K &key, const V &val)
00051     : NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) {
00052   }
00053 
00054   const K &getKey() const { return Key; }
00055   const V &getValue() const { return Val; }
00056   V &getValue() { return Val; }
00057 
00058   ScopedHashTableVal *getNextForKey() { return NextForKey; }
00059   const ScopedHashTableVal *getNextForKey() const { return NextForKey; }
00060 public:
00061   ScopedHashTableVal *getNextInScope() { return NextInScope; }
00062 };
00063 
00064 template <typename K, typename V>
00065 class ScopedHashTableScope {
00066   /// HT - The hashtable that we are active for.
00067   ScopedHashTable<K, V> &HT;
00068 
00069   /// PrevScope - This is the scope that we are shadowing in HT.
00070   ScopedHashTableScope *PrevScope;
00071 
00072   /// LastValInScope - This is the last value that was inserted for this scope
00073   /// or null if none have been inserted yet.
00074   ScopedHashTableVal<K,V> *LastValInScope;
00075   void operator=(ScopedHashTableScope&);       // DO NOT IMPLEMENT
00076   ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT
00077 public:
00078   ScopedHashTableScope(ScopedHashTable<K, V> &HT);
00079   ~ScopedHashTableScope();
00080 
00081 private:
00082   friend class ScopedHashTable<K, V>;
00083   ScopedHashTableVal<K, V> *getLastValInScope() { return LastValInScope; }
00084   void setLastValInScope(ScopedHashTableVal<K,V> *Val) { LastValInScope = Val; }
00085 };
00086 
00087 
00088 template <typename K, typename V>
00089 class ScopedHashTableIterator {
00090   ScopedHashTableVal<K,V> *Node;
00091 public:
00092   ScopedHashTableIterator(ScopedHashTableVal<K,V> *node) : Node(node){}
00093 
00094   V &operator*() const {
00095     assert(Node && "Dereference end()");
00096     return Node->getValue();
00097   }
00098   V *operator->() const {
00099     return &Node->getValue();
00100   }
00101 
00102   bool operator==(const ScopedHashTableIterator &RHS) const {
00103     return Node == RHS.Node;
00104   }
00105   bool operator!=(const ScopedHashTableIterator &RHS) const {
00106     return Node != RHS.Node;
00107   }
00108 
00109   inline ScopedHashTableIterator& operator++() {          // Preincrement
00110     assert(Node && "incrementing past end()");
00111     Node = Node->getNextForKey();
00112     return *this;
00113   }
00114   ScopedHashTableIterator operator++(int) {        // Postincrement
00115     ScopedHashTableIterator tmp = *this; ++*this; return tmp;
00116   }
00117 };
00118 
00119 
00120 template <typename K, typename V>
00121 class ScopedHashTable {
00122   DenseMap<K, ScopedHashTableVal<K,V>*> TopLevelMap;
00123   ScopedHashTableScope<K, V> *CurScope;
00124   ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED
00125   void operator=(const ScopedHashTable&);  // NOT YET IMPLEMENTED
00126   friend class ScopedHashTableScope<K, V>;
00127 public:
00128   ScopedHashTable() : CurScope(0) {}
00129   ~ScopedHashTable() {
00130     assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!");
00131   }
00132 
00133   void insert(const K &Key, const V &Val) {
00134     assert(CurScope && "No scope active!");
00135 
00136     ScopedHashTableVal<K,V> *&KeyEntry = TopLevelMap[Key];
00137 
00138     KeyEntry = new ScopedHashTableVal<K,V>(CurScope->getLastValInScope(),
00139                                            KeyEntry, Key, Val);
00140     CurScope->setLastValInScope(KeyEntry);
00141   }
00142 
00143   typedef ScopedHashTableIterator<K, V> iterator;
00144 
00145   iterator end() { return iterator(0); }
00146 
00147   iterator begin(const K &Key) {
00148     typename DenseMap<K, ScopedHashTableVal<K,V>*>::iterator I =
00149       TopLevelMap.find(Key);
00150     if (I == TopLevelMap.end()) return end();
00151     return iterator(I->second);
00152   }
00153 };
00154 
00155 /// ScopedHashTableScope ctor - Install this as the current scope for the hash
00156 /// table.
00157 template <typename K, typename V>
00158 ScopedHashTableScope<K, V>::ScopedHashTableScope(ScopedHashTable<K, V> &ht)
00159   : HT(ht) {
00160   PrevScope = HT.CurScope;
00161   HT.CurScope = this;
00162   LastValInScope = 0;
00163 }
00164 
00165 template <typename K, typename V>
00166 ScopedHashTableScope<K, V>::~ScopedHashTableScope() {
00167   assert(HT.CurScope == this && "Scope imbalance!");
00168   HT.CurScope = PrevScope;
00169 
00170   // Pop and delete all values corresponding to this scope.
00171   while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) {
00172     // Pop this value out of the TopLevelMap.
00173     if (ThisEntry->getNextForKey() == 0) {
00174       assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry &&
00175              "Scope imbalance!");
00176       HT.TopLevelMap.erase(ThisEntry->getKey());
00177     } else {
00178       ScopedHashTableVal<K,V> *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()];
00179       assert(KeyEntry == ThisEntry && "Scope imbalance!");
00180       KeyEntry = ThisEntry->getNextForKey();
00181     }
00182 
00183     // Pop this value out of the scope.
00184     LastValInScope = ThisEntry->getNextInScope();
00185 
00186     // Delete this entry.
00187     delete ThisEntry;
00188   }
00189 }
00190 
00191 } // end namespace llvm
00192 
00193 #endif