LLVM API Documentation
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