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
26namespace llvm {
27
28namespace detail {
29
30/// Simplistic combination of 32-bit hash values into 32-bit hash values.
31static 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
46template<typename T>
47struct 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.
59template<typename T>
60struct 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.
88template<> 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.
99template <> 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.
110template <> 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.
121template<> 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.
132template<> 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.
146template<> 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.
161template <> 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.
169template<> 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.
180template<> 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.
197template<> 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.
212template<typename T, typename U>
213struct 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.
240template <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.
290template <> 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.
318template <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
345template <> 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.
353template <> 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.
376template <> 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