Skip to content

Conversation

melver
Copy link
Contributor

@melver melver commented Sep 26, 2025

Factor out the 64-bit hash calculation in getPointerAuthStableSipHash()
as getStableSipHash(). This allows using the full 64-bit hash where we
require a stable hash.

Similar to getPointerAuthStableSipHash(), the new hash function is meant
to be stable across platforms and compiler versions.

Created using spr 1.3.8-beta.1
@melver melver marked this pull request as ready for review September 26, 2025 20:39
@melver melver requested review from ojhunt and vitalybuka September 26, 2025 20:39
@llvmbot
Copy link
Member

llvmbot commented Sep 26, 2025

@llvm/pr-subscribers-llvm-support

Author: Marco Elver (melver)

Changes

Factor out the 64-bit hash calculation in getPointerAuthStableSipHash()
as getStableSipHash(). This allows using the full 64-bit hash where we
require a stable hash.

Similar to getPointerAuthStableSipHash(), the new hash function is meant
to be stable across platforms and compiler versions.


Full diff: https://github.com/llvm/llvm-project/pull/160945.diff

3 Files Affected:

  • (modified) llvm/include/llvm/Support/SipHash.h (+7)
  • (modified) llvm/lib/Support/SipHash.cpp (+8-3)
  • (modified) llvm/unittests/Support/SipHashTest.cpp (+7)
diff --git a/llvm/include/llvm/Support/SipHash.h b/llvm/include/llvm/Support/SipHash.h
index 910cf59432c69..b090565641526 100644
--- a/llvm/include/llvm/Support/SipHash.h
+++ b/llvm/include/llvm/Support/SipHash.h
@@ -33,6 +33,13 @@ LLVM_ABI void getSipHash_2_4_64(ArrayRef<uint8_t> In, const uint8_t (&K)[16],
 LLVM_ABI void getSipHash_2_4_128(ArrayRef<uint8_t> In, const uint8_t (&K)[16],
                                  uint8_t (&Out)[16]);
 
+/// Compute a stable 64-bit hash of the given string.
+///
+/// The exact algorithm is the little-endian interpretation of the
+/// non-doubled (i.e. 64-bit) result of applying a SipHash-2-4 using
+/// a specific seed value which can be found in the source.
+LLVM_ABI uint64_t getStableSipHash(StringRef Str);
+
 /// Compute a stable non-zero 16-bit hash of the given string.
 ///
 /// The exact algorithm is the little-endian interpretation of the
diff --git a/llvm/lib/Support/SipHash.cpp b/llvm/lib/Support/SipHash.cpp
index 86dad66420435..382d36f0a8da5 100644
--- a/llvm/lib/Support/SipHash.cpp
+++ b/llvm/lib/Support/SipHash.cpp
@@ -35,14 +35,19 @@ void llvm::getSipHash_2_4_128(ArrayRef<uint8_t> In, const uint8_t (&K)[16],
   siphash<2, 4>(In.data(), In.size(), K, Out);
 }
 
-/// Compute an ABI-stable 16-bit hash of the given string.
-uint16_t llvm::getPointerAuthStableSipHash(StringRef Str) {
+/// Compute an ABI-stable 64-bit hash of the given string.
+uint64_t llvm::getStableSipHash(StringRef Str) {
   static const uint8_t K[16] = {0xb5, 0xd4, 0xc9, 0xeb, 0x79, 0x10, 0x4a, 0x79,
                                 0x6f, 0xec, 0x8b, 0x1b, 0x42, 0x87, 0x81, 0xd4};
 
   uint8_t RawHashBytes[8];
   getSipHash_2_4_64(arrayRefFromStringRef(Str), K, RawHashBytes);
-  uint64_t RawHash = endian::read64le(RawHashBytes);
+  return endian::read64le(RawHashBytes);
+}
+
+/// Compute an ABI-stable 16-bit hash of the given string.
+uint16_t llvm::getPointerAuthStableSipHash(StringRef Str) {
+  uint64_t RawHash = getStableSipHash(Str);
 
   // Produce a non-zero 16-bit discriminator.
   uint16_t Discriminator = (RawHash % 0xFFFF) + 1;
diff --git a/llvm/unittests/Support/SipHashTest.cpp b/llvm/unittests/Support/SipHashTest.cpp
index 7c557eb488acc..3037e6436e18d 100644
--- a/llvm/unittests/Support/SipHashTest.cpp
+++ b/llvm/unittests/Support/SipHashTest.cpp
@@ -50,6 +50,13 @@ TEST(SipHashTest, SipHash_2_4_128) {
   }
 }
 
+// Tests for the 64-bit stable SipHash wrapper.
+TEST(SipHashTest, StableSipHash) {
+  EXPECT_EQ(0xB2BB69BB0A2AC0F1UL, getStableSipHash(""));
+  EXPECT_EQ(0x9304ABFF427B72E8UL, getStableSipHash("strlen"));
+  EXPECT_EQ(0x55F45179A08AE51BUL, getStableSipHash("_ZN1 ind; f"));
+}
+
 // Tests for the ptrauth-specific SipHash wrapper.
 TEST(SipHashTest, PointerAuthSipHash) {
   // Test some basic cases.

@ojhunt
Copy link
Contributor

ojhunt commented Sep 29, 2025

Have you verified arm64e tests are unaffected? In principle codegen should be fine due to truncation, but there's a builtin (__builtin_ptrauth_string_discriminator) which may fail

@melver
Copy link
Contributor Author

melver commented Sep 29, 2025

Have you verified arm64e tests are unaffected? In principle codegen should be fine due to truncation, but there's a builtin (__builtin_ptrauth_string_discriminator) which may fail

This should be a non-functional change for getPointerAuthStableSipHash() - I just factored out part of it into a separate function that we now expose:

-  uint64_t RawHash = endian::read64le(RawHashBytes);
+  return endian::read64le(RawHashBytes);
+}
+
+/// Compute an ABI-stable 16-bit hash of the given string.
+uint16_t llvm::getPointerAuthStableSipHash(StringRef Str) {
+  uint64_t RawHash = getStableSipHash(Str);

Did I miss something?

@melver melver merged commit 3408e6a into main Sep 29, 2025
13 checks passed
@melver melver deleted the users/melver/spr/support-add-siphash-based-64-bit-stable-hash-function branch September 29, 2025 13:56
@ojhunt
Copy link
Contributor

ojhunt commented Sep 30, 2025

Have you verified arm64e tests are unaffected? In principle codegen should be fine due to truncation, but there's a builtin (__builtin_ptrauth_string_discriminator) which may fail

This should be a non-functional change for getPointerAuthStableSipHash() - I just factored out part of it into a separate function that we now expose:

-  uint64_t RawHash = endian::read64le(RawHashBytes);
+  return endian::read64le(RawHashBytes);
+}
+
+/// Compute an ABI-stable 16-bit hash of the given string.
+uint16_t llvm::getPointerAuthStableSipHash(StringRef Str) {
+  uint64_t RawHash = getStableSipHash(Str);

Did I miss something?

Sorry I'm a muppet and misread the diff :D

mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Oct 3, 2025
Factor out the 64-bit hash calculation in getPointerAuthStableSipHash()
as getStableSipHash(). This allows using the full 64-bit hash where we
require a stable hash.

Similar to getPointerAuthStableSipHash(), the new hash function is meant
to be stable across platforms and compiler versions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants