diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_hash.h b/compiler-rt/lib/sanitizer_common/sanitizer_hash.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_hash.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_hash.h @@ -38,6 +38,30 @@ return x; } }; + +class MurMur2Hash64Builder { + static const u64 m = 0xc6a4a7935bd1e995ull; + static const u64 seed = 0x9747b28c9747b28cull; + static const u64 r = 47; + u64 h; + + public: + explicit MurMur2Hash64Builder(u64 init = 0) { h = seed ^ (init * m); } + void add(u64 k) { + k *= m; + k ^= k >> r; + k *= m; + h ^= k; + h *= m; + } + u64 get() { + u64 x = h; + x ^= x >> r; + x *= m; + x ^= x >> r; + return x; + } +}; } //namespace __sanitizer #endif // SANITIZER_HASH_H diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_hash_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_hash_test.cpp --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_hash_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_hash_test.cpp @@ -31,4 +31,18 @@ EXPECT_EQ(h.get(), 2640061027u); } +TEST(SanitizerCommon, Hash64Seed) { + EXPECT_EQ(MurMur2Hash64Builder(0).get(), 4469829599815726255ull); + EXPECT_EQ(MurMur2Hash64Builder(1).get(), 14121968454562043709ull); + EXPECT_EQ(MurMur2Hash64Builder(3).get(), 8040757559320203998ull); +} + +TEST(SanitizerCommon, Hash64Add) { + MurMur2Hash64Builder h(123 * sizeof(u64)); + for (u32 i = 0; i < 123; ++i) h.add(i); + EXPECT_EQ(h.get(), 11366430808886012537ull); + for (u32 i = 0; i < 123; ++i) h.add(-i); + EXPECT_EQ(h.get(), 10843188204560467446ull); +} + } // namespace __sanitizer