[clang] 2f4c387 - Move KCFI type ID hash helpers out of LLVMSupport (#196784)
via cfe-commits
cfe-commits at lists.llvm.org
Sun May 10 10:26:40 PDT 2026
Author: Fangrui Song
Date: 2026-05-10T10:26:34-07:00
New Revision: 2f4c387147f1617e242dd500960410728e5ec35e
URL: https://github.com/llvm/llvm-project/commit/2f4c387147f1617e242dd500960410728e5ec35e
DIFF: https://github.com/llvm/llvm-project/commit/2f4c387147f1617e242dd500960410728e5ec35e.diff
LOG: Move KCFI type ID hash helpers out of LLVMSupport (#196784)
PR #167254 inappropriately introduced llvm/Support/Hash.{h,cpp} for the
KCFI helpers. The name is misleading — it has nothing to do with the
generic hashing facility in llvm/ADT/Hashing.h — and KCFI is a
CodeGen/IR feature that does not belong in the foundational Support
layer.
Move the files to llvm/lib/Transforms/Utils/KCFIHash.cpp, alongside
setKCFIType, which is the only existing KCFI helper in TransformUtils.
Also relocate the deprecated pre-xxh3 xxHash64 implementation into
KCFIHash.cpp, the sole user. clang/test/CodeGen/kcfi-generalize.c and
kcfi-normalize.c are end-to-end regression tests for the xxHash64 output
Added:
llvm/include/llvm/Transforms/Utils/KCFIHash.h
llvm/lib/Transforms/Utils/KCFIHash.cpp
Modified:
clang/include/clang/Basic/CodeGenOptions.h
clang/lib/CodeGen/CodeGenModule.cpp
llvm/include/llvm/Support/xxhash.h
llvm/lib/Support/CMakeLists.txt
llvm/lib/Support/xxhash.cpp
llvm/lib/Transforms/Utils/CMakeLists.txt
llvm/lib/Transforms/Utils/ModuleUtils.cpp
llvm/unittests/Support/xxhashTest.cpp
Removed:
llvm/include/llvm/Support/Hash.h
llvm/lib/Support/Hash.cpp
################################################################################
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 3cbbf1a3074ac..e43112b4bb98b 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -22,10 +22,10 @@
#include "llvm/Frontend/Driver/CodeGenOptions.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/CodeGen.h"
-#include "llvm/Support/Hash.h"
#include "llvm/Support/Regex.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
+#include "llvm/Transforms/Utils/KCFIHash.h"
#include <map>
#include <memory>
#include <string>
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 106f1e63cd904..2d91b7eaa52dc 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -70,7 +70,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Hash.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
@@ -78,6 +77,7 @@
#include "llvm/TargetParser/X86TargetParser.h"
#include "llvm/Transforms/Instrumentation/KCFI.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
+#include "llvm/Transforms/Utils/KCFIHash.h"
#include <optional>
#include <set>
diff --git a/llvm/include/llvm/Support/xxhash.h b/llvm/include/llvm/Support/xxhash.h
index 15c4f1bfd4563..b03aaa1e907b4 100644
--- a/llvm/include/llvm/Support/xxhash.h
+++ b/llvm/include/llvm/Support/xxhash.h
@@ -32,9 +32,6 @@
- xxHash source repository : https://github.com/Cyan4973/xxHash
*/
-/* based on revision d2df04efcbef7d7f6886d345861e5dfda4edacc1 Removed
- * everything but a simple interface for computing XXh64. */
-
#ifndef LLVM_SUPPORT_XXHASH_H
#define LLVM_SUPPORT_XXHASH_H
@@ -44,9 +41,6 @@
namespace llvm {
-// Deprecated pre-xxh3 64-bit hash.
-LLVM_ABI uint64_t xxHash64(const uint8_t *data, size_t len);
-
/// XXH3's 64-bit variant. Inline ArrayRef and StringRef overloads live in
/// llvm/ADT/ArrayRef.h and llvm/ADT/StringRef.h.
LLVM_ABI uint64_t xxh3_64bits(const uint8_t *data, size_t len);
diff --git a/llvm/include/llvm/Support/Hash.h b/llvm/include/llvm/Transforms/Utils/KCFIHash.h
similarity index 78%
rename from llvm/include/llvm/Support/Hash.h
rename to llvm/include/llvm/Transforms/Utils/KCFIHash.h
index 7a2cfb8774ae8..553c24d1289aa 100644
--- a/llvm/include/llvm/Support/Hash.h
+++ b/llvm/include/llvm/Transforms/Utils/KCFIHash.h
@@ -1,4 +1,4 @@
-//===- llvm/Support/Hash.h - Hash functions --------------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
//
-// This file provides hash functions.
+// Helpers for computing the 32-bit KCFI type ID from a mangled type name.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_HASH_H
-#define LLVM_SUPPORT_HASH_H
+#ifndef LLVM_TRANSFORMS_UTILS_KCFIHASH_H
+#define LLVM_TRANSFORMS_UTILS_KCFIHASH_H
#include "llvm/ADT/StringRef.h"
#include <cstdint>
@@ -34,4 +34,4 @@ LLVM_ABI uint32_t getKCFITypeID(StringRef MangledTypeName,
} // end namespace llvm
-#endif // LLVM_SUPPORT_HASH_H
+#endif // LLVM_TRANSFORMS_UTILS_KCFIHASH_H
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index e8d505f218b69..100cfb567c348 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -204,7 +204,6 @@ add_llvm_component_library(LLVMSupport
FormatVariadic.cpp
GlobPattern.cpp
GraphWriter.cpp
- Hash.cpp
HexagonAttributeParser.cpp
HexagonAttributes.cpp
InitLLVM.cpp
diff --git a/llvm/lib/Support/Hash.cpp b/llvm/lib/Support/Hash.cpp
deleted file mode 100644
index 6b5d000ee27c9..0000000000000
--- a/llvm/lib/Support/Hash.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- Hash.cpp - Hash functions ---------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements hash functions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Hash.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/xxhash.h"
-
-using namespace llvm;
-
-KCFIHashAlgorithm llvm::parseKCFIHashAlgorithm(StringRef Name) {
- if (Name == "FNV-1a")
- return KCFIHashAlgorithm::FNV1a;
- // Default to xxHash64 for backward compatibility
- return KCFIHashAlgorithm::xxHash64;
-}
-
-StringRef llvm::stringifyKCFIHashAlgorithm(KCFIHashAlgorithm Algorithm) {
- switch (Algorithm) {
- case KCFIHashAlgorithm::xxHash64:
- return "xxHash64";
- case KCFIHashAlgorithm::FNV1a:
- return "FNV-1a";
- }
- llvm_unreachable("Unknown KCFI hash algorithm");
-}
-
-uint32_t llvm::getKCFITypeID(StringRef MangledTypeName,
- KCFIHashAlgorithm Algorithm) {
- switch (Algorithm) {
- case KCFIHashAlgorithm::xxHash64:
- // Use lower 32 bits of xxHash64
- return static_cast<uint32_t>(
- xxHash64(reinterpret_cast<const uint8_t *>(MangledTypeName.data()),
- MangledTypeName.size()));
- case KCFIHashAlgorithm::FNV1a:
- // FNV-1a hash (32-bit)
- uint32_t Hash = 2166136261u; // FNV offset basis
- for (unsigned char C : MangledTypeName) {
- Hash ^= C;
- Hash *= 16777619u; // FNV prime
- }
- return Hash;
- }
- llvm_unreachable("Unknown KCFI hash algorithm");
-}
diff --git a/llvm/lib/Support/xxhash.cpp b/llvm/lib/Support/xxhash.cpp
index 6997fed7e8336..a1aee00b82637 100644
--- a/llvm/lib/Support/xxhash.cpp
+++ b/llvm/lib/Support/xxhash.cpp
@@ -32,9 +32,6 @@
* - xxHash source repository : https://github.com/Cyan4973/xxHash
*/
-// xxhash64 is based on commit d2df04efcbef7d7f6886d345861e5dfda4edacc1. Removed
-// everything but a simple interface for computing xxh64.
-
// xxh3_64bits is based on commit d5891596637d21366b9b1dcf2c0007a3edb26a9e (July
// 2023).
@@ -77,20 +74,6 @@ static const uint64_t PRIME64_3 = 1609587929392839161ULL;
static const uint64_t PRIME64_4 = 9650029242287828579ULL;
static const uint64_t PRIME64_5 = 2870177450012600261ULL;
-static uint64_t round(uint64_t Acc, uint64_t Input) {
- Acc += Input * PRIME64_2;
- Acc = rotl64(Acc, 31);
- Acc *= PRIME64_1;
- return Acc;
-}
-
-static uint64_t mergeRound(uint64_t Acc, uint64_t Val) {
- Val = round(0, Val);
- Acc ^= Val;
- Acc = Acc * PRIME64_1 + PRIME64_4;
- return Acc;
-}
-
static uint64_t XXH64_avalanche(uint64_t hash) {
hash ^= hash >> 33;
hash *= PRIME64_2;
@@ -100,64 +83,6 @@ static uint64_t XXH64_avalanche(uint64_t hash) {
return hash;
}
-uint64_t llvm::xxHash64(const uint8_t *P, size_t Len) {
- uint64_t Seed = 0;
- const uint8_t *const BEnd = P + Len;
- uint64_t H64;
-
- if (Len >= 32) {
- const unsigned char *const Limit = BEnd - 32;
- uint64_t V1 = Seed + PRIME64_1 + PRIME64_2;
- uint64_t V2 = Seed + PRIME64_2;
- uint64_t V3 = Seed + 0;
- uint64_t V4 = Seed - PRIME64_1;
-
- do {
- V1 = round(V1, endian::read64le(P));
- P += 8;
- V2 = round(V2, endian::read64le(P));
- P += 8;
- V3 = round(V3, endian::read64le(P));
- P += 8;
- V4 = round(V4, endian::read64le(P));
- P += 8;
- } while (P <= Limit);
-
- H64 = rotl64(V1, 1) + rotl64(V2, 7) + rotl64(V3, 12) + rotl64(V4, 18);
- H64 = mergeRound(H64, V1);
- H64 = mergeRound(H64, V2);
- H64 = mergeRound(H64, V3);
- H64 = mergeRound(H64, V4);
-
- } else {
- H64 = Seed + PRIME64_5;
- }
-
- H64 += (uint64_t)Len;
-
- while (reinterpret_cast<uintptr_t>(P) + 8 <=
- reinterpret_cast<uintptr_t>(BEnd)) {
- uint64_t const K1 = round(0, endian::read64le(P));
- H64 ^= K1;
- H64 = rotl64(H64, 27) * PRIME64_1 + PRIME64_4;
- P += 8;
- }
-
- if (reinterpret_cast<uintptr_t>(P) + 4 <= reinterpret_cast<uintptr_t>(BEnd)) {
- H64 ^= (uint64_t)(endian::read32le(P)) * PRIME64_1;
- H64 = rotl64(H64, 23) * PRIME64_2 + PRIME64_3;
- P += 4;
- }
-
- while (P < BEnd) {
- H64 ^= (*P) * PRIME64_5;
- H64 = rotl64(H64, 11) * PRIME64_1;
- P++;
- }
-
- return XXH64_avalanche(H64);
-}
-
constexpr size_t XXH3_SECRETSIZE_MIN = 136;
constexpr size_t XXH_SECRET_DEFAULT_SIZE = 192;
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 82e9edf674866..933e204081ad2 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -40,6 +40,7 @@ add_llvm_component_library(LLVMTransformUtils
Instrumentation.cpp
IntegerDivision.cpp
IRNormalizer.cpp
+ KCFIHash.cpp
LCSSA.cpp
LibCallsShrinkWrap.cpp
Local.cpp
diff --git a/llvm/lib/Transforms/Utils/KCFIHash.cpp b/llvm/lib/Transforms/Utils/KCFIHash.cpp
new file mode 100644
index 0000000000000..df65ed53b66b6
--- /dev/null
+++ b/llvm/lib/Transforms/Utils/KCFIHash.cpp
@@ -0,0 +1,142 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/KCFIHash.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+using namespace support;
+
+// xxHash64 is a deprecated pre-xxh3 hash, retained here only as the default
+// KCFI type-ID hash for ABI compatibility.
+
+static uint64_t rotl64(uint64_t X, size_t R) {
+ return (X << R) | (X >> (64 - R));
+}
+
+constexpr uint64_t PRIME64_1 = 11400714785074694791ULL;
+constexpr uint64_t PRIME64_2 = 14029467366897019727ULL;
+constexpr uint64_t PRIME64_3 = 1609587929392839161ULL;
+constexpr uint64_t PRIME64_4 = 9650029242287828579ULL;
+constexpr uint64_t PRIME64_5 = 2870177450012600261ULL;
+
+static uint64_t round(uint64_t Acc, uint64_t Input) {
+ Acc += Input * PRIME64_2;
+ Acc = rotl64(Acc, 31);
+ Acc *= PRIME64_1;
+ return Acc;
+}
+
+static uint64_t mergeRound(uint64_t Acc, uint64_t Val) {
+ Val = round(0, Val);
+ Acc ^= Val;
+ Acc = Acc * PRIME64_1 + PRIME64_4;
+ return Acc;
+}
+
+static uint64_t avalanche(uint64_t H) {
+ H ^= H >> 33;
+ H *= PRIME64_2;
+ H ^= H >> 29;
+ H *= PRIME64_3;
+ H ^= H >> 32;
+ return H;
+}
+
+static uint64_t xxHash64(const uint8_t *P, size_t Len) {
+ const uint8_t *const BEnd = P + Len;
+ uint64_t H64;
+
+ if (Len >= 32) {
+ const uint8_t *const Limit = BEnd - 32;
+ uint64_t V1 = PRIME64_1 + PRIME64_2;
+ uint64_t V2 = PRIME64_2;
+ uint64_t V3 = 0;
+ uint64_t V4 = -PRIME64_1;
+
+ do {
+ V1 = round(V1, endian::read64le(P));
+ P += 8;
+ V2 = round(V2, endian::read64le(P));
+ P += 8;
+ V3 = round(V3, endian::read64le(P));
+ P += 8;
+ V4 = round(V4, endian::read64le(P));
+ P += 8;
+ } while (P <= Limit);
+
+ H64 = rotl64(V1, 1) + rotl64(V2, 7) + rotl64(V3, 12) + rotl64(V4, 18);
+ H64 = mergeRound(H64, V1);
+ H64 = mergeRound(H64, V2);
+ H64 = mergeRound(H64, V3);
+ H64 = mergeRound(H64, V4);
+ } else {
+ H64 = PRIME64_5;
+ }
+
+ H64 += (uint64_t)Len;
+
+ while (reinterpret_cast<uintptr_t>(P) + 8 <=
+ reinterpret_cast<uintptr_t>(BEnd)) {
+ H64 ^= round(0, endian::read64le(P));
+ H64 = rotl64(H64, 27) * PRIME64_1 + PRIME64_4;
+ P += 8;
+ }
+
+ if (reinterpret_cast<uintptr_t>(P) + 4 <= reinterpret_cast<uintptr_t>(BEnd)) {
+ H64 ^= (uint64_t)endian::read32le(P) * PRIME64_1;
+ H64 = rotl64(H64, 23) * PRIME64_2 + PRIME64_3;
+ P += 4;
+ }
+
+ while (P < BEnd) {
+ H64 ^= (*P) * PRIME64_5;
+ H64 = rotl64(H64, 11) * PRIME64_1;
+ ++P;
+ }
+
+ return avalanche(H64);
+}
+
+KCFIHashAlgorithm llvm::parseKCFIHashAlgorithm(StringRef Name) {
+ if (Name == "FNV-1a")
+ return KCFIHashAlgorithm::FNV1a;
+ // Default to xxHash64 for backward compatibility
+ return KCFIHashAlgorithm::xxHash64;
+}
+
+StringRef llvm::stringifyKCFIHashAlgorithm(KCFIHashAlgorithm Algorithm) {
+ switch (Algorithm) {
+ case KCFIHashAlgorithm::xxHash64:
+ return "xxHash64";
+ case KCFIHashAlgorithm::FNV1a:
+ return "FNV-1a";
+ }
+ llvm_unreachable("Unknown KCFI hash algorithm");
+}
+
+uint32_t llvm::getKCFITypeID(StringRef MangledTypeName,
+ KCFIHashAlgorithm Algorithm) {
+ switch (Algorithm) {
+ case KCFIHashAlgorithm::xxHash64:
+ // Use lower 32 bits of xxHash64
+ return static_cast<uint32_t>(
+ xxHash64(reinterpret_cast<const uint8_t *>(MangledTypeName.data()),
+ MangledTypeName.size()));
+ case KCFIHashAlgorithm::FNV1a:
+ // FNV-1a hash (32-bit)
+ uint32_t Hash = 2166136261u; // FNV offset basis
+ for (unsigned char C : MangledTypeName) {
+ Hash ^= C;
+ Hash *= 16777619u; // FNV prime
+ }
+ return Hash;
+ }
+ llvm_unreachable("Unknown KCFI hash algorithm");
+}
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 63a234960a0ad..2976ebf46c9b7 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -19,9 +19,9 @@
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/Hash.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/KCFIHash.h"
using namespace llvm;
diff --git a/llvm/unittests/Support/xxhashTest.cpp b/llvm/unittests/Support/xxhashTest.cpp
index 9f91fc79e1f62..6097f0525e2b2 100644
--- a/llvm/unittests/Support/xxhashTest.cpp
+++ b/llvm/unittests/Support/xxhashTest.cpp
@@ -32,18 +32,6 @@ static void fillTestBuffer(uint8_t *buffer, size_t len) {
}
}
-TEST(xxhashTest, Basic) {
- EXPECT_EQ(0xef46db3751d8e999U, xxHash64(nullptr, 0));
- EXPECT_EQ(0x33bf00a859c4ba3fU,
- xxHash64(reinterpret_cast<const uint8_t *>("foo"), 3));
- EXPECT_EQ(0x48a37c90ad27a659U,
- xxHash64(reinterpret_cast<const uint8_t *>("bar"), 3));
- EXPECT_EQ(0x69196c1b3af0bff9U,
- xxHash64(reinterpret_cast<const uint8_t *>(
- "0123456789abcdefghijklmnopqrstuvwxyz"),
- 36));
-}
-
TEST(xxhashTest, xxh3) {
constexpr size_t size = 2243;
uint8_t a[size];
More information about the cfe-commits
mailing list