1 //===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines DenseMapInfo traits for DenseMap.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_ADT_DENSEMAPINFO_H
14 #define LLVM_ADT_DENSEMAPINFO_H
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/Hashing.h"
18 #include "llvm/ADT/StringRef.h"
28 /// Simplistic combination of 32-bit hash values into 32-bit hash values.
29 static inline unsigned combineHashValue(unsigned a, unsigned b) {
30 uint64_t key = (uint64_t)a << 32 | (uint64_t)b;
42 } // end namespace detail
46 //static inline T getEmptyKey();
47 //static inline T getTombstoneKey();
48 //static unsigned getHashValue(const T &Val);
49 //static bool isEqual(const T &LHS, const T &RHS);
52 // Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
53 // that are aligned to alignof(T) bytes, but try to avoid requiring T to be
54 // complete. This allows clients to instantiate DenseMap<T*, ...> with forward
55 // declared key types. Assume that no pointer key type requires more than 4096
56 // bytes of alignment.
58 struct DenseMapInfo<T*> {
59 // The following should hold, but it would require T to be complete:
60 // static_assert(alignof(T) <= (1 << Log2MaxAlign),
61 // "DenseMap does not support pointer keys requiring more than "
62 // "Log2MaxAlign bits of alignment");
63 static constexpr uintptr_t Log2MaxAlign = 12;
65 static inline T* getEmptyKey() {
66 uintptr_t Val = static_cast<uintptr_t>(-1);
68 return reinterpret_cast<T*>(Val);
71 static inline T* getTombstoneKey() {
72 uintptr_t Val = static_cast<uintptr_t>(-2);
74 return reinterpret_cast<T*>(Val);
77 static unsigned getHashValue(const T *PtrVal) {
78 return (unsigned((uintptr_t)PtrVal) >> 4) ^
79 (unsigned((uintptr_t)PtrVal) >> 9);
82 static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
85 // Provide DenseMapInfo for chars.
86 template<> struct DenseMapInfo<char> {
87 static inline char getEmptyKey() { return ~0; }
88 static inline char getTombstoneKey() { return ~0 - 1; }
89 static unsigned getHashValue(const char& Val) { return Val * 37U; }
91 static bool isEqual(const char &LHS, const char &RHS) {
96 // Provide DenseMapInfo for unsigned chars.
97 template <> struct DenseMapInfo<unsigned char> {
98 static inline unsigned char getEmptyKey() { return ~0; }
99 static inline unsigned char getTombstoneKey() { return ~0 - 1; }
100 static unsigned getHashValue(const unsigned char &Val) { return Val * 37U; }
102 static bool isEqual(const unsigned char &LHS, const unsigned char &RHS) {
107 // Provide DenseMapInfo for unsigned shorts.
108 template <> struct DenseMapInfo<unsigned short> {
109 static inline unsigned short getEmptyKey() { return 0xFFFF; }
110 static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
111 static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
113 static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
118 // Provide DenseMapInfo for unsigned ints.
119 template<> struct DenseMapInfo<unsigned> {
120 static inline unsigned getEmptyKey() { return ~0U; }
121 static inline unsigned getTombstoneKey() { return ~0U - 1; }
122 static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
124 static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
129 // Provide DenseMapInfo for unsigned longs.
130 template<> struct DenseMapInfo<unsigned long> {
131 static inline unsigned long getEmptyKey() { return ~0UL; }
132 static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
134 static unsigned getHashValue(const unsigned long& Val) {
135 return (unsigned)(Val * 37UL);
138 static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
143 // Provide DenseMapInfo for unsigned long longs.
144 template<> struct DenseMapInfo<unsigned long long> {
145 static inline unsigned long long getEmptyKey() { return ~0ULL; }
146 static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
148 static unsigned getHashValue(const unsigned long long& Val) {
149 return (unsigned)(Val * 37ULL);
152 static bool isEqual(const unsigned long long& LHS,
153 const unsigned long long& RHS) {
158 // Provide DenseMapInfo for shorts.
159 template <> struct DenseMapInfo<short> {
160 static inline short getEmptyKey() { return 0x7FFF; }
161 static inline short getTombstoneKey() { return -0x7FFF - 1; }
162 static unsigned getHashValue(const short &Val) { return Val * 37U; }
163 static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
166 // Provide DenseMapInfo for ints.
167 template<> struct DenseMapInfo<int> {
168 static inline int getEmptyKey() { return 0x7fffffff; }
169 static inline int getTombstoneKey() { return -0x7fffffff - 1; }
170 static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
172 static bool isEqual(const int& LHS, const int& RHS) {
177 // Provide DenseMapInfo for longs.
178 template<> struct DenseMapInfo<long> {
179 static inline long getEmptyKey() {
180 return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
183 static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
185 static unsigned getHashValue(const long& Val) {
186 return (unsigned)(Val * 37UL);
189 static bool isEqual(const long& LHS, const long& RHS) {
194 // Provide DenseMapInfo for long longs.
195 template<> struct DenseMapInfo<long long> {
196 static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
197 static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
199 static unsigned getHashValue(const long long& Val) {
200 return (unsigned)(Val * 37ULL);
203 static bool isEqual(const long long& LHS,
204 const long long& RHS) {
209 // Provide DenseMapInfo for all pairs whose members have info.
210 template<typename T, typename U>
211 struct DenseMapInfo<std::pair<T, U>> {
212 using Pair = std::pair<T, U>;
213 using FirstInfo = DenseMapInfo<T>;
214 using SecondInfo = DenseMapInfo<U>;
216 static inline Pair getEmptyKey() {
217 return std::make_pair(FirstInfo::getEmptyKey(),
218 SecondInfo::getEmptyKey());
221 static inline Pair getTombstoneKey() {
222 return std::make_pair(FirstInfo::getTombstoneKey(),
223 SecondInfo::getTombstoneKey());
226 static unsigned getHashValue(const Pair& PairVal) {
227 return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
228 SecondInfo::getHashValue(PairVal.second));
231 static bool isEqual(const Pair &LHS, const Pair &RHS) {
232 return FirstInfo::isEqual(LHS.first, RHS.first) &&
233 SecondInfo::isEqual(LHS.second, RHS.second);
237 // Provide DenseMapInfo for all tuples whose members have info.
238 template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
239 using Tuple = std::tuple<Ts...>;
241 static inline Tuple getEmptyKey() {
242 return Tuple(DenseMapInfo<Ts>::getEmptyKey()...);
245 static inline Tuple getTombstoneKey() {
246 return Tuple(DenseMapInfo<Ts>::getTombstoneKey()...);
249 template <unsigned I>
250 static unsigned getHashValueImpl(const Tuple &values, std::false_type) {
251 using EltType = typename std::tuple_element<I, Tuple>::type;
252 std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
253 return detail::combineHashValue(
254 DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
255 getHashValueImpl<I + 1>(values, atEnd));
258 template <unsigned I>
259 static unsigned getHashValueImpl(const Tuple &values, std::true_type) {
263 static unsigned getHashValue(const std::tuple<Ts...> &values) {
264 std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
265 return getHashValueImpl<0>(values, atEnd);
268 template <unsigned I>
269 static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::false_type) {
270 using EltType = typename std::tuple_element<I, Tuple>::type;
271 std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
272 return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), std::get<I>(rhs)) &&
273 isEqualImpl<I + 1>(lhs, rhs, atEnd);
276 template <unsigned I>
277 static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::true_type) {
281 static bool isEqual(const Tuple &lhs, const Tuple &rhs) {
282 std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
283 return isEqualImpl<0>(lhs, rhs, atEnd);
287 // Provide DenseMapInfo for StringRefs.
288 template <> struct DenseMapInfo<StringRef> {
289 static inline StringRef getEmptyKey() {
290 return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
294 static inline StringRef getTombstoneKey() {
295 return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
299 static unsigned getHashValue(StringRef Val) {
300 assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
301 assert(Val.data() != getTombstoneKey().data() &&
302 "Cannot hash the tombstone key!");
303 return (unsigned)(hash_value(Val));
306 static bool isEqual(StringRef LHS, StringRef RHS) {
307 if (RHS.data() == getEmptyKey().data())
308 return LHS.data() == getEmptyKey().data();
309 if (RHS.data() == getTombstoneKey().data())
310 return LHS.data() == getTombstoneKey().data();
315 // Provide DenseMapInfo for ArrayRefs.
316 template <typename T> struct DenseMapInfo<ArrayRef<T>> {
317 static inline ArrayRef<T> getEmptyKey() {
318 return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
322 static inline ArrayRef<T> getTombstoneKey() {
323 return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
327 static unsigned getHashValue(ArrayRef<T> Val) {
328 assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
329 assert(Val.data() != getTombstoneKey().data() &&
330 "Cannot hash the tombstone key!");
331 return (unsigned)(hash_value(Val));
334 static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
335 if (RHS.data() == getEmptyKey().data())
336 return LHS.data() == getEmptyKey().data();
337 if (RHS.data() == getTombstoneKey().data())
338 return LHS.data() == getTombstoneKey().data();
343 template <> struct DenseMapInfo<hash_code> {
344 static inline hash_code getEmptyKey() { return hash_code(-1); }
345 static inline hash_code getTombstoneKey() { return hash_code(-2); }
346 static unsigned getHashValue(hash_code val) { return val; }
347 static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
350 } // end namespace llvm
352 #endif // LLVM_ADT_DENSEMAPINFO_H