sanitizer_dense_map_info.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. //===- sanitizer_dense_map_info.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. #ifndef SANITIZER_DENSE_MAP_INFO_H
  9. #define SANITIZER_DENSE_MAP_INFO_H
  10. #include "sanitizer_common.h"
  11. #include "sanitizer_internal_defs.h"
  12. #include "sanitizer_type_traits.h"
  13. namespace __sanitizer {
  14. namespace detail {
  15. /// Simplistic combination of 32-bit hash values into 32-bit hash values.
  16. static constexpr unsigned combineHashValue(unsigned a, unsigned b) {
  17. u64 key = (u64)a << 32 | (u64)b;
  18. key += ~(key << 32);
  19. key ^= (key >> 22);
  20. key += ~(key << 13);
  21. key ^= (key >> 8);
  22. key += (key << 3);
  23. key ^= (key >> 15);
  24. key += ~(key << 27);
  25. key ^= (key >> 31);
  26. return (unsigned)key;
  27. }
  28. // We extend a pair to allow users to override the bucket type with their own
  29. // implementation without requiring two members.
  30. template <typename KeyT, typename ValueT>
  31. struct DenseMapPair {
  32. KeyT first = {};
  33. ValueT second = {};
  34. constexpr DenseMapPair() = default;
  35. constexpr DenseMapPair(const KeyT &f, const ValueT &s)
  36. : first(f), second(s) {}
  37. template <typename KeyT2, typename ValueT2>
  38. constexpr DenseMapPair(KeyT2 &&f, ValueT2 &&s)
  39. : first(__sanitizer::forward<KeyT2>(f)),
  40. second(__sanitizer::forward<ValueT2>(s)) {}
  41. constexpr DenseMapPair(const DenseMapPair &other) = default;
  42. constexpr DenseMapPair &operator=(const DenseMapPair &other) = default;
  43. constexpr DenseMapPair(DenseMapPair &&other) = default;
  44. constexpr DenseMapPair &operator=(DenseMapPair &&other) = default;
  45. KeyT &getFirst() { return first; }
  46. const KeyT &getFirst() const { return first; }
  47. ValueT &getSecond() { return second; }
  48. const ValueT &getSecond() const { return second; }
  49. };
  50. } // end namespace detail
  51. template <typename T>
  52. struct DenseMapInfo {
  53. // static T getEmptyKey();
  54. // static T getTombstoneKey();
  55. // static unsigned getHashValue(const T &Val);
  56. // static bool isEqual(const T &LHS, const T &RHS);
  57. };
  58. // Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
  59. // that are aligned to alignof(T) bytes, but try to avoid requiring T to be
  60. // complete. This allows clients to instantiate DenseMap<T*, ...> with forward
  61. // declared key types. Assume that no pointer key type requires more than 4096
  62. // bytes of alignment.
  63. template <typename T>
  64. struct DenseMapInfo<T *> {
  65. // The following should hold, but it would require T to be complete:
  66. // static_assert(alignof(T) <= (1 << Log2MaxAlign),
  67. // "DenseMap does not support pointer keys requiring more than "
  68. // "Log2MaxAlign bits of alignment");
  69. static constexpr uptr Log2MaxAlign = 12;
  70. static constexpr T *getEmptyKey() {
  71. uptr Val = static_cast<uptr>(-1);
  72. Val <<= Log2MaxAlign;
  73. return reinterpret_cast<T *>(Val);
  74. }
  75. static constexpr T *getTombstoneKey() {
  76. uptr Val = static_cast<uptr>(-2);
  77. Val <<= Log2MaxAlign;
  78. return reinterpret_cast<T *>(Val);
  79. }
  80. static constexpr unsigned getHashValue(const T *PtrVal) {
  81. return (unsigned((uptr)PtrVal) >> 4) ^ (unsigned((uptr)PtrVal) >> 9);
  82. }
  83. static constexpr bool isEqual(const T *LHS, const T *RHS) {
  84. return LHS == RHS;
  85. }
  86. };
  87. // Provide DenseMapInfo for chars.
  88. template <>
  89. struct DenseMapInfo<char> {
  90. static constexpr char getEmptyKey() { return ~0; }
  91. static constexpr char getTombstoneKey() { return ~0 - 1; }
  92. static constexpr unsigned getHashValue(const char &Val) { return Val * 37U; }
  93. static constexpr bool isEqual(const char &LHS, const char &RHS) {
  94. return LHS == RHS;
  95. }
  96. };
  97. // Provide DenseMapInfo for unsigned chars.
  98. template <>
  99. struct DenseMapInfo<unsigned char> {
  100. static constexpr unsigned char getEmptyKey() { return ~0; }
  101. static constexpr unsigned char getTombstoneKey() { return ~0 - 1; }
  102. static constexpr unsigned getHashValue(const unsigned char &Val) {
  103. return Val * 37U;
  104. }
  105. static constexpr bool isEqual(const unsigned char &LHS,
  106. const unsigned char &RHS) {
  107. return LHS == RHS;
  108. }
  109. };
  110. // Provide DenseMapInfo for unsigned shorts.
  111. template <>
  112. struct DenseMapInfo<unsigned short> {
  113. static constexpr unsigned short getEmptyKey() { return 0xFFFF; }
  114. static constexpr unsigned short getTombstoneKey() { return 0xFFFF - 1; }
  115. static constexpr unsigned getHashValue(const unsigned short &Val) {
  116. return Val * 37U;
  117. }
  118. static constexpr bool isEqual(const unsigned short &LHS,
  119. const unsigned short &RHS) {
  120. return LHS == RHS;
  121. }
  122. };
  123. // Provide DenseMapInfo for unsigned ints.
  124. template <>
  125. struct DenseMapInfo<unsigned> {
  126. static constexpr unsigned getEmptyKey() { return ~0U; }
  127. static constexpr unsigned getTombstoneKey() { return ~0U - 1; }
  128. static constexpr unsigned getHashValue(const unsigned &Val) {
  129. return Val * 37U;
  130. }
  131. static constexpr bool isEqual(const unsigned &LHS, const unsigned &RHS) {
  132. return LHS == RHS;
  133. }
  134. };
  135. // Provide DenseMapInfo for unsigned longs.
  136. template <>
  137. struct DenseMapInfo<unsigned long> {
  138. static constexpr unsigned long getEmptyKey() { return ~0UL; }
  139. static constexpr unsigned long getTombstoneKey() { return ~0UL - 1L; }
  140. static constexpr unsigned getHashValue(const unsigned long &Val) {
  141. return (unsigned)(Val * 37UL);
  142. }
  143. static constexpr bool isEqual(const unsigned long &LHS,
  144. const unsigned long &RHS) {
  145. return LHS == RHS;
  146. }
  147. };
  148. // Provide DenseMapInfo for unsigned long longs.
  149. template <>
  150. struct DenseMapInfo<unsigned long long> {
  151. static constexpr unsigned long long getEmptyKey() { return ~0ULL; }
  152. static constexpr unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
  153. static constexpr unsigned getHashValue(const unsigned long long &Val) {
  154. return (unsigned)(Val * 37ULL);
  155. }
  156. static constexpr bool isEqual(const unsigned long long &LHS,
  157. const unsigned long long &RHS) {
  158. return LHS == RHS;
  159. }
  160. };
  161. // Provide DenseMapInfo for shorts.
  162. template <>
  163. struct DenseMapInfo<short> {
  164. static constexpr short getEmptyKey() { return 0x7FFF; }
  165. static constexpr short getTombstoneKey() { return -0x7FFF - 1; }
  166. static constexpr unsigned getHashValue(const short &Val) { return Val * 37U; }
  167. static constexpr bool isEqual(const short &LHS, const short &RHS) {
  168. return LHS == RHS;
  169. }
  170. };
  171. // Provide DenseMapInfo for ints.
  172. template <>
  173. struct DenseMapInfo<int> {
  174. static constexpr int getEmptyKey() { return 0x7fffffff; }
  175. static constexpr int getTombstoneKey() { return -0x7fffffff - 1; }
  176. static constexpr unsigned getHashValue(const int &Val) {
  177. return (unsigned)(Val * 37U);
  178. }
  179. static constexpr bool isEqual(const int &LHS, const int &RHS) {
  180. return LHS == RHS;
  181. }
  182. };
  183. // Provide DenseMapInfo for longs.
  184. template <>
  185. struct DenseMapInfo<long> {
  186. static constexpr long getEmptyKey() {
  187. return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
  188. }
  189. static constexpr long getTombstoneKey() { return getEmptyKey() - 1L; }
  190. static constexpr unsigned getHashValue(const long &Val) {
  191. return (unsigned)(Val * 37UL);
  192. }
  193. static constexpr bool isEqual(const long &LHS, const long &RHS) {
  194. return LHS == RHS;
  195. }
  196. };
  197. // Provide DenseMapInfo for long longs.
  198. template <>
  199. struct DenseMapInfo<long long> {
  200. static constexpr long long getEmptyKey() { return 0x7fffffffffffffffLL; }
  201. static constexpr long long getTombstoneKey() {
  202. return -0x7fffffffffffffffLL - 1;
  203. }
  204. static constexpr unsigned getHashValue(const long long &Val) {
  205. return (unsigned)(Val * 37ULL);
  206. }
  207. static constexpr bool isEqual(const long long &LHS, const long long &RHS) {
  208. return LHS == RHS;
  209. }
  210. };
  211. // Provide DenseMapInfo for all pairs whose members have info.
  212. template <typename T, typename U>
  213. struct DenseMapInfo<detail::DenseMapPair<T, U>> {
  214. using Pair = detail::DenseMapPair<T, U>;
  215. using FirstInfo = DenseMapInfo<T>;
  216. using SecondInfo = DenseMapInfo<U>;
  217. static constexpr Pair getEmptyKey() {
  218. return detail::DenseMapPair<T, U>(FirstInfo::getEmptyKey(),
  219. SecondInfo::getEmptyKey());
  220. }
  221. static constexpr Pair getTombstoneKey() {
  222. return detail::DenseMapPair<T, U>(FirstInfo::getTombstoneKey(),
  223. SecondInfo::getTombstoneKey());
  224. }
  225. static constexpr unsigned getHashValue(const Pair &PairVal) {
  226. return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
  227. SecondInfo::getHashValue(PairVal.second));
  228. }
  229. static constexpr bool isEqual(const Pair &LHS, const Pair &RHS) {
  230. return FirstInfo::isEqual(LHS.first, RHS.first) &&
  231. SecondInfo::isEqual(LHS.second, RHS.second);
  232. }
  233. };
  234. } // namespace __sanitizer
  235. #endif // SANITIZER_DENSE_MAP_INFO_H