File indexing completed on 2026-05-10 08:43:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #ifndef LLVM_ADT_SCOPEDHASHTABLE_H
0031 #define LLVM_ADT_SCOPEDHASHTABLE_H
0032
0033 #include "llvm/ADT/DenseMap.h"
0034 #include "llvm/ADT/DenseMapInfo.h"
0035 #include "llvm/Support/AllocatorBase.h"
0036 #include <cassert>
0037 #include <new>
0038
0039 namespace llvm {
0040
0041 template <typename K, typename V, typename KInfo = DenseMapInfo<K>,
0042 typename AllocatorTy = MallocAllocator>
0043 class ScopedHashTable;
0044
0045 template <typename K, typename V>
0046 class ScopedHashTableVal {
0047 ScopedHashTableVal *NextInScope;
0048 ScopedHashTableVal *NextForKey;
0049 K Key;
0050 V Val;
0051
0052 ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {}
0053
0054 public:
0055 const K &getKey() const { return Key; }
0056 const V &getValue() const { return Val; }
0057 V &getValue() { return Val; }
0058
0059 ScopedHashTableVal *getNextForKey() { return NextForKey; }
0060 const ScopedHashTableVal *getNextForKey() const { return NextForKey; }
0061 ScopedHashTableVal *getNextInScope() { return NextInScope; }
0062
0063 template <typename AllocatorTy>
0064 static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope,
0065 ScopedHashTableVal *nextForKey,
0066 const K &key, const V &val,
0067 AllocatorTy &Allocator) {
0068 ScopedHashTableVal *New = Allocator.template Allocate<ScopedHashTableVal>();
0069
0070 new (New) ScopedHashTableVal(key, val);
0071 New->NextInScope = nextInScope;
0072 New->NextForKey = nextForKey;
0073 return New;
0074 }
0075
0076 template <typename AllocatorTy> void Destroy(AllocatorTy &Allocator) {
0077
0078 this->~ScopedHashTableVal();
0079 Allocator.Deallocate(this);
0080 }
0081 };
0082
0083 template <typename K, typename V, typename KInfo = DenseMapInfo<K>,
0084 typename AllocatorTy = MallocAllocator>
0085 class ScopedHashTableScope {
0086
0087 ScopedHashTable<K, V, KInfo, AllocatorTy> &HT;
0088
0089
0090 ScopedHashTableScope *PrevScope;
0091
0092
0093
0094 ScopedHashTableVal<K, V> *LastValInScope;
0095
0096 public:
0097 ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT);
0098 ScopedHashTableScope(ScopedHashTableScope &) = delete;
0099 ScopedHashTableScope &operator=(ScopedHashTableScope &) = delete;
0100 ~ScopedHashTableScope();
0101
0102 ScopedHashTableScope *getParentScope() { return PrevScope; }
0103 const ScopedHashTableScope *getParentScope() const { return PrevScope; }
0104
0105 private:
0106 friend class ScopedHashTable<K, V, KInfo, AllocatorTy>;
0107
0108 ScopedHashTableVal<K, V> *getLastValInScope() {
0109 return LastValInScope;
0110 }
0111
0112 void setLastValInScope(ScopedHashTableVal<K, V> *Val) {
0113 LastValInScope = Val;
0114 }
0115 };
0116
0117 template <typename K, typename V, typename KInfo = DenseMapInfo<K>>
0118 class ScopedHashTableIterator {
0119 ScopedHashTableVal<K, V> *Node;
0120
0121 public:
0122 ScopedHashTableIterator(ScopedHashTableVal<K, V> *node) : Node(node) {}
0123
0124 V &operator*() const {
0125 assert(Node && "Dereference end()");
0126 return Node->getValue();
0127 }
0128 V *operator->() const {
0129 return &Node->getValue();
0130 }
0131
0132 bool operator==(const ScopedHashTableIterator &RHS) const {
0133 return Node == RHS.Node;
0134 }
0135 bool operator!=(const ScopedHashTableIterator &RHS) const {
0136 return Node != RHS.Node;
0137 }
0138
0139 inline ScopedHashTableIterator& operator++() {
0140 assert(Node && "incrementing past end()");
0141 Node = Node->getNextForKey();
0142 return *this;
0143 }
0144 ScopedHashTableIterator operator++(int) {
0145 ScopedHashTableIterator tmp = *this; ++*this; return tmp;
0146 }
0147 };
0148
0149 template <typename K, typename V, typename KInfo, typename AllocatorTy>
0150 class ScopedHashTable : detail::AllocatorHolder<AllocatorTy> {
0151 using AllocTy = detail::AllocatorHolder<AllocatorTy>;
0152
0153 public:
0154
0155
0156 using ScopeTy = ScopedHashTableScope<K, V, KInfo, AllocatorTy>;
0157 using size_type = unsigned;
0158
0159 private:
0160 friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>;
0161
0162 using ValTy = ScopedHashTableVal<K, V>;
0163
0164 DenseMap<K, ValTy*, KInfo> TopLevelMap;
0165 ScopeTy *CurScope = nullptr;
0166
0167 public:
0168 ScopedHashTable() = default;
0169 ScopedHashTable(AllocatorTy A) : AllocTy(A) {}
0170 ScopedHashTable(const ScopedHashTable &) = delete;
0171 ScopedHashTable &operator=(const ScopedHashTable &) = delete;
0172
0173 ~ScopedHashTable() {
0174 assert(!CurScope && TopLevelMap.empty() && "Scope imbalance!");
0175 }
0176
0177
0178 using AllocTy::getAllocator;
0179
0180
0181 size_type count(const K &Key) const {
0182 return TopLevelMap.count(Key);
0183 }
0184
0185 V lookup(const K &Key) const {
0186 auto I = TopLevelMap.find(Key);
0187 if (I != TopLevelMap.end())
0188 return I->second->getValue();
0189
0190 return V();
0191 }
0192
0193 void insert(const K &Key, const V &Val) {
0194 insertIntoScope(CurScope, Key, Val);
0195 }
0196
0197 using iterator = ScopedHashTableIterator<K, V, KInfo>;
0198
0199 iterator end() { return iterator(nullptr); }
0200
0201 iterator begin(const K &Key) {
0202 typename DenseMap<K, ValTy*, KInfo>::iterator I =
0203 TopLevelMap.find(Key);
0204 if (I == TopLevelMap.end()) return end();
0205 return iterator(I->second);
0206 }
0207
0208 ScopeTy *getCurScope() { return CurScope; }
0209 const ScopeTy *getCurScope() const { return CurScope; }
0210
0211
0212
0213
0214
0215 void insertIntoScope(ScopeTy *S, const K &Key, const V &Val) {
0216 assert(S && "No scope active!");
0217 ScopedHashTableVal<K, V> *&KeyEntry = TopLevelMap[Key];
0218 KeyEntry = ValTy::Create(S->getLastValInScope(), KeyEntry, Key, Val,
0219 getAllocator());
0220 S->setLastValInScope(KeyEntry);
0221 }
0222 };
0223
0224
0225
0226 template <typename K, typename V, typename KInfo, typename Allocator>
0227 ScopedHashTableScope<K, V, KInfo, Allocator>::
0228 ScopedHashTableScope(ScopedHashTable<K, V, KInfo, Allocator> &ht) : HT(ht) {
0229 PrevScope = HT.CurScope;
0230 HT.CurScope = this;
0231 LastValInScope = nullptr;
0232 }
0233
0234 template <typename K, typename V, typename KInfo, typename Allocator>
0235 ScopedHashTableScope<K, V, KInfo, Allocator>::~ScopedHashTableScope() {
0236 assert(HT.CurScope == this && "Scope imbalance!");
0237 HT.CurScope = PrevScope;
0238
0239
0240 while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) {
0241
0242 if (!ThisEntry->getNextForKey()) {
0243 assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry &&
0244 "Scope imbalance!");
0245 HT.TopLevelMap.erase(ThisEntry->getKey());
0246 } else {
0247 ScopedHashTableVal<K, V> *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()];
0248 assert(KeyEntry == ThisEntry && "Scope imbalance!");
0249 KeyEntry = ThisEntry->getNextForKey();
0250 }
0251
0252
0253 LastValInScope = ThisEntry->getNextInScope();
0254
0255
0256 ThisEntry->Destroy(HT.getAllocator());
0257 }
0258 }
0259
0260 }
0261
0262 #endif