1 | //===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file defines DenseMapInfo traits for DenseMap. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_ADT_DENSEMAPINFO_H |
15 | #define LLVM_ADT_DENSEMAPINFO_H |
16 | |
17 | #include "llvm/ADT/ArrayRef.h" |
18 | #include "llvm/ADT/Hashing.h" |
19 | #include "llvm/ADT/StringRef.h" |
20 | #include "llvm/Support/PointerLikeTypeTraits.h" |
21 | #include <cassert> |
22 | #include <cstddef> |
23 | #include <cstdint> |
24 | #include <utility> |
25 | |
26 | namespace llvm { |
27 | |
28 | template<typename T> |
29 | struct DenseMapInfo { |
30 | //static inline T getEmptyKey(); |
31 | //static inline T getTombstoneKey(); |
32 | //static unsigned getHashValue(const T &Val); |
33 | //static bool isEqual(const T &LHS, const T &RHS); |
34 | }; |
35 | |
36 | // Provide DenseMapInfo for all pointers. |
37 | template<typename T> |
38 | struct DenseMapInfo<T*> { |
39 | static inline T* getEmptyKey() { |
40 | uintptr_t Val = static_cast<uintptr_t>(-1); |
41 | Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable; |
42 | return reinterpret_cast<T*>(Val); |
43 | } |
44 | |
45 | static inline T* getTombstoneKey() { |
46 | uintptr_t Val = static_cast<uintptr_t>(-2); |
47 | Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable; |
48 | return reinterpret_cast<T*>(Val); |
49 | } |
50 | |
51 | static unsigned getHashValue(const T *PtrVal) { |
52 | return (unsigned((uintptr_t)PtrVal) >> 4) ^ |
53 | (unsigned((uintptr_t)PtrVal) >> 9); |
54 | } |
55 | |
56 | static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } |
57 | }; |
58 | |
59 | // Provide DenseMapInfo for chars. |
60 | template<> struct DenseMapInfo<char> { |
61 | static inline char getEmptyKey() { return ~0; } |
62 | static inline char getTombstoneKey() { return ~0 - 1; } |
63 | static unsigned getHashValue(const char& Val) { return Val * 37U; } |
64 | |
65 | static bool isEqual(const char &LHS, const char &RHS) { |
66 | return LHS == RHS; |
67 | } |
68 | }; |
69 | |
70 | // Provide DenseMapInfo for unsigned shorts. |
71 | template <> struct DenseMapInfo<unsigned short> { |
72 | static inline unsigned short getEmptyKey() { return 0xFFFF; } |
73 | static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; } |
74 | static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; } |
75 | |
76 | static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) { |
77 | return LHS == RHS; |
78 | } |
79 | }; |
80 | |
81 | // Provide DenseMapInfo for unsigned ints. |
82 | template<> struct DenseMapInfo<unsigned> { |
83 | static inline unsigned getEmptyKey() { return ~0U; } |
84 | static inline unsigned getTombstoneKey() { return ~0U - 1; } |
85 | static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } |
86 | |
87 | static bool isEqual(const unsigned& LHS, const unsigned& RHS) { |
88 | return LHS == RHS; |
89 | } |
90 | }; |
91 | |
92 | // Provide DenseMapInfo for unsigned longs. |
93 | template<> struct DenseMapInfo<unsigned long> { |
94 | static inline unsigned long getEmptyKey() { return ~0UL; } |
95 | static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } |
96 | |
97 | static unsigned getHashValue(const unsigned long& Val) { |
98 | return (unsigned)(Val * 37UL); |
99 | } |
100 | |
101 | static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { |
102 | return LHS == RHS; |
103 | } |
104 | }; |
105 | |
106 | // Provide DenseMapInfo for unsigned long longs. |
107 | template<> struct DenseMapInfo<unsigned long long> { |
108 | static inline unsigned long long getEmptyKey() { return ~0ULL; } |
109 | static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } |
110 | |
111 | static unsigned getHashValue(const unsigned long long& Val) { |
112 | return (unsigned)(Val * 37ULL); |
113 | } |
114 | |
115 | static bool isEqual(const unsigned long long& LHS, |
116 | const unsigned long long& RHS) { |
117 | return LHS == RHS; |
118 | } |
119 | }; |
120 | |
121 | // Provide DenseMapInfo for shorts. |
122 | template <> struct DenseMapInfo<short> { |
123 | static inline short getEmptyKey() { return 0x7FFF; } |
124 | static inline short getTombstoneKey() { return -0x7FFF - 1; } |
125 | static unsigned getHashValue(const short &Val) { return Val * 37U; } |
126 | static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; } |
127 | }; |
128 | |
129 | // Provide DenseMapInfo for ints. |
130 | template<> struct DenseMapInfo<int> { |
131 | static inline int getEmptyKey() { return 0x7fffffff; } |
132 | static inline int getTombstoneKey() { return -0x7fffffff - 1; } |
133 | static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } |
134 | |
135 | static bool isEqual(const int& LHS, const int& RHS) { |
136 | return LHS == RHS; |
137 | } |
138 | }; |
139 | |
140 | // Provide DenseMapInfo for longs. |
141 | template<> struct DenseMapInfo<long> { |
142 | static inline long getEmptyKey() { |
143 | return (1UL << (sizeof(long) * 8 - 1)) - 1UL; |
144 | } |
145 | |
146 | static inline long getTombstoneKey() { return getEmptyKey() - 1L; } |
147 | |
148 | static unsigned getHashValue(const long& Val) { |
149 | return (unsigned)(Val * 37UL); |
150 | } |
151 | |
152 | static bool isEqual(const long& LHS, const long& RHS) { |
153 | return LHS == RHS; |
154 | } |
155 | }; |
156 | |
157 | // Provide DenseMapInfo for long longs. |
158 | template<> struct DenseMapInfo<long long> { |
159 | static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } |
160 | static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } |
161 | |
162 | static unsigned getHashValue(const long long& Val) { |
163 | return (unsigned)(Val * 37ULL); |
164 | } |
165 | |
166 | static bool isEqual(const long long& LHS, |
167 | const long long& RHS) { |
168 | return LHS == RHS; |
169 | } |
170 | }; |
171 | |
172 | // Provide DenseMapInfo for all pairs whose members have info. |
173 | template<typename T, typename U> |
174 | struct DenseMapInfo<std::pair<T, U>> { |
175 | using Pair = std::pair<T, U>; |
176 | using FirstInfo = DenseMapInfo<T>; |
177 | using SecondInfo = DenseMapInfo<U>; |
178 | |
179 | static inline Pair getEmptyKey() { |
180 | return std::make_pair(FirstInfo::getEmptyKey(), |
181 | SecondInfo::getEmptyKey()); |
182 | } |
183 | |
184 | static inline Pair getTombstoneKey() { |
185 | return std::make_pair(FirstInfo::getTombstoneKey(), |
186 | SecondInfo::getTombstoneKey()); |
187 | } |
188 | |
189 | static unsigned getHashValue(const Pair& PairVal) { |
190 | uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 |
191 | | (uint64_t)SecondInfo::getHashValue(PairVal.second); |
192 | key += ~(key << 32); |
193 | key ^= (key >> 22); |
194 | key += ~(key << 13); |
195 | key ^= (key >> 8); |
196 | key += (key << 3); |
197 | key ^= (key >> 15); |
198 | key += ~(key << 27); |
199 | key ^= (key >> 31); |
200 | return (unsigned)key; |
201 | } |
202 | |
203 | static bool isEqual(const Pair &LHS, const Pair &RHS) { |
204 | return FirstInfo::isEqual(LHS.first, RHS.first) && |
205 | SecondInfo::isEqual(LHS.second, RHS.second); |
206 | } |
207 | }; |
208 | |
209 | // Provide DenseMapInfo for StringRefs. |
210 | template <> struct DenseMapInfo<StringRef> { |
211 | static inline StringRef getEmptyKey() { |
212 | return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)), |
213 | 0); |
214 | } |
215 | |
216 | static inline StringRef getTombstoneKey() { |
217 | return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)), |
218 | 0); |
219 | } |
220 | |
221 | static unsigned getHashValue(StringRef Val) { |
222 | assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!" ); |
223 | assert(Val.data() != getTombstoneKey().data() && |
224 | "Cannot hash the tombstone key!" ); |
225 | return (unsigned)(hash_value(Val)); |
226 | } |
227 | |
228 | static bool isEqual(StringRef LHS, StringRef RHS) { |
229 | if (RHS.data() == getEmptyKey().data()) |
230 | return LHS.data() == getEmptyKey().data(); |
231 | if (RHS.data() == getTombstoneKey().data()) |
232 | return LHS.data() == getTombstoneKey().data(); |
233 | return LHS == RHS; |
234 | } |
235 | }; |
236 | |
237 | // Provide DenseMapInfo for ArrayRefs. |
238 | template <typename T> struct DenseMapInfo<ArrayRef<T>> { |
239 | static inline ArrayRef<T> getEmptyKey() { |
240 | return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)), |
241 | size_t(0)); |
242 | } |
243 | |
244 | static inline ArrayRef<T> getTombstoneKey() { |
245 | return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)), |
246 | size_t(0)); |
247 | } |
248 | |
249 | static unsigned getHashValue(ArrayRef<T> Val) { |
250 | assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!" ); |
251 | assert(Val.data() != getTombstoneKey().data() && |
252 | "Cannot hash the tombstone key!" ); |
253 | return (unsigned)(hash_value(Val)); |
254 | } |
255 | |
256 | static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) { |
257 | if (RHS.data() == getEmptyKey().data()) |
258 | return LHS.data() == getEmptyKey().data(); |
259 | if (RHS.data() == getTombstoneKey().data()) |
260 | return LHS.data() == getTombstoneKey().data(); |
261 | return LHS == RHS; |
262 | } |
263 | }; |
264 | |
265 | template <> struct DenseMapInfo<hash_code> { |
266 | static inline hash_code getEmptyKey() { return hash_code(-1); } |
267 | static inline hash_code getTombstoneKey() { return hash_code(-2); } |
268 | static unsigned getHashValue(hash_code val) { return val; } |
269 | static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; } |
270 | }; |
271 | |
272 | } // end namespace llvm |
273 | |
274 | #endif // LLVM_ADT_DENSEMAPINFO_H |
275 | |