xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/ADT/DenseMapInfo.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 //===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines DenseMapInfo traits for DenseMap.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_ADT_DENSEMAPINFO_H
14 #define LLVM_ADT_DENSEMAPINFO_H
15 
16 #include "llvm/ADT/APInt.h"
17 #include "llvm/ADT/APSInt.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/Hashing.h"
20 #include "llvm/ADT/StringRef.h"
21 #include <cassert>
22 #include <cstddef>
23 #include <cstdint>
24 #include <utility>
25 
26 namespace llvm {
27 
28 namespace detail {
29 
30 /// Simplistic combination of 32-bit hash values into 32-bit hash values.
combineHashValue(unsigned a,unsigned b)31 static inline unsigned combineHashValue(unsigned a, unsigned b) {
32   uint64_t key = (uint64_t)a << 32 | (uint64_t)b;
33   key += ~(key << 32);
34   key ^= (key >> 22);
35   key += ~(key << 13);
36   key ^= (key >> 8);
37   key += (key << 3);
38   key ^= (key >> 15);
39   key += ~(key << 27);
40   key ^= (key >> 31);
41   return (unsigned)key;
42 }
43 
44 } // end namespace detail
45 
46 template<typename T>
47 struct DenseMapInfo {
48   //static inline T getEmptyKey();
49   //static inline T getTombstoneKey();
50   //static unsigned getHashValue(const T &Val);
51   //static bool isEqual(const T &LHS, const T &RHS);
52 };
53 
54 // Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
55 // that are aligned to alignof(T) bytes, but try to avoid requiring T to be
56 // complete. This allows clients to instantiate DenseMap<T*, ...> with forward
57 // declared key types. Assume that no pointer key type requires more than 4096
58 // bytes of alignment.
59 template<typename T>
60 struct DenseMapInfo<T*> {
61   // The following should hold, but it would require T to be complete:
62   // static_assert(alignof(T) <= (1 << Log2MaxAlign),
63   //               "DenseMap does not support pointer keys requiring more than "
64   //               "Log2MaxAlign bits of alignment");
65   static constexpr uintptr_t Log2MaxAlign = 12;
66 
67   static inline T* getEmptyKey() {
68     uintptr_t Val = static_cast<uintptr_t>(-1);
69     Val <<= Log2MaxAlign;
70     return reinterpret_cast<T*>(Val);
71   }
72 
73   static inline T* getTombstoneKey() {
74     uintptr_t Val = static_cast<uintptr_t>(-2);
75     Val <<= Log2MaxAlign;
76     return reinterpret_cast<T*>(Val);
77   }
78 
79   static unsigned getHashValue(const T *PtrVal) {
80     return (unsigned((uintptr_t)PtrVal) >> 4) ^
81            (unsigned((uintptr_t)PtrVal) >> 9);
82   }
83 
84   static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
85 };
86 
87 // Provide DenseMapInfo for chars.
88 template<> struct DenseMapInfo<char> {
89   static inline char getEmptyKey() { return ~0; }
90   static inline char getTombstoneKey() { return ~0 - 1; }
91   static unsigned getHashValue(const char& Val) { return Val * 37U; }
92 
93   static bool isEqual(const char &LHS, const char &RHS) {
94     return LHS == RHS;
95   }
96 };
97 
98 // Provide DenseMapInfo for unsigned chars.
99 template <> struct DenseMapInfo<unsigned char> {
100   static inline unsigned char getEmptyKey() { return ~0; }
101   static inline unsigned char getTombstoneKey() { return ~0 - 1; }
102   static unsigned getHashValue(const unsigned char &Val) { return Val * 37U; }
103 
104   static bool isEqual(const unsigned char &LHS, const unsigned char &RHS) {
105     return LHS == RHS;
106   }
107 };
108 
109 // Provide DenseMapInfo for unsigned shorts.
110 template <> struct DenseMapInfo<unsigned short> {
111   static inline unsigned short getEmptyKey() { return 0xFFFF; }
112   static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
113   static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
114 
115   static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
116     return LHS == RHS;
117   }
118 };
119 
120 // Provide DenseMapInfo for unsigned ints.
121 template<> struct DenseMapInfo<unsigned> {
122   static inline unsigned getEmptyKey() { return ~0U; }
123   static inline unsigned getTombstoneKey() { return ~0U - 1; }
124   static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
125 
126   static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
127     return LHS == RHS;
128   }
129 };
130 
131 // Provide DenseMapInfo for unsigned longs.
132 template<> struct DenseMapInfo<unsigned long> {
133   static inline unsigned long getEmptyKey() { return ~0UL; }
134   static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
135 
136   static unsigned getHashValue(const unsigned long& Val) {
137     return (unsigned)(Val * 37UL);
138   }
139 
140   static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
141     return LHS == RHS;
142   }
143 };
144 
145 // Provide DenseMapInfo for unsigned long longs.
146 template<> struct DenseMapInfo<unsigned long long> {
147   static inline unsigned long long getEmptyKey() { return ~0ULL; }
148   static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
149 
150   static unsigned getHashValue(const unsigned long long& Val) {
151     return (unsigned)(Val * 37ULL);
152   }
153 
154   static bool isEqual(const unsigned long long& LHS,
155                       const unsigned long long& RHS) {
156     return LHS == RHS;
157   }
158 };
159 
160 // Provide DenseMapInfo for shorts.
161 template <> struct DenseMapInfo<short> {
162   static inline short getEmptyKey() { return 0x7FFF; }
163   static inline short getTombstoneKey() { return -0x7FFF - 1; }
164   static unsigned getHashValue(const short &Val) { return Val * 37U; }
165   static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
166 };
167 
168 // Provide DenseMapInfo for ints.
169 template<> struct DenseMapInfo<int> {
170   static inline int getEmptyKey() { return 0x7fffffff; }
171   static inline int getTombstoneKey() { return -0x7fffffff - 1; }
172   static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
173 
174   static bool isEqual(const int& LHS, const int& RHS) {
175     return LHS == RHS;
176   }
177 };
178 
179 // Provide DenseMapInfo for longs.
180 template<> struct DenseMapInfo<long> {
181   static inline long getEmptyKey() {
182     return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
183   }
184 
185   static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
186 
187   static unsigned getHashValue(const long& Val) {
188     return (unsigned)(Val * 37UL);
189   }
190 
191   static bool isEqual(const long& LHS, const long& RHS) {
192     return LHS == RHS;
193   }
194 };
195 
196 // Provide DenseMapInfo for long longs.
197 template<> struct DenseMapInfo<long long> {
198   static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
199   static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
200 
201   static unsigned getHashValue(const long long& Val) {
202     return (unsigned)(Val * 37ULL);
203   }
204 
205   static bool isEqual(const long long& LHS,
206                       const long long& RHS) {
207     return LHS == RHS;
208   }
209 };
210 
211 // Provide DenseMapInfo for all pairs whose members have info.
212 template<typename T, typename U>
213 struct DenseMapInfo<std::pair<T, U>> {
214   using Pair = std::pair<T, U>;
215   using FirstInfo = DenseMapInfo<T>;
216   using SecondInfo = DenseMapInfo<U>;
217 
218   static inline Pair getEmptyKey() {
219     return std::make_pair(FirstInfo::getEmptyKey(),
220                           SecondInfo::getEmptyKey());
221   }
222 
223   static inline Pair getTombstoneKey() {
224     return std::make_pair(FirstInfo::getTombstoneKey(),
225                           SecondInfo::getTombstoneKey());
226   }
227 
228   static unsigned getHashValue(const Pair& PairVal) {
229     return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
230                                     SecondInfo::getHashValue(PairVal.second));
231   }
232 
233   static bool isEqual(const Pair &LHS, const Pair &RHS) {
234     return FirstInfo::isEqual(LHS.first, RHS.first) &&
235            SecondInfo::isEqual(LHS.second, RHS.second);
236   }
237 };
238 
239 // Provide DenseMapInfo for all tuples whose members have info.
240 template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
241   using Tuple = std::tuple<Ts...>;
242 
243   static inline Tuple getEmptyKey() {
244     return Tuple(DenseMapInfo<Ts>::getEmptyKey()...);
245   }
246 
247   static inline Tuple getTombstoneKey() {
248     return Tuple(DenseMapInfo<Ts>::getTombstoneKey()...);
249   }
250 
251   template <unsigned I>
252   static unsigned getHashValueImpl(const Tuple &values, std::false_type) {
253     using EltType = typename std::tuple_element<I, Tuple>::type;
254     std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
255     return detail::combineHashValue(
256         DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
257         getHashValueImpl<I + 1>(values, atEnd));
258   }
259 
260   template <unsigned I>
261   static unsigned getHashValueImpl(const Tuple &, std::true_type) {
262     return 0;
263   }
264 
265   static unsigned getHashValue(const std::tuple<Ts...> &values) {
266     std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
267     return getHashValueImpl<0>(values, atEnd);
268   }
269 
270   template <unsigned I>
271   static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::false_type) {
272     using EltType = typename std::tuple_element<I, Tuple>::type;
273     std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
274     return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), std::get<I>(rhs)) &&
275            isEqualImpl<I + 1>(lhs, rhs, atEnd);
276   }
277 
278   template <unsigned I>
279   static bool isEqualImpl(const Tuple &, const Tuple &, std::true_type) {
280     return true;
281   }
282 
283   static bool isEqual(const Tuple &lhs, const Tuple &rhs) {
284     std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
285     return isEqualImpl<0>(lhs, rhs, atEnd);
286   }
287 };
288 
289 // Provide DenseMapInfo for StringRefs.
290 template <> struct DenseMapInfo<StringRef> {
291   static inline StringRef getEmptyKey() {
292     return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
293                      0);
294   }
295 
296   static inline StringRef getTombstoneKey() {
297     return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
298                      0);
299   }
300 
301   static unsigned getHashValue(StringRef Val) {
302     assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
303     assert(Val.data() != getTombstoneKey().data() &&
304            "Cannot hash the tombstone key!");
305     return (unsigned)(hash_value(Val));
306   }
307 
308   static bool isEqual(StringRef LHS, StringRef RHS) {
309     if (RHS.data() == getEmptyKey().data())
310       return LHS.data() == getEmptyKey().data();
311     if (RHS.data() == getTombstoneKey().data())
312       return LHS.data() == getTombstoneKey().data();
313     return LHS == RHS;
314   }
315 };
316 
317 // Provide DenseMapInfo for ArrayRefs.
318 template <typename T> struct DenseMapInfo<ArrayRef<T>> {
319   static inline ArrayRef<T> getEmptyKey() {
320     return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
321                        size_t(0));
322   }
323 
324   static inline ArrayRef<T> getTombstoneKey() {
325     return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
326                        size_t(0));
327   }
328 
329   static unsigned getHashValue(ArrayRef<T> Val) {
330     assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
331     assert(Val.data() != getTombstoneKey().data() &&
332            "Cannot hash the tombstone key!");
333     return (unsigned)(hash_value(Val));
334   }
335 
336   static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
337     if (RHS.data() == getEmptyKey().data())
338       return LHS.data() == getEmptyKey().data();
339     if (RHS.data() == getTombstoneKey().data())
340       return LHS.data() == getTombstoneKey().data();
341     return LHS == RHS;
342   }
343 };
344 
345 template <> struct DenseMapInfo<hash_code> {
346   static inline hash_code getEmptyKey() { return hash_code(-1); }
347   static inline hash_code getTombstoneKey() { return hash_code(-2); }
348   static unsigned getHashValue(hash_code val) { return val; }
349   static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
350 };
351 
352 /// Provide DenseMapInfo for APInt.
353 template <> struct DenseMapInfo<APInt> {
354   static inline APInt getEmptyKey() {
355     APInt V(nullptr, 0);
356     V.U.VAL = 0;
357     return V;
358   }
359 
360   static inline APInt getTombstoneKey() {
361     APInt V(nullptr, 0);
362     V.U.VAL = 1;
363     return V;
364   }
365 
366   static unsigned getHashValue(const APInt &Key) {
367     return static_cast<unsigned>(hash_value(Key));
368   }
369 
370   static bool isEqual(const APInt &LHS, const APInt &RHS) {
371     return LHS.getBitWidth() == RHS.getBitWidth() && LHS == RHS;
372   }
373 };
374 
375 /// Provide DenseMapInfo for APSInt, using the DenseMapInfo for APInt.
376 template <> struct DenseMapInfo<APSInt> {
377   static inline APSInt getEmptyKey() {
378     return APSInt(DenseMapInfo<APInt>::getEmptyKey());
379   }
380 
381   static inline APSInt getTombstoneKey() {
382     return APSInt(DenseMapInfo<APInt>::getTombstoneKey());
383   }
384 
385   static unsigned getHashValue(const APSInt &Key) {
386     return static_cast<unsigned>(hash_value(Key));
387   }
388 
389   static bool isEqual(const APSInt &LHS, const APSInt &RHS) {
390     return LHS.getBitWidth() == RHS.getBitWidth() &&
391            LHS.isUnsigned() == RHS.isUnsigned() && LHS == RHS;
392   }
393 };
394 
395 } // end namespace llvm
396 
397 #endif // LLVM_ADT_DENSEMAPINFO_H
398