LLVM 23.0.0git
KCFIHash.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
10#include "llvm/Support/Endian.h"
12
13using namespace llvm;
14using namespace support;
15
16// xxHash64 is a deprecated pre-xxh3 hash, retained here only as the default
17// KCFI type-ID hash for ABI compatibility.
18
19static uint64_t rotl64(uint64_t X, size_t R) {
20 return (X << R) | (X >> (64 - R));
21}
22
23constexpr uint64_t PRIME64_1 = 11400714785074694791ULL;
24constexpr uint64_t PRIME64_2 = 14029467366897019727ULL;
25constexpr uint64_t PRIME64_3 = 1609587929392839161ULL;
26constexpr uint64_t PRIME64_4 = 9650029242287828579ULL;
27constexpr uint64_t PRIME64_5 = 2870177450012600261ULL;
28
30 Acc += Input * PRIME64_2;
31 Acc = rotl64(Acc, 31);
32 Acc *= PRIME64_1;
33 return Acc;
34}
35
37 Val = round(0, Val);
38 Acc ^= Val;
39 Acc = Acc * PRIME64_1 + PRIME64_4;
40 return Acc;
41}
42
44 H ^= H >> 33;
45 H *= PRIME64_2;
46 H ^= H >> 29;
47 H *= PRIME64_3;
48 H ^= H >> 32;
49 return H;
50}
51
52static uint64_t xxHash64(const uint8_t *P, size_t Len) {
53 const uint8_t *const BEnd = P + Len;
54 uint64_t H64;
55
56 if (Len >= 32) {
57 const uint8_t *const Limit = BEnd - 32;
60 uint64_t V3 = 0;
61 uint64_t V4 = -PRIME64_1;
62
63 do {
64 V1 = round(V1, endian::read64le(P));
65 P += 8;
66 V2 = round(V2, endian::read64le(P));
67 P += 8;
68 V3 = round(V3, endian::read64le(P));
69 P += 8;
70 V4 = round(V4, endian::read64le(P));
71 P += 8;
72 } while (P <= Limit);
73
74 H64 = rotl64(V1, 1) + rotl64(V2, 7) + rotl64(V3, 12) + rotl64(V4, 18);
75 H64 = mergeRound(H64, V1);
76 H64 = mergeRound(H64, V2);
77 H64 = mergeRound(H64, V3);
78 H64 = mergeRound(H64, V4);
79 } else {
80 H64 = PRIME64_5;
81 }
82
83 H64 += (uint64_t)Len;
84
85 while (reinterpret_cast<uintptr_t>(P) + 8 <=
86 reinterpret_cast<uintptr_t>(BEnd)) {
87 H64 ^= round(0, endian::read64le(P));
88 H64 = rotl64(H64, 27) * PRIME64_1 + PRIME64_4;
89 P += 8;
90 }
91
92 if (reinterpret_cast<uintptr_t>(P) + 4 <= reinterpret_cast<uintptr_t>(BEnd)) {
94 H64 = rotl64(H64, 23) * PRIME64_2 + PRIME64_3;
95 P += 4;
96 }
97
98 while (P < BEnd) {
99 H64 ^= (*P) * PRIME64_5;
100 H64 = rotl64(H64, 11) * PRIME64_1;
101 ++P;
102 }
103
104 return avalanche(H64);
105}
106
108 if (Name == "FNV-1a")
110 // Default to xxHash64 for backward compatibility
112}
113
115 switch (Algorithm) {
117 return "xxHash64";
119 return "FNV-1a";
120 }
121 llvm_unreachable("Unknown KCFI hash algorithm");
122}
123
125 KCFIHashAlgorithm Algorithm) {
126 switch (Algorithm) {
128 // Use lower 32 bits of xxHash64
129 return static_cast<uint32_t>(
130 xxHash64(reinterpret_cast<const uint8_t *>(MangledTypeName.data()),
131 MangledTypeName.size()));
133 // FNV-1a hash (32-bit)
134 uint32_t Hash = 2166136261u; // FNV offset basis
135 for (unsigned char C : MangledTypeName) {
136 Hash ^= C;
137 Hash *= 16777619u; // FNV prime
138 }
139 return Hash;
140 }
141 llvm_unreachable("Unknown KCFI hash algorithm");
142}
#define X(NUM, ENUM, NAME)
Definition ELF.h:851
static uint64_t mergeRound(uint64_t Acc, uint64_t Val)
Definition KCFIHash.cpp:36
static uint64_t avalanche(uint64_t H)
Definition KCFIHash.cpp:43
static uint64_t rotl64(uint64_t X, size_t R)
Definition KCFIHash.cpp:19
static uint64_t round(uint64_t Acc, uint64_t Input)
Definition KCFIHash.cpp:29
#define H(x, y, z)
Definition MD5.cpp:56
#define P(N)
The Input class is used to parse a yaml document into in-memory structs and vectors.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
uint64_t read64le(const void *P)
Definition Endian.h:435
uint32_t read32le(const void *P)
Definition Endian.h:432
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI KCFIHashAlgorithm parseKCFIHashAlgorithm(StringRef Name)
Parse a KCFI hash algorithm name.
Definition KCFIHash.cpp:107
KCFIHashAlgorithm
Definition KCFIHash.h:21
LLVM_ABI StringRef stringifyKCFIHashAlgorithm(KCFIHashAlgorithm Algorithm)
Convert a KCFI hash algorithm enum to its string representation.
Definition KCFIHash.cpp:114
LLVM_ABI uint32_t getKCFITypeID(StringRef MangledTypeName, KCFIHashAlgorithm Algorithm)
Compute KCFI type ID from mangled type name.
Definition KCFIHash.cpp:124
static const uint64_t PRIME64_3
Definition xxhash.cpp:73
static const uint64_t PRIME64_1
Definition xxhash.cpp:71
static const uint64_t PRIME64_2
Definition xxhash.cpp:72
static const uint64_t PRIME64_4
Definition xxhash.cpp:74
static const uint64_t PRIME64_5
Definition xxhash.cpp:75