Skip to content

Commit e0343b5

Browse files
committed
[Support] Integrate SipHash.cpp into libSupport.
Start building it as part of the library, with some minor tweaks compared to the reference implementation: - templatize cROUNDS/dROUNDS, as well as 8B/16B result type - replace assert with static_assert - use LLVM_FALLTHROUGH This also exports interfaces for SipHash-2-4-64/-128, and tests them using the reference test vectors.
1 parent aec3a94 commit e0343b5

File tree

5 files changed

+141
-1091
lines changed

5 files changed

+141
-1091
lines changed

llvm/include/llvm/Support/SipHash.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===--- SipHash.h - An ABI-stable string SipHash ---------------*- C++ -*-===//
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+
//
9+
// An implementation of SipHash, a hash function optimized for speed on
10+
// short inputs. Based on the SipHash reference implementation.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_SUPPORT_SIPHASH_H
15+
#define LLVM_SUPPORT_SIPHASH_H
16+
17+
#include <cstdint>
18+
19+
namespace llvm {
20+
21+
template <typename T> class ArrayRef;
22+
23+
/// Computes a SipHash-2-4 64-bit result.
24+
void getSipHash_2_4_64(ArrayRef<uint8_t> In, const uint8_t (&K)[16],
25+
uint8_t (&Out)[8]);
26+
27+
/// Computes a SipHash-2-4 128-bit result.
28+
void getSipHash_2_4_128(ArrayRef<uint8_t> In, const uint8_t (&K)[16],
29+
uint8_t (&Out)[16]);
30+
31+
} // end namespace llvm
32+
33+
#endif

llvm/lib/Support/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,6 @@ endif()
127127

128128
add_subdirectory(BLAKE3)
129129

130-
# Temporarily ignore SipHash.cpp before we fully integrate it into LLVMSupport.
131-
set(LLVM_OPTIONAL_SOURCES SipHash.cpp)
132-
133130
add_llvm_component_library(LLVMSupport
134131
ABIBreak.cpp
135132
AMDGPUMetadata.cpp
@@ -227,6 +224,7 @@ add_llvm_component_library(LLVMSupport
227224
SHA1.cpp
228225
SHA256.cpp
229226
Signposts.cpp
227+
SipHash.cpp
230228
SlowDynamicAPInt.cpp
231229
SmallPtrSet.cpp
232230
SmallVector.cpp

llvm/lib/Support/SipHash.cpp

Lines changed: 48 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,20 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "siphash.h"
10-
#include <assert.h>
11-
#include <stddef.h>
12-
#include <stdint.h>
13-
14-
// Lightly adapted from the SipHash reference C implementation by
15-
// Jean-Philippe Aumasson and Daniel J. Bernstein.
16-
17-
/* default: SipHash-2-4 */
18-
#ifndef cROUNDS
19-
#define cROUNDS 2
20-
#endif
21-
#ifndef dROUNDS
22-
#define dROUNDS 4
23-
#endif
9+
#include "llvm/Support/SipHash.h"
10+
#include "llvm/ADT/ArrayRef.h"
11+
#include "llvm/Support/Compiler.h"
12+
#include "llvm/Support/Endian.h"
13+
#include <cstdint>
2414

25-
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
26-
27-
#define U32TO8_LE(p, v) \
28-
(p)[0] = (uint8_t)((v)); \
29-
(p)[1] = (uint8_t)((v) >> 8); \
30-
(p)[2] = (uint8_t)((v) >> 16); \
31-
(p)[3] = (uint8_t)((v) >> 24);
15+
using namespace llvm;
16+
using namespace support;
3217

33-
#define U64TO8_LE(p, v) \
34-
U32TO8_LE((p), (uint32_t)((v))); \
35-
U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
18+
// Lightly adapted from the SipHash reference C implementation:
19+
// https://github.com/veorq/SipHash
20+
// by Jean-Philippe Aumasson and Daniel J. Bernstein
3621

37-
#define U8TO64_LE(p) \
38-
(((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
39-
((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
40-
((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
41-
((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
22+
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
4223

4324
#define SIPROUND \
4425
do { \
@@ -58,27 +39,30 @@
5839
v2 = ROTL(v2, 32); \
5940
} while (0)
6041

61-
/*
62-
Computes a SipHash value
63-
*in: pointer to input data (read-only)
64-
inlen: input data length in bytes (any size_t value)
65-
*k: pointer to the key data (read-only), must be 16 bytes
66-
*out: pointer to output data (write-only), outlen bytes must be allocated
67-
outlen: length of the output in bytes, must be 8 or 16
68-
*/
69-
int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
70-
const size_t outlen) {
42+
namespace {
43+
44+
/// Computes a SipHash value
45+
///
46+
/// \param in: pointer to input data (read-only)
47+
/// \param inlen: input data length in bytes (any size_t value)
48+
/// \param k: reference to the key data 16-byte array (read-only)
49+
/// \returns output data, must be 8 or 16 bytes
50+
///
51+
template <int cROUNDS, int dROUNDS, size_t outlen>
52+
void siphash(const unsigned char *in, uint64_t inlen,
53+
const unsigned char (&k)[16], unsigned char (&out)[outlen]) {
7154

7255
const unsigned char *ni = (const unsigned char *)in;
7356
const unsigned char *kk = (const unsigned char *)k;
7457

75-
assert((outlen == 8) || (outlen == 16));
58+
static_assert(outlen == 8 || outlen == 16, "result should be 8 or 16 bytes");
59+
7660
uint64_t v0 = UINT64_C(0x736f6d6570736575);
7761
uint64_t v1 = UINT64_C(0x646f72616e646f6d);
7862
uint64_t v2 = UINT64_C(0x6c7967656e657261);
7963
uint64_t v3 = UINT64_C(0x7465646279746573);
80-
uint64_t k0 = U8TO64_LE(kk);
81-
uint64_t k1 = U8TO64_LE(kk + 8);
64+
uint64_t k0 = endian::read64le(kk);
65+
uint64_t k1 = endian::read64le(kk + 8);
8266
uint64_t m;
8367
int i;
8468
const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t));
@@ -93,7 +77,7 @@ int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
9377
v1 ^= 0xee;
9478

9579
for (; ni != end; ni += 8) {
96-
m = U8TO64_LE(ni);
80+
m = endian::read64le(ni);
9781
v3 ^= m;
9882

9983
for (i = 0; i < cROUNDS; ++i)
@@ -105,22 +89,22 @@ int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
10589
switch (left) {
10690
case 7:
10791
b |= ((uint64_t)ni[6]) << 48;
108-
/* FALLTHRU */
92+
LLVM_FALLTHROUGH;
10993
case 6:
11094
b |= ((uint64_t)ni[5]) << 40;
111-
/* FALLTHRU */
95+
LLVM_FALLTHROUGH;
11296
case 5:
11397
b |= ((uint64_t)ni[4]) << 32;
114-
/* FALLTHRU */
98+
LLVM_FALLTHROUGH;
11599
case 4:
116100
b |= ((uint64_t)ni[3]) << 24;
117-
/* FALLTHRU */
101+
LLVM_FALLTHROUGH;
118102
case 3:
119103
b |= ((uint64_t)ni[2]) << 16;
120-
/* FALLTHRU */
104+
LLVM_FALLTHROUGH;
121105
case 2:
122106
b |= ((uint64_t)ni[1]) << 8;
123-
/* FALLTHRU */
107+
LLVM_FALLTHROUGH;
124108
case 1:
125109
b |= ((uint64_t)ni[0]);
126110
break;
@@ -144,18 +128,28 @@ int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
144128
SIPROUND;
145129

146130
b = v0 ^ v1 ^ v2 ^ v3;
147-
U64TO8_LE(out, b);
131+
endian::write64le(out, b);
148132

149133
if (outlen == 8)
150-
return 0;
134+
return;
151135

152136
v1 ^= 0xdd;
153137

154138
for (i = 0; i < dROUNDS; ++i)
155139
SIPROUND;
156140

157141
b = v0 ^ v1 ^ v2 ^ v3;
158-
U64TO8_LE(out + 8, b);
142+
endian::write64le(out + 8, b);
143+
}
144+
145+
} // end anonymous namespace
146+
147+
void llvm::getSipHash_2_4_64(ArrayRef<uint8_t> In, const uint8_t (&K)[16],
148+
uint8_t (&Out)[8]) {
149+
siphash<2, 4>(In.data(), In.size(), K, Out);
150+
}
159151

160-
return 0;
152+
void llvm::getSipHash_2_4_128(ArrayRef<uint8_t> In, const uint8_t (&K)[16],
153+
uint8_t (&Out)[16]) {
154+
siphash<2, 4>(In.data(), In.size(), K, Out);
161155
}

llvm/unittests/Support/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ set(LLVM_LINK_COMPONENTS
33
TargetParser
44
)
55

6-
# Temporarily ignore SipHashTest.cpp before we fully integrate it.
7-
set(LLVM_OPTIONAL_SOURCES SipHashTest.cpp)
8-
96
add_llvm_unittest(SupportTests
107
AddressRangeTest.cpp
118
AlignmentTest.cpp
@@ -78,6 +75,7 @@ add_llvm_unittest(SupportTests
7875
ScopedPrinterTest.cpp
7976
SHA256.cpp
8077
SignalsTest.cpp
78+
SipHashTest.cpp
8179
SourceMgrTest.cpp
8280
SpecialCaseListTest.cpp
8381
SuffixTreeTest.cpp

0 commit comments

Comments
 (0)