xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_dense_map_info.h (revision 4824e7fd18a1223177218d4aec1b3c6c5c4a444e)
1349cc55cSDimitry Andric //===- sanitizer_dense_map_info.h - Type traits for DenseMap ----*- C++ -*-===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric 
9349cc55cSDimitry Andric #ifndef SANITIZER_DENSE_MAP_INFO_H
10349cc55cSDimitry Andric #define SANITIZER_DENSE_MAP_INFO_H
11349cc55cSDimitry Andric 
12349cc55cSDimitry Andric #include "sanitizer_common.h"
13349cc55cSDimitry Andric #include "sanitizer_internal_defs.h"
14349cc55cSDimitry Andric #include "sanitizer_type_traits.h"
15349cc55cSDimitry Andric 
16349cc55cSDimitry Andric namespace __sanitizer {
17349cc55cSDimitry Andric 
18349cc55cSDimitry Andric namespace detail {
19349cc55cSDimitry Andric 
20349cc55cSDimitry Andric /// Simplistic combination of 32-bit hash values into 32-bit hash values.
combineHashValue(unsigned a,unsigned b)21*4824e7fdSDimitry Andric static constexpr unsigned combineHashValue(unsigned a, unsigned b) {
22349cc55cSDimitry Andric   u64 key = (u64)a << 32 | (u64)b;
23349cc55cSDimitry Andric   key += ~(key << 32);
24349cc55cSDimitry Andric   key ^= (key >> 22);
25349cc55cSDimitry Andric   key += ~(key << 13);
26349cc55cSDimitry Andric   key ^= (key >> 8);
27349cc55cSDimitry Andric   key += (key << 3);
28349cc55cSDimitry Andric   key ^= (key >> 15);
29349cc55cSDimitry Andric   key += ~(key << 27);
30349cc55cSDimitry Andric   key ^= (key >> 31);
31349cc55cSDimitry Andric   return (unsigned)key;
32349cc55cSDimitry Andric }
33349cc55cSDimitry Andric 
34349cc55cSDimitry Andric // We extend a pair to allow users to override the bucket type with their own
35349cc55cSDimitry Andric // implementation without requiring two members.
36349cc55cSDimitry Andric template <typename KeyT, typename ValueT>
37349cc55cSDimitry Andric struct DenseMapPair {
38349cc55cSDimitry Andric   KeyT first = {};
39349cc55cSDimitry Andric   ValueT second = {};
40*4824e7fdSDimitry Andric   constexpr DenseMapPair() = default;
DenseMapPairDenseMapPair41*4824e7fdSDimitry Andric   constexpr DenseMapPair(const KeyT &f, const ValueT &s)
42*4824e7fdSDimitry Andric       : first(f), second(s) {}
43349cc55cSDimitry Andric 
44349cc55cSDimitry Andric   template <typename KeyT2, typename ValueT2>
DenseMapPairDenseMapPair45*4824e7fdSDimitry Andric   constexpr DenseMapPair(KeyT2 &&f, ValueT2 &&s)
46349cc55cSDimitry Andric       : first(__sanitizer::forward<KeyT2>(f)),
47349cc55cSDimitry Andric         second(__sanitizer::forward<ValueT2>(s)) {}
48349cc55cSDimitry Andric 
49*4824e7fdSDimitry Andric   constexpr DenseMapPair(const DenseMapPair &other) = default;
50*4824e7fdSDimitry Andric   constexpr DenseMapPair &operator=(const DenseMapPair &other) = default;
51*4824e7fdSDimitry Andric   constexpr DenseMapPair(DenseMapPair &&other) = default;
52*4824e7fdSDimitry Andric   constexpr DenseMapPair &operator=(DenseMapPair &&other) = default;
53349cc55cSDimitry Andric 
getFirstDenseMapPair54349cc55cSDimitry Andric   KeyT &getFirst() { return first; }
getFirstDenseMapPair55349cc55cSDimitry Andric   const KeyT &getFirst() const { return first; }
getSecondDenseMapPair56349cc55cSDimitry Andric   ValueT &getSecond() { return second; }
getSecondDenseMapPair57349cc55cSDimitry Andric   const ValueT &getSecond() const { return second; }
58349cc55cSDimitry Andric };
59349cc55cSDimitry Andric 
60349cc55cSDimitry Andric }  // end namespace detail
61349cc55cSDimitry Andric 
62349cc55cSDimitry Andric template <typename T>
63349cc55cSDimitry Andric struct DenseMapInfo {
64*4824e7fdSDimitry Andric   // static T getEmptyKey();
65*4824e7fdSDimitry Andric   // static T getTombstoneKey();
66349cc55cSDimitry Andric   // static unsigned getHashValue(const T &Val);
67349cc55cSDimitry Andric   // static bool isEqual(const T &LHS, const T &RHS);
68349cc55cSDimitry Andric };
69349cc55cSDimitry Andric 
70349cc55cSDimitry Andric // Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
71349cc55cSDimitry Andric // that are aligned to alignof(T) bytes, but try to avoid requiring T to be
72349cc55cSDimitry Andric // complete. This allows clients to instantiate DenseMap<T*, ...> with forward
73349cc55cSDimitry Andric // declared key types. Assume that no pointer key type requires more than 4096
74349cc55cSDimitry Andric // bytes of alignment.
75349cc55cSDimitry Andric template <typename T>
76349cc55cSDimitry Andric struct DenseMapInfo<T *> {
77349cc55cSDimitry Andric   // The following should hold, but it would require T to be complete:
78349cc55cSDimitry Andric   // static_assert(alignof(T) <= (1 << Log2MaxAlign),
79349cc55cSDimitry Andric   //               "DenseMap does not support pointer keys requiring more than "
80349cc55cSDimitry Andric   //               "Log2MaxAlign bits of alignment");
81349cc55cSDimitry Andric   static constexpr uptr Log2MaxAlign = 12;
82349cc55cSDimitry Andric 
83*4824e7fdSDimitry Andric   static constexpr T *getEmptyKey() {
84349cc55cSDimitry Andric     uptr Val = static_cast<uptr>(-1);
85349cc55cSDimitry Andric     Val <<= Log2MaxAlign;
86349cc55cSDimitry Andric     return reinterpret_cast<T *>(Val);
87349cc55cSDimitry Andric   }
88349cc55cSDimitry Andric 
89*4824e7fdSDimitry Andric   static constexpr T *getTombstoneKey() {
90349cc55cSDimitry Andric     uptr Val = static_cast<uptr>(-2);
91349cc55cSDimitry Andric     Val <<= Log2MaxAlign;
92349cc55cSDimitry Andric     return reinterpret_cast<T *>(Val);
93349cc55cSDimitry Andric   }
94349cc55cSDimitry Andric 
95*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const T *PtrVal) {
96349cc55cSDimitry Andric     return (unsigned((uptr)PtrVal) >> 4) ^ (unsigned((uptr)PtrVal) >> 9);
97349cc55cSDimitry Andric   }
98349cc55cSDimitry Andric 
99*4824e7fdSDimitry Andric   static constexpr bool isEqual(const T *LHS, const T *RHS) {
100*4824e7fdSDimitry Andric     return LHS == RHS;
101*4824e7fdSDimitry Andric   }
102349cc55cSDimitry Andric };
103349cc55cSDimitry Andric 
104349cc55cSDimitry Andric // Provide DenseMapInfo for chars.
105349cc55cSDimitry Andric template <>
106349cc55cSDimitry Andric struct DenseMapInfo<char> {
107*4824e7fdSDimitry Andric   static constexpr char getEmptyKey() { return ~0; }
108*4824e7fdSDimitry Andric   static constexpr char getTombstoneKey() { return ~0 - 1; }
109*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const char &Val) { return Val * 37U; }
110349cc55cSDimitry Andric 
111*4824e7fdSDimitry Andric   static constexpr bool isEqual(const char &LHS, const char &RHS) {
112*4824e7fdSDimitry Andric     return LHS == RHS;
113*4824e7fdSDimitry Andric   }
114349cc55cSDimitry Andric };
115349cc55cSDimitry Andric 
116349cc55cSDimitry Andric // Provide DenseMapInfo for unsigned chars.
117349cc55cSDimitry Andric template <>
118349cc55cSDimitry Andric struct DenseMapInfo<unsigned char> {
119*4824e7fdSDimitry Andric   static constexpr unsigned char getEmptyKey() { return ~0; }
120*4824e7fdSDimitry Andric   static constexpr unsigned char getTombstoneKey() { return ~0 - 1; }
121*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const unsigned char &Val) {
122*4824e7fdSDimitry Andric     return Val * 37U;
123*4824e7fdSDimitry Andric   }
124349cc55cSDimitry Andric 
125*4824e7fdSDimitry Andric   static constexpr bool isEqual(const unsigned char &LHS,
126*4824e7fdSDimitry Andric                                 const unsigned char &RHS) {
127349cc55cSDimitry Andric     return LHS == RHS;
128349cc55cSDimitry Andric   }
129349cc55cSDimitry Andric };
130349cc55cSDimitry Andric 
131349cc55cSDimitry Andric // Provide DenseMapInfo for unsigned shorts.
132349cc55cSDimitry Andric template <>
133349cc55cSDimitry Andric struct DenseMapInfo<unsigned short> {
134*4824e7fdSDimitry Andric   static constexpr unsigned short getEmptyKey() { return 0xFFFF; }
135*4824e7fdSDimitry Andric   static constexpr unsigned short getTombstoneKey() { return 0xFFFF - 1; }
136*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const unsigned short &Val) {
137*4824e7fdSDimitry Andric     return Val * 37U;
138*4824e7fdSDimitry Andric   }
139349cc55cSDimitry Andric 
140*4824e7fdSDimitry Andric   static constexpr bool isEqual(const unsigned short &LHS,
141*4824e7fdSDimitry Andric                                 const unsigned short &RHS) {
142349cc55cSDimitry Andric     return LHS == RHS;
143349cc55cSDimitry Andric   }
144349cc55cSDimitry Andric };
145349cc55cSDimitry Andric 
146349cc55cSDimitry Andric // Provide DenseMapInfo for unsigned ints.
147349cc55cSDimitry Andric template <>
148349cc55cSDimitry Andric struct DenseMapInfo<unsigned> {
149*4824e7fdSDimitry Andric   static constexpr unsigned getEmptyKey() { return ~0U; }
150*4824e7fdSDimitry Andric   static constexpr unsigned getTombstoneKey() { return ~0U - 1; }
151*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const unsigned &Val) {
152*4824e7fdSDimitry Andric     return Val * 37U;
153*4824e7fdSDimitry Andric   }
154349cc55cSDimitry Andric 
155*4824e7fdSDimitry Andric   static constexpr bool isEqual(const unsigned &LHS, const unsigned &RHS) {
156349cc55cSDimitry Andric     return LHS == RHS;
157349cc55cSDimitry Andric   }
158349cc55cSDimitry Andric };
159349cc55cSDimitry Andric 
160349cc55cSDimitry Andric // Provide DenseMapInfo for unsigned longs.
161349cc55cSDimitry Andric template <>
162349cc55cSDimitry Andric struct DenseMapInfo<unsigned long> {
163*4824e7fdSDimitry Andric   static constexpr unsigned long getEmptyKey() { return ~0UL; }
164*4824e7fdSDimitry Andric   static constexpr unsigned long getTombstoneKey() { return ~0UL - 1L; }
165349cc55cSDimitry Andric 
166*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const unsigned long &Val) {
167349cc55cSDimitry Andric     return (unsigned)(Val * 37UL);
168349cc55cSDimitry Andric   }
169349cc55cSDimitry Andric 
170*4824e7fdSDimitry Andric   static constexpr bool isEqual(const unsigned long &LHS,
171*4824e7fdSDimitry Andric                                 const unsigned long &RHS) {
172349cc55cSDimitry Andric     return LHS == RHS;
173349cc55cSDimitry Andric   }
174349cc55cSDimitry Andric };
175349cc55cSDimitry Andric 
176349cc55cSDimitry Andric // Provide DenseMapInfo for unsigned long longs.
177349cc55cSDimitry Andric template <>
178349cc55cSDimitry Andric struct DenseMapInfo<unsigned long long> {
179*4824e7fdSDimitry Andric   static constexpr unsigned long long getEmptyKey() { return ~0ULL; }
180*4824e7fdSDimitry Andric   static constexpr unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
181349cc55cSDimitry Andric 
182*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const unsigned long long &Val) {
183349cc55cSDimitry Andric     return (unsigned)(Val * 37ULL);
184349cc55cSDimitry Andric   }
185349cc55cSDimitry Andric 
186*4824e7fdSDimitry Andric   static constexpr bool isEqual(const unsigned long long &LHS,
187349cc55cSDimitry Andric                                 const unsigned long long &RHS) {
188349cc55cSDimitry Andric     return LHS == RHS;
189349cc55cSDimitry Andric   }
190349cc55cSDimitry Andric };
191349cc55cSDimitry Andric 
192349cc55cSDimitry Andric // Provide DenseMapInfo for shorts.
193349cc55cSDimitry Andric template <>
194349cc55cSDimitry Andric struct DenseMapInfo<short> {
195*4824e7fdSDimitry Andric   static constexpr short getEmptyKey() { return 0x7FFF; }
196*4824e7fdSDimitry Andric   static constexpr short getTombstoneKey() { return -0x7FFF - 1; }
197*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const short &Val) { return Val * 37U; }
198*4824e7fdSDimitry Andric   static constexpr bool isEqual(const short &LHS, const short &RHS) {
199*4824e7fdSDimitry Andric     return LHS == RHS;
200*4824e7fdSDimitry Andric   }
201349cc55cSDimitry Andric };
202349cc55cSDimitry Andric 
203349cc55cSDimitry Andric // Provide DenseMapInfo for ints.
204349cc55cSDimitry Andric template <>
205349cc55cSDimitry Andric struct DenseMapInfo<int> {
206*4824e7fdSDimitry Andric   static constexpr int getEmptyKey() { return 0x7fffffff; }
207*4824e7fdSDimitry Andric   static constexpr int getTombstoneKey() { return -0x7fffffff - 1; }
208*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const int &Val) {
209*4824e7fdSDimitry Andric     return (unsigned)(Val * 37U);
210*4824e7fdSDimitry Andric   }
211349cc55cSDimitry Andric 
212*4824e7fdSDimitry Andric   static constexpr bool isEqual(const int &LHS, const int &RHS) {
213*4824e7fdSDimitry Andric     return LHS == RHS;
214*4824e7fdSDimitry Andric   }
215349cc55cSDimitry Andric };
216349cc55cSDimitry Andric 
217349cc55cSDimitry Andric // Provide DenseMapInfo for longs.
218349cc55cSDimitry Andric template <>
219349cc55cSDimitry Andric struct DenseMapInfo<long> {
220*4824e7fdSDimitry Andric   static constexpr long getEmptyKey() {
221349cc55cSDimitry Andric     return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
222349cc55cSDimitry Andric   }
223349cc55cSDimitry Andric 
224*4824e7fdSDimitry Andric   static constexpr long getTombstoneKey() { return getEmptyKey() - 1L; }
225349cc55cSDimitry Andric 
226*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const long &Val) {
227349cc55cSDimitry Andric     return (unsigned)(Val * 37UL);
228349cc55cSDimitry Andric   }
229349cc55cSDimitry Andric 
230*4824e7fdSDimitry Andric   static constexpr bool isEqual(const long &LHS, const long &RHS) {
231*4824e7fdSDimitry Andric     return LHS == RHS;
232*4824e7fdSDimitry Andric   }
233349cc55cSDimitry Andric };
234349cc55cSDimitry Andric 
235349cc55cSDimitry Andric // Provide DenseMapInfo for long longs.
236349cc55cSDimitry Andric template <>
237349cc55cSDimitry Andric struct DenseMapInfo<long long> {
238*4824e7fdSDimitry Andric   static constexpr long long getEmptyKey() { return 0x7fffffffffffffffLL; }
239*4824e7fdSDimitry Andric   static constexpr long long getTombstoneKey() {
240349cc55cSDimitry Andric     return -0x7fffffffffffffffLL - 1;
241349cc55cSDimitry Andric   }
242349cc55cSDimitry Andric 
243*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const long long &Val) {
244349cc55cSDimitry Andric     return (unsigned)(Val * 37ULL);
245349cc55cSDimitry Andric   }
246349cc55cSDimitry Andric 
247*4824e7fdSDimitry Andric   static constexpr bool isEqual(const long long &LHS, const long long &RHS) {
248349cc55cSDimitry Andric     return LHS == RHS;
249349cc55cSDimitry Andric   }
250349cc55cSDimitry Andric };
251349cc55cSDimitry Andric 
252349cc55cSDimitry Andric // Provide DenseMapInfo for all pairs whose members have info.
253349cc55cSDimitry Andric template <typename T, typename U>
254349cc55cSDimitry Andric struct DenseMapInfo<detail::DenseMapPair<T, U>> {
255349cc55cSDimitry Andric   using Pair = detail::DenseMapPair<T, U>;
256349cc55cSDimitry Andric   using FirstInfo = DenseMapInfo<T>;
257349cc55cSDimitry Andric   using SecondInfo = DenseMapInfo<U>;
258349cc55cSDimitry Andric 
259*4824e7fdSDimitry Andric   static constexpr Pair getEmptyKey() {
260349cc55cSDimitry Andric     return detail::DenseMapPair<T, U>(FirstInfo::getEmptyKey(),
261349cc55cSDimitry Andric                                       SecondInfo::getEmptyKey());
262349cc55cSDimitry Andric   }
263349cc55cSDimitry Andric 
264*4824e7fdSDimitry Andric   static constexpr Pair getTombstoneKey() {
265349cc55cSDimitry Andric     return detail::DenseMapPair<T, U>(FirstInfo::getTombstoneKey(),
266349cc55cSDimitry Andric                                       SecondInfo::getTombstoneKey());
267349cc55cSDimitry Andric   }
268349cc55cSDimitry Andric 
269*4824e7fdSDimitry Andric   static constexpr unsigned getHashValue(const Pair &PairVal) {
270349cc55cSDimitry Andric     return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
271349cc55cSDimitry Andric                                     SecondInfo::getHashValue(PairVal.second));
272349cc55cSDimitry Andric   }
273349cc55cSDimitry Andric 
274*4824e7fdSDimitry Andric   static constexpr bool isEqual(const Pair &LHS, const Pair &RHS) {
275349cc55cSDimitry Andric     return FirstInfo::isEqual(LHS.first, RHS.first) &&
276349cc55cSDimitry Andric            SecondInfo::isEqual(LHS.second, RHS.second);
277349cc55cSDimitry Andric   }
278349cc55cSDimitry Andric };
279349cc55cSDimitry Andric 
280349cc55cSDimitry Andric }  // namespace __sanitizer
281349cc55cSDimitry Andric 
282349cc55cSDimitry Andric #endif  // SANITIZER_DENSE_MAP_INFO_H
283