File indexing completed on 2026-05-10 08:43:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #ifndef LLVM_ADT_HASHING_H
0045 #define LLVM_ADT_HASHING_H
0046
0047 #include "llvm/Config/abi-breaking.h"
0048 #include "llvm/Support/DataTypes.h"
0049 #include "llvm/Support/ErrorHandling.h"
0050 #include "llvm/Support/SwapByteOrder.h"
0051 #include "llvm/Support/type_traits.h"
0052 #include <algorithm>
0053 #include <cassert>
0054 #include <cstring>
0055 #include <optional>
0056 #include <string>
0057 #include <tuple>
0058 #include <utility>
0059
0060 namespace llvm {
0061 template <typename T, typename Enable> struct DenseMapInfo;
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 class hash_code {
0076 size_t value;
0077
0078 public:
0079
0080
0081 hash_code() = default;
0082
0083
0084 hash_code(size_t value) : value(value) {}
0085
0086
0087 operator size_t() const { return value; }
0088
0089 friend bool operator==(const hash_code &lhs, const hash_code &rhs) {
0090 return lhs.value == rhs.value;
0091 }
0092 friend bool operator!=(const hash_code &lhs, const hash_code &rhs) {
0093 return lhs.value != rhs.value;
0094 }
0095
0096
0097 friend size_t hash_value(const hash_code &code) { return code.value; }
0098 };
0099
0100
0101
0102
0103
0104
0105
0106
0107 template <typename T>
0108 std::enable_if_t<is_integral_or_enum<T>::value, hash_code> hash_value(T value);
0109
0110
0111
0112
0113 template <typename T> hash_code hash_value(const T *ptr);
0114
0115
0116 template <typename T, typename U>
0117 hash_code hash_value(const std::pair<T, U> &arg);
0118
0119
0120 template <typename... Ts>
0121 hash_code hash_value(const std::tuple<Ts...> &arg);
0122
0123
0124 template <typename T>
0125 hash_code hash_value(const std::basic_string<T> &arg);
0126
0127
0128 template <typename T> hash_code hash_value(const std::optional<T> &arg);
0129
0130
0131
0132
0133 namespace hashing {
0134 namespace detail {
0135
0136 inline uint64_t fetch64(const char *p) {
0137 uint64_t result;
0138 memcpy(&result, p, sizeof(result));
0139 if (sys::IsBigEndianHost)
0140 sys::swapByteOrder(result);
0141 return result;
0142 }
0143
0144 inline uint32_t fetch32(const char *p) {
0145 uint32_t result;
0146 memcpy(&result, p, sizeof(result));
0147 if (sys::IsBigEndianHost)
0148 sys::swapByteOrder(result);
0149 return result;
0150 }
0151
0152
0153 static constexpr uint64_t k0 = 0xc3a5c85c97cb3127ULL;
0154 static constexpr uint64_t k1 = 0xb492b66fbe98f273ULL;
0155 static constexpr uint64_t k2 = 0x9ae16a3b2f90404fULL;
0156 static constexpr uint64_t k3 = 0xc949d7c7509e6557ULL;
0157
0158
0159
0160
0161 inline uint64_t rotate(uint64_t val, size_t shift) {
0162
0163 return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
0164 }
0165
0166 inline uint64_t shift_mix(uint64_t val) {
0167 return val ^ (val >> 47);
0168 }
0169
0170 inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) {
0171
0172 const uint64_t kMul = 0x9ddfea08eb382d69ULL;
0173 uint64_t a = (low ^ high) * kMul;
0174 a ^= (a >> 47);
0175 uint64_t b = (high ^ a) * kMul;
0176 b ^= (b >> 47);
0177 b *= kMul;
0178 return b;
0179 }
0180
0181 inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) {
0182 uint8_t a = s[0];
0183 uint8_t b = s[len >> 1];
0184 uint8_t c = s[len - 1];
0185 uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
0186 uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2);
0187 return shift_mix(y * k2 ^ z * k3 ^ seed) * k2;
0188 }
0189
0190 inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) {
0191 uint64_t a = fetch32(s);
0192 return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4));
0193 }
0194
0195 inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) {
0196 uint64_t a = fetch64(s);
0197 uint64_t b = fetch64(s + len - 8);
0198 return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b;
0199 }
0200
0201 inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) {
0202 uint64_t a = fetch64(s) * k1;
0203 uint64_t b = fetch64(s + 8);
0204 uint64_t c = fetch64(s + len - 8) * k2;
0205 uint64_t d = fetch64(s + len - 16) * k0;
0206 return hash_16_bytes(llvm::rotr<uint64_t>(a - b, 43) +
0207 llvm::rotr<uint64_t>(c ^ seed, 30) + d,
0208 a + llvm::rotr<uint64_t>(b ^ k3, 20) - c + len + seed);
0209 }
0210
0211 inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) {
0212 uint64_t z = fetch64(s + 24);
0213 uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0;
0214 uint64_t b = llvm::rotr<uint64_t>(a + z, 52);
0215 uint64_t c = llvm::rotr<uint64_t>(a, 37);
0216 a += fetch64(s + 8);
0217 c += llvm::rotr<uint64_t>(a, 7);
0218 a += fetch64(s + 16);
0219 uint64_t vf = a + z;
0220 uint64_t vs = b + llvm::rotr<uint64_t>(a, 31) + c;
0221 a = fetch64(s + 16) + fetch64(s + len - 32);
0222 z = fetch64(s + len - 8);
0223 b = llvm::rotr<uint64_t>(a + z, 52);
0224 c = llvm::rotr<uint64_t>(a, 37);
0225 a += fetch64(s + len - 24);
0226 c += llvm::rotr<uint64_t>(a, 7);
0227 a += fetch64(s + len - 16);
0228 uint64_t wf = a + z;
0229 uint64_t ws = b + llvm::rotr<uint64_t>(a, 31) + c;
0230 uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0);
0231 return shift_mix((seed ^ (r * k0)) + vs) * k2;
0232 }
0233
0234 inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) {
0235 if (length >= 4 && length <= 8)
0236 return hash_4to8_bytes(s, length, seed);
0237 if (length > 8 && length <= 16)
0238 return hash_9to16_bytes(s, length, seed);
0239 if (length > 16 && length <= 32)
0240 return hash_17to32_bytes(s, length, seed);
0241 if (length > 32)
0242 return hash_33to64_bytes(s, length, seed);
0243 if (length != 0)
0244 return hash_1to3_bytes(s, length, seed);
0245
0246 return k2 ^ seed;
0247 }
0248
0249
0250
0251
0252 struct hash_state {
0253 uint64_t h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0;
0254
0255
0256
0257
0258 static hash_state create(const char *s, uint64_t seed) {
0259 hash_state state = {0,
0260 seed,
0261 hash_16_bytes(seed, k1),
0262 llvm::rotr<uint64_t>(seed ^ k1, 49),
0263 seed * k1,
0264 shift_mix(seed),
0265 0};
0266 state.h6 = hash_16_bytes(state.h4, state.h5);
0267 state.mix(s);
0268 return state;
0269 }
0270
0271
0272
0273 static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) {
0274 a += fetch64(s);
0275 uint64_t c = fetch64(s + 24);
0276 b = llvm::rotr<uint64_t>(b + a + c, 21);
0277 uint64_t d = a;
0278 a += fetch64(s + 8) + fetch64(s + 16);
0279 b += llvm::rotr<uint64_t>(a, 44) + d;
0280 a += c;
0281 }
0282
0283
0284
0285
0286 void mix(const char *s) {
0287 h0 = llvm::rotr<uint64_t>(h0 + h1 + h3 + fetch64(s + 8), 37) * k1;
0288 h1 = llvm::rotr<uint64_t>(h1 + h4 + fetch64(s + 48), 42) * k1;
0289 h0 ^= h6;
0290 h1 += h3 + fetch64(s + 40);
0291 h2 = llvm::rotr<uint64_t>(h2 + h5, 33) * k1;
0292 h3 = h4 * k1;
0293 h4 = h0 + h5;
0294 mix_32_bytes(s, h3, h4);
0295 h5 = h2 + h6;
0296 h6 = h1 + fetch64(s + 16);
0297 mix_32_bytes(s + 32, h5, h6);
0298 std::swap(h2, h0);
0299 }
0300
0301
0302
0303 uint64_t finalize(size_t length) {
0304 return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2,
0305 hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0);
0306 }
0307 };
0308
0309
0310
0311
0312
0313 inline uint64_t get_execution_seed() {
0314 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0315 return static_cast<uint64_t>(
0316 reinterpret_cast<uintptr_t>(&install_fatal_error_handler));
0317 #else
0318 return 0xff51afd7ed558ccdULL;
0319 #endif
0320 }
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335 template <typename T> struct is_hashable_data
0336 : std::integral_constant<bool, ((is_integral_or_enum<T>::value ||
0337 std::is_pointer<T>::value) &&
0338 64 % sizeof(T) == 0)> {};
0339
0340
0341
0342
0343
0344 template <typename T, typename U> struct is_hashable_data<std::pair<T, U> >
0345 : std::integral_constant<bool, (is_hashable_data<T>::value &&
0346 is_hashable_data<U>::value &&
0347 (sizeof(T) + sizeof(U)) ==
0348 sizeof(std::pair<T, U>))> {};
0349
0350
0351
0352 template <typename T>
0353 std::enable_if_t<is_hashable_data<T>::value, T>
0354 get_hashable_data(const T &value) {
0355 return value;
0356 }
0357
0358
0359
0360 template <typename T>
0361 std::enable_if_t<!is_hashable_data<T>::value, size_t>
0362 get_hashable_data(const T &value) {
0363 using ::llvm::hash_value;
0364 return hash_value(value);
0365 }
0366
0367
0368
0369
0370
0371
0372
0373
0374 template <typename T>
0375 bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value,
0376 size_t offset = 0) {
0377 size_t store_size = sizeof(value) - offset;
0378 if (buffer_ptr + store_size > buffer_end)
0379 return false;
0380 const char *value_data = reinterpret_cast<const char *>(&value);
0381 memcpy(buffer_ptr, value_data + offset, store_size);
0382 buffer_ptr += store_size;
0383 return true;
0384 }
0385
0386
0387
0388
0389
0390
0391 template <typename InputIteratorT>
0392 hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
0393 const uint64_t seed = get_execution_seed();
0394 char buffer[64], *buffer_ptr = buffer;
0395 char *const buffer_end = std::end(buffer);
0396 while (first != last && store_and_advance(buffer_ptr, buffer_end,
0397 get_hashable_data(*first)))
0398 ++first;
0399 if (first == last)
0400 return hash_short(buffer, buffer_ptr - buffer, seed);
0401 assert(buffer_ptr == buffer_end);
0402
0403 hash_state state = state.create(buffer, seed);
0404 size_t length = 64;
0405 while (first != last) {
0406
0407
0408 buffer_ptr = buffer;
0409 while (first != last && store_and_advance(buffer_ptr, buffer_end,
0410 get_hashable_data(*first)))
0411 ++first;
0412
0413
0414
0415
0416 std::rotate(buffer, buffer_ptr, buffer_end);
0417
0418
0419 state.mix(buffer);
0420 length += buffer_ptr - buffer;
0421 };
0422
0423 return state.finalize(length);
0424 }
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434 template <typename ValueT>
0435 std::enable_if_t<is_hashable_data<ValueT>::value, hash_code>
0436 hash_combine_range_impl(ValueT *first, ValueT *last) {
0437 const uint64_t seed = get_execution_seed();
0438 const char *s_begin = reinterpret_cast<const char *>(first);
0439 const char *s_end = reinterpret_cast<const char *>(last);
0440 const size_t length = std::distance(s_begin, s_end);
0441 if (length <= 64)
0442 return hash_short(s_begin, length, seed);
0443
0444 const char *s_aligned_end = s_begin + (length & ~63);
0445 hash_state state = state.create(s_begin, seed);
0446 s_begin += 64;
0447 while (s_begin != s_aligned_end) {
0448 state.mix(s_begin);
0449 s_begin += 64;
0450 }
0451 if (length & 63)
0452 state.mix(s_end - 64);
0453
0454 return state.finalize(length);
0455 }
0456
0457 }
0458 }
0459
0460
0461
0462
0463
0464
0465
0466
0467 template <typename InputIteratorT>
0468 hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) {
0469 return ::llvm::hashing::detail::hash_combine_range_impl(first, last);
0470 }
0471
0472
0473
0474 namespace hashing {
0475 namespace detail {
0476
0477
0478
0479
0480
0481
0482
0483
0484 struct hash_combine_recursive_helper {
0485 char buffer[64] = {};
0486 hash_state state;
0487 const uint64_t seed;
0488
0489 public:
0490
0491
0492
0493
0494 hash_combine_recursive_helper()
0495 : seed(get_execution_seed()) {}
0496
0497
0498
0499
0500
0501
0502
0503 template <typename T>
0504 char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) {
0505 if (!store_and_advance(buffer_ptr, buffer_end, data)) {
0506
0507
0508
0509
0510 size_t partial_store_size = buffer_end - buffer_ptr;
0511 memcpy(buffer_ptr, &data, partial_store_size);
0512
0513
0514
0515
0516
0517 if (length == 0) {
0518 state = state.create(buffer, seed);
0519 length = 64;
0520 } else {
0521
0522 state.mix(buffer);
0523 length += 64;
0524 }
0525
0526
0527 buffer_ptr = buffer;
0528
0529
0530
0531 if (!store_and_advance(buffer_ptr, buffer_end, data,
0532 partial_store_size))
0533 llvm_unreachable("buffer smaller than stored type");
0534 }
0535 return buffer_ptr;
0536 }
0537
0538
0539
0540
0541
0542 template <typename T, typename ...Ts>
0543 hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
0544 const T &arg, const Ts &...args) {
0545 buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg));
0546
0547
0548 return combine(length, buffer_ptr, buffer_end, args...);
0549 }
0550
0551
0552
0553
0554
0555
0556 hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) {
0557
0558
0559 if (length == 0)
0560 return hash_short(buffer, buffer_ptr - buffer, seed);
0561
0562
0563
0564
0565
0566 std::rotate(buffer, buffer_ptr, buffer_end);
0567
0568
0569 state.mix(buffer);
0570 length += buffer_ptr - buffer;
0571
0572 return state.finalize(length);
0573 }
0574 };
0575
0576 }
0577 }
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590 template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
0591
0592 ::llvm::hashing::detail::hash_combine_recursive_helper helper;
0593 return helper.combine(0, helper.buffer, helper.buffer + 64, args...);
0594 }
0595
0596
0597
0598 namespace hashing {
0599 namespace detail {
0600
0601
0602
0603
0604
0605
0606 inline hash_code hash_integer_value(uint64_t value) {
0607
0608 const uint64_t seed = get_execution_seed();
0609 const char *s = reinterpret_cast<const char *>(&value);
0610 const uint64_t a = fetch32(s);
0611 return hash_16_bytes(seed + (a << 3), fetch32(s + 4));
0612 }
0613
0614 }
0615 }
0616
0617
0618
0619 template <typename T>
0620 std::enable_if_t<is_integral_or_enum<T>::value, hash_code> hash_value(T value) {
0621 return ::llvm::hashing::detail::hash_integer_value(
0622 static_cast<uint64_t>(value));
0623 }
0624
0625
0626
0627 template <typename T> hash_code hash_value(const T *ptr) {
0628 return ::llvm::hashing::detail::hash_integer_value(
0629 reinterpret_cast<uintptr_t>(ptr));
0630 }
0631
0632
0633
0634 template <typename T, typename U>
0635 hash_code hash_value(const std::pair<T, U> &arg) {
0636 return hash_combine(arg.first, arg.second);
0637 }
0638
0639 template <typename... Ts> hash_code hash_value(const std::tuple<Ts...> &arg) {
0640 return std::apply([](const auto &...xs) { return hash_combine(xs...); }, arg);
0641 }
0642
0643
0644
0645 template <typename T>
0646 hash_code hash_value(const std::basic_string<T> &arg) {
0647 return hash_combine_range(arg.begin(), arg.end());
0648 }
0649
0650 template <typename T> hash_code hash_value(const std::optional<T> &arg) {
0651 return arg ? hash_combine(true, *arg) : hash_value(false);
0652 }
0653
0654 template <> struct DenseMapInfo<hash_code, void> {
0655 static inline hash_code getEmptyKey() { return hash_code(-1); }
0656 static inline hash_code getTombstoneKey() { return hash_code(-2); }
0657 static unsigned getHashValue(hash_code val) {
0658 return static_cast<unsigned>(size_t(val));
0659 }
0660 static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
0661 };
0662
0663 }
0664
0665
0666 namespace std {
0667
0668 template<>
0669 struct hash<llvm::hash_code> {
0670 size_t operator()(llvm::hash_code const& Val) const {
0671 return Val;
0672 }
0673 };
0674
0675 }
0676
0677 #endif