mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-02 02:51:42 +00:00
[wpiutil] Upgrade to LLVM 17.0.1 (#5482)
This commit is contained in:
@@ -103,7 +103,7 @@ bool convertUTF16ToUTF8String(std::span<const char> SrcBytes, SmallVectorImpl<ch
|
||||
if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
|
||||
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
|
||||
for (UTF16 &I : ByteSwapped)
|
||||
I = wpi::ByteSwap_16(I);
|
||||
I = wpi::byteswap<uint16_t>(I);
|
||||
Src = &ByteSwapped[0];
|
||||
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
|
||||
}
|
||||
@@ -161,7 +161,7 @@ bool convertUTF32ToUTF8String(std::span<const char> SrcBytes, std::string &Out)
|
||||
if (Src[0] == UNI_UTF32_BYTE_ORDER_MARK_SWAPPED) {
|
||||
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
|
||||
for (UTF32 &I : ByteSwapped)
|
||||
I = wpi::ByteSwap_32(I);
|
||||
I = wpi::byteswap<uint32_t>(I);
|
||||
Src = &ByteSwapped[0];
|
||||
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/StringMap.h"
|
||||
#include "wpi/DJB.h"
|
||||
#include "wpi/MathExtras.h"
|
||||
#include "wpi/ReverseIteration.h"
|
||||
#include "wpi/xxhash.h"
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
@@ -84,7 +85,9 @@ unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
|
||||
// Hash table unallocated so far?
|
||||
if (NumBuckets == 0)
|
||||
init(16);
|
||||
unsigned FullHashValue = djbHash(Name, 0);
|
||||
unsigned FullHashValue = xxh3_64bits(Name);
|
||||
if (shouldReverseIterate())
|
||||
FullHashValue = ~FullHashValue;
|
||||
unsigned BucketNo = FullHashValue & (NumBuckets - 1);
|
||||
unsigned *HashTable = getHashTable(TheTable, NumBuckets);
|
||||
|
||||
@@ -139,7 +142,9 @@ unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
|
||||
int StringMapImpl::FindKey(std::string_view Key) const {
|
||||
if (NumBuckets == 0)
|
||||
return -1; // Really empty table?
|
||||
unsigned FullHashValue = djbHash(Key, 0);
|
||||
unsigned FullHashValue = xxh3_64bits(Key);
|
||||
if (shouldReverseIterate())
|
||||
FullHashValue = ~FullHashValue;
|
||||
unsigned BucketNo = FullHashValue & (NumBuckets - 1);
|
||||
unsigned *HashTable = getHashTable(TheTable, NumBuckets);
|
||||
|
||||
|
||||
407
wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/xxhash.cpp
vendored
Normal file
407
wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/xxhash.cpp
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* xxHash - Fast Hash algorithm
|
||||
* Copyright (C) 2012-2021, Yann Collet
|
||||
*
|
||||
* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - xxHash homepage: http://www.xxhash.com
|
||||
* - 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).
|
||||
|
||||
#include "wpi/xxhash.h"
|
||||
#include "wpi/Compiler.h"
|
||||
#include "wpi/Endian.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace wpi;
|
||||
using namespace support;
|
||||
|
||||
static uint64_t rotl64(uint64_t X, size_t R) {
|
||||
return (X << R) | (X >> (64 - R));
|
||||
}
|
||||
|
||||
constexpr uint32_t PRIME32_1 = 0x9E3779B1;
|
||||
constexpr uint32_t PRIME32_2 = 0x85EBCA77;
|
||||
constexpr uint32_t PRIME32_3 = 0xC2B2AE3D;
|
||||
|
||||
static const uint64_t PRIME64_1 = 11400714785074694791ULL;
|
||||
static const uint64_t PRIME64_2 = 14029467366897019727ULL;
|
||||
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;
|
||||
hash ^= hash >> 29;
|
||||
hash *= PRIME64_3;
|
||||
hash ^= hash >> 32;
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint64_t wpi::xxHash64(std::string_view Data) {
|
||||
size_t Len = Data.size();
|
||||
uint64_t Seed = 0;
|
||||
const unsigned char *P = reinterpret_cast<const unsigned char*>(Data.data());
|
||||
const unsigned char *const BEnd = P + Data.size();
|
||||
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);
|
||||
}
|
||||
|
||||
uint64_t wpi::xxHash64(std::span<const uint8_t> Data) {
|
||||
return xxHash64({(const char *)Data.data(), Data.size()});
|
||||
}
|
||||
|
||||
constexpr size_t XXH3_SECRETSIZE_MIN = 136;
|
||||
constexpr size_t XXH_SECRET_DEFAULT_SIZE = 192;
|
||||
|
||||
/* Pseudorandom data taken directly from FARSH */
|
||||
// clang-format off
|
||||
constexpr uint8_t kSecret[XXH_SECRET_DEFAULT_SIZE] = {
|
||||
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
|
||||
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
|
||||
0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
|
||||
0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
|
||||
0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
|
||||
0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
|
||||
0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
|
||||
0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
|
||||
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
|
||||
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
|
||||
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
|
||||
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
constexpr uint64_t PRIME_MX1 = 0x165667919E3779F9;
|
||||
constexpr uint64_t PRIME_MX2 = 0x9FB21C651E98DF25;
|
||||
|
||||
// Calculates a 64-bit to 128-bit multiply, then XOR folds it.
|
||||
static uint64_t XXH3_mul128_fold64(uint64_t lhs, uint64_t rhs) {
|
||||
#if defined(__SIZEOF_INT128__) || \
|
||||
(defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128)
|
||||
__uint128_t product = (__uint128_t)lhs * (__uint128_t)rhs;
|
||||
return uint64_t(product) ^ uint64_t(product >> 64);
|
||||
|
||||
#else
|
||||
/* First calculate all of the cross products. */
|
||||
const uint64_t lo_lo = (lhs & 0xFFFFFFFF) * (rhs & 0xFFFFFFFF);
|
||||
const uint64_t hi_lo = (lhs >> 32) * (rhs & 0xFFFFFFFF);
|
||||
const uint64_t lo_hi = (lhs & 0xFFFFFFFF) * (rhs >> 32);
|
||||
const uint64_t hi_hi = (lhs >> 32) * (rhs >> 32);
|
||||
|
||||
/* Now add the products together. These will never overflow. */
|
||||
const uint64_t cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
|
||||
const uint64_t upper = (hi_lo >> 32) + (cross >> 32) + hi_hi;
|
||||
const uint64_t lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);
|
||||
|
||||
return upper ^ lower;
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr size_t XXH_STRIPE_LEN = 64;
|
||||
constexpr size_t XXH_SECRET_CONSUME_RATE = 8;
|
||||
constexpr size_t XXH_ACC_NB = XXH_STRIPE_LEN / sizeof(uint64_t);
|
||||
|
||||
static uint64_t XXH3_avalanche(uint64_t hash) {
|
||||
hash ^= hash >> 37;
|
||||
hash *= PRIME_MX1;
|
||||
hash ^= hash >> 32;
|
||||
return hash;
|
||||
}
|
||||
|
||||
static uint64_t XXH3_len_1to3_64b(const uint8_t *input, size_t len,
|
||||
const uint8_t *secret, uint64_t seed) {
|
||||
const uint8_t c1 = input[0];
|
||||
const uint8_t c2 = input[len >> 1];
|
||||
const uint8_t c3 = input[len - 1];
|
||||
uint32_t combined = ((uint32_t)c1 << 16) | ((uint32_t)c2 << 24) |
|
||||
((uint32_t)c3 << 0) | ((uint32_t)len << 8);
|
||||
uint64_t bitflip =
|
||||
(uint64_t)(endian::read32le(secret) ^ endian::read32le(secret + 4)) +
|
||||
seed;
|
||||
return XXH64_avalanche(uint64_t(combined) ^ bitflip);
|
||||
}
|
||||
|
||||
static uint64_t XXH3_len_4to8_64b(const uint8_t *input, size_t len,
|
||||
const uint8_t *secret, uint64_t seed) {
|
||||
seed ^= (uint64_t)byteswap(uint32_t(seed)) << 32;
|
||||
const uint32_t input1 = endian::read32le(input);
|
||||
const uint32_t input2 = endian::read32le(input + len - 4);
|
||||
uint64_t acc =
|
||||
(endian::read64le(secret + 8) ^ endian::read64le(secret + 16)) - seed;
|
||||
const uint64_t input64 = (uint64_t)input2 | ((uint64_t)input1 << 32);
|
||||
acc ^= input64;
|
||||
// XXH3_rrmxmx(acc, len)
|
||||
acc ^= rotl64(acc, 49) ^ rotl64(acc, 24);
|
||||
acc *= PRIME_MX2;
|
||||
acc ^= (acc >> 35) + (uint64_t)len;
|
||||
acc *= PRIME_MX2;
|
||||
return acc ^ (acc >> 28);
|
||||
}
|
||||
|
||||
static uint64_t XXH3_len_9to16_64b(const uint8_t *input, size_t len,
|
||||
const uint8_t *secret, uint64_t const seed) {
|
||||
uint64_t input_lo =
|
||||
(endian::read64le(secret + 24) ^ endian::read64le(secret + 32)) + seed;
|
||||
uint64_t input_hi =
|
||||
(endian::read64le(secret + 40) ^ endian::read64le(secret + 48)) - seed;
|
||||
input_lo ^= endian::read64le(input);
|
||||
input_hi ^= endian::read64le(input + len - 8);
|
||||
uint64_t acc = uint64_t(len) + byteswap(input_lo) + input_hi +
|
||||
XXH3_mul128_fold64(input_lo, input_hi);
|
||||
return XXH3_avalanche(acc);
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static uint64_t XXH3_len_0to16_64b(const uint8_t *input, size_t len,
|
||||
const uint8_t *secret, uint64_t const seed) {
|
||||
if (LLVM_LIKELY(len > 8))
|
||||
return XXH3_len_9to16_64b(input, len, secret, seed);
|
||||
if (LLVM_LIKELY(len >= 4))
|
||||
return XXH3_len_4to8_64b(input, len, secret, seed);
|
||||
if (len != 0)
|
||||
return XXH3_len_1to3_64b(input, len, secret, seed);
|
||||
return XXH64_avalanche(seed ^ endian::read64le(secret + 56) ^
|
||||
endian::read64le(secret + 64));
|
||||
}
|
||||
|
||||
static uint64_t XXH3_mix16B(const uint8_t *input, uint8_t const *secret,
|
||||
uint64_t seed) {
|
||||
uint64_t lhs = seed;
|
||||
uint64_t rhs = 0U - seed;
|
||||
lhs += endian::read64le(secret);
|
||||
rhs += endian::read64le(secret + 8);
|
||||
lhs ^= endian::read64le(input);
|
||||
rhs ^= endian::read64le(input + 8);
|
||||
return XXH3_mul128_fold64(lhs, rhs);
|
||||
}
|
||||
|
||||
/* For mid range keys, XXH3 uses a Mum-hash variant. */
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static uint64_t XXH3_len_17to128_64b(const uint8_t *input, size_t len,
|
||||
const uint8_t *secret,
|
||||
uint64_t const seed) {
|
||||
uint64_t acc = len * PRIME64_1, acc_end;
|
||||
acc += XXH3_mix16B(input + 0, secret + 0, seed);
|
||||
acc_end = XXH3_mix16B(input + len - 16, secret + 16, seed);
|
||||
if (len > 32) {
|
||||
acc += XXH3_mix16B(input + 16, secret + 32, seed);
|
||||
acc_end += XXH3_mix16B(input + len - 32, secret + 48, seed);
|
||||
if (len > 64) {
|
||||
acc += XXH3_mix16B(input + 32, secret + 64, seed);
|
||||
acc_end += XXH3_mix16B(input + len - 48, secret + 80, seed);
|
||||
if (len > 96) {
|
||||
acc += XXH3_mix16B(input + 48, secret + 96, seed);
|
||||
acc_end += XXH3_mix16B(input + len - 64, secret + 112, seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
return XXH3_avalanche(acc + acc_end);
|
||||
}
|
||||
|
||||
constexpr size_t XXH3_MIDSIZE_MAX = 240;
|
||||
|
||||
LLVM_ATTRIBUTE_NOINLINE
|
||||
static uint64_t XXH3_len_129to240_64b(const uint8_t *input, size_t len,
|
||||
const uint8_t *secret, uint64_t seed) {
|
||||
constexpr size_t XXH3_MIDSIZE_STARTOFFSET = 3;
|
||||
constexpr size_t XXH3_MIDSIZE_LASTOFFSET = 17;
|
||||
uint64_t acc = (uint64_t)len * PRIME64_1;
|
||||
const unsigned nbRounds = len / 16;
|
||||
for (unsigned i = 0; i < 8; ++i)
|
||||
acc += XXH3_mix16B(input + 16 * i, secret + 16 * i, seed);
|
||||
acc = XXH3_avalanche(acc);
|
||||
|
||||
for (unsigned i = 8; i < nbRounds; ++i) {
|
||||
acc += XXH3_mix16B(input + 16 * i,
|
||||
secret + 16 * (i - 8) + XXH3_MIDSIZE_STARTOFFSET, seed);
|
||||
}
|
||||
/* last bytes */
|
||||
acc +=
|
||||
XXH3_mix16B(input + len - 16,
|
||||
secret + XXH3_SECRETSIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed);
|
||||
return XXH3_avalanche(acc);
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static void XXH3_accumulate_512_scalar(uint64_t *acc, const uint8_t *input,
|
||||
const uint8_t *secret) {
|
||||
for (size_t i = 0; i < XXH_ACC_NB; ++i) {
|
||||
uint64_t data_val = endian::read64le(input + 8 * i);
|
||||
uint64_t data_key = data_val ^ endian::read64le(secret + 8 * i);
|
||||
acc[i ^ 1] += data_val;
|
||||
acc[i] += uint32_t(data_key) * (data_key >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
static void XXH3_accumulate_scalar(uint64_t *acc, const uint8_t *input,
|
||||
const uint8_t *secret, size_t nbStripes) {
|
||||
for (size_t n = 0; n < nbStripes; ++n)
|
||||
XXH3_accumulate_512_scalar(acc, input + n * XXH_STRIPE_LEN,
|
||||
secret + n * XXH_SECRET_CONSUME_RATE);
|
||||
}
|
||||
|
||||
static void XXH3_scrambleAcc(uint64_t *acc, const uint8_t *secret) {
|
||||
for (size_t i = 0; i < XXH_ACC_NB; ++i) {
|
||||
acc[i] ^= acc[i] >> 47;
|
||||
acc[i] ^= endian::read64le(secret + 8 * i);
|
||||
acc[i] *= PRIME32_1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t XXH3_mix2Accs(const uint64_t *acc, const uint8_t *secret) {
|
||||
return XXH3_mul128_fold64(acc[0] ^ endian::read64le(secret),
|
||||
acc[1] ^ endian::read64le(secret + 8));
|
||||
}
|
||||
|
||||
static uint64_t XXH3_mergeAccs(const uint64_t *acc, const uint8_t *key,
|
||||
uint64_t start) {
|
||||
uint64_t result64 = start;
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
result64 += XXH3_mix2Accs(acc + 2 * i, key + 16 * i);
|
||||
return XXH3_avalanche(result64);
|
||||
}
|
||||
|
||||
LLVM_ATTRIBUTE_NOINLINE
|
||||
static uint64_t XXH3_hashLong_64b(const uint8_t *input, size_t len,
|
||||
const uint8_t *secret, size_t secretSize) {
|
||||
const size_t nbStripesPerBlock =
|
||||
(secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE;
|
||||
const size_t block_len = XXH_STRIPE_LEN * nbStripesPerBlock;
|
||||
const size_t nb_blocks = (len - 1) / block_len;
|
||||
alignas(16) uint64_t acc[XXH_ACC_NB] = {
|
||||
PRIME32_3, PRIME64_1, PRIME64_2, PRIME64_3,
|
||||
PRIME64_4, PRIME32_2, PRIME64_5, PRIME32_1,
|
||||
};
|
||||
for (size_t n = 0; n < nb_blocks; ++n) {
|
||||
XXH3_accumulate_scalar(acc, input + n * block_len, secret,
|
||||
nbStripesPerBlock);
|
||||
XXH3_scrambleAcc(acc, secret + secretSize - XXH_STRIPE_LEN);
|
||||
}
|
||||
|
||||
/* last partial block */
|
||||
const size_t nbStripes = (len - 1 - (block_len * nb_blocks)) / XXH_STRIPE_LEN;
|
||||
assert(nbStripes <= secretSize / XXH_SECRET_CONSUME_RATE);
|
||||
XXH3_accumulate_scalar(acc, input + nb_blocks * block_len, secret, nbStripes);
|
||||
|
||||
/* last stripe */
|
||||
constexpr size_t XXH_SECRET_LASTACC_START = 7;
|
||||
XXH3_accumulate_512_scalar(acc, input + len - XXH_STRIPE_LEN,
|
||||
secret + secretSize - XXH_STRIPE_LEN -
|
||||
XXH_SECRET_LASTACC_START);
|
||||
|
||||
/* converge into final hash */
|
||||
constexpr size_t XXH_SECRET_MERGEACCS_START = 11;
|
||||
return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START,
|
||||
(uint64_t)len * PRIME64_1);
|
||||
}
|
||||
|
||||
uint64_t wpi::xxh3_64bits(std::span<const uint8_t> data) {
|
||||
auto *in = data.data();
|
||||
size_t len = data.size();
|
||||
if (len <= 16)
|
||||
return XXH3_len_0to16_64b(in, len, kSecret, 0);
|
||||
if (len <= 128)
|
||||
return XXH3_len_17to128_64b(in, len, kSecret, 0);
|
||||
if (len <= XXH3_MIDSIZE_MAX)
|
||||
return XXH3_len_129to240_64b(in, len, kSecret, 0);
|
||||
return XXH3_hashLong_64b(in, len, kSecret, sizeof(kSecret));
|
||||
}
|
||||
103
wpiutil/src/main/native/thirdparty/llvm/include/wpi/ADL.h
vendored
Normal file
103
wpiutil/src/main/native/thirdparty/llvm/include/wpi/ADL.h
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
//===- llvm/ADT/ADL.h - Argument dependent lookup utilities -----*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_ADL_H
|
||||
#define WPIUTIL_WPI_ADL_H
|
||||
|
||||
#include <type_traits>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
// Only used by compiler if both template types are the same. Useful when
|
||||
// using SFINAE to test for the existence of member functions.
|
||||
template <typename T, T> struct SameType;
|
||||
|
||||
namespace adl_detail {
|
||||
|
||||
using std::begin;
|
||||
|
||||
template <typename RangeT>
|
||||
constexpr auto begin_impl(RangeT &&range)
|
||||
-> decltype(begin(std::forward<RangeT>(range))) {
|
||||
return begin(std::forward<RangeT>(range));
|
||||
}
|
||||
|
||||
using std::end;
|
||||
|
||||
template <typename RangeT>
|
||||
constexpr auto end_impl(RangeT &&range)
|
||||
-> decltype(end(std::forward<RangeT>(range))) {
|
||||
return end(std::forward<RangeT>(range));
|
||||
}
|
||||
|
||||
using std::swap;
|
||||
|
||||
template <typename T>
|
||||
constexpr void swap_impl(T &&lhs,
|
||||
T &&rhs) noexcept(noexcept(swap(std::declval<T>(),
|
||||
std::declval<T>()))) {
|
||||
swap(std::forward<T>(lhs), std::forward<T>(rhs));
|
||||
}
|
||||
|
||||
using std::size;
|
||||
|
||||
template <typename RangeT>
|
||||
constexpr auto size_impl(RangeT &&range)
|
||||
-> decltype(size(std::forward<RangeT>(range))) {
|
||||
return size(std::forward<RangeT>(range));
|
||||
}
|
||||
|
||||
} // end namespace adl_detail
|
||||
|
||||
/// Returns the begin iterator to \p range using `std::begin` and
|
||||
/// function found through Argument-Dependent Lookup (ADL).
|
||||
template <typename RangeT>
|
||||
constexpr auto adl_begin(RangeT &&range)
|
||||
-> decltype(adl_detail::begin_impl(std::forward<RangeT>(range))) {
|
||||
return adl_detail::begin_impl(std::forward<RangeT>(range));
|
||||
}
|
||||
|
||||
/// Returns the end iterator to \p range using `std::end` and
|
||||
/// functions found through Argument-Dependent Lookup (ADL).
|
||||
template <typename RangeT>
|
||||
constexpr auto adl_end(RangeT &&range)
|
||||
-> decltype(adl_detail::end_impl(std::forward<RangeT>(range))) {
|
||||
return adl_detail::end_impl(std::forward<RangeT>(range));
|
||||
}
|
||||
|
||||
/// Swaps \p lhs with \p rhs using `std::swap` and functions found through
|
||||
/// Argument-Dependent Lookup (ADL).
|
||||
template <typename T>
|
||||
constexpr void adl_swap(T &&lhs, T &&rhs) noexcept(
|
||||
noexcept(adl_detail::swap_impl(std::declval<T>(), std::declval<T>()))) {
|
||||
adl_detail::swap_impl(std::forward<T>(lhs), std::forward<T>(rhs));
|
||||
}
|
||||
|
||||
/// Returns the size of \p range using `std::size` and functions found through
|
||||
/// Argument-Dependent Lookup (ADL).
|
||||
template <typename RangeT>
|
||||
constexpr auto adl_size(RangeT &&range)
|
||||
-> decltype(adl_detail::size_impl(std::forward<RangeT>(range))) {
|
||||
return adl_detail::size_impl(std::forward<RangeT>(range));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename RangeT>
|
||||
using IterOfRange = decltype(adl_begin(std::declval<RangeT &>()));
|
||||
|
||||
template <typename RangeT>
|
||||
using ValueOfRange =
|
||||
std::remove_reference_t<decltype(*adl_begin(std::declval<RangeT &>()))>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace wpi
|
||||
|
||||
#endif // WPIUTIL_WPI_ADL_H
|
||||
@@ -19,6 +19,12 @@
|
||||
#ifndef WPIUTIL_WPI_ALLOCATORBASE_H
|
||||
#define WPIUTIL_WPI_ALLOCATORBASE_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define LLVM_ALLOCATORHOLDER_EMPTYBASE __declspec(empty_bases)
|
||||
#else
|
||||
#define LLVM_ALLOCATORHOLDER_EMPTYBASE
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include "wpi/Compiler.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include <type_traits>
|
||||
@@ -72,7 +78,7 @@ public:
|
||||
|
||||
/// Deallocate space for a sequence of objects without constructing them.
|
||||
template <typename T>
|
||||
std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value, void>
|
||||
std::enable_if_t<!std::is_same_v<std::remove_cv_t<T>, void>, void>
|
||||
Deallocate(T *Ptr, size_t Num = 1) {
|
||||
Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T), alignof(T));
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ template <typename To, typename From, typename Enabler = void> struct isa_impl {
|
||||
|
||||
// Always allow upcasts, and perform no dynamic check for them.
|
||||
template <typename To, typename From>
|
||||
struct isa_impl<To, From, std::enable_if_t<std::is_base_of<To, From>::value>> {
|
||||
struct isa_impl<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> {
|
||||
static inline bool doit(const From &) { return true; }
|
||||
};
|
||||
|
||||
@@ -231,7 +231,7 @@ struct cast_convert_val<To, FromTy *, FromTy *> {
|
||||
|
||||
template <class X> struct is_simple_type {
|
||||
static const bool value =
|
||||
std::is_same<X, typename simplify_type<X>::SimpleType>::value;
|
||||
std::is_same_v<X, typename simplify_type<X>::SimpleType>;
|
||||
};
|
||||
|
||||
// } // namespace detail
|
||||
@@ -275,8 +275,7 @@ struct CastIsPossible<To, std::optional<From>> {
|
||||
/// Upcasting (from derived to base) and casting from a type to itself should
|
||||
/// always be possible.
|
||||
template <typename To, typename From>
|
||||
struct CastIsPossible<To, From,
|
||||
std::enable_if_t<std::is_base_of<To, From>::value>> {
|
||||
struct CastIsPossible<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> {
|
||||
static inline bool isPossible(const From &f) { return true; }
|
||||
};
|
||||
|
||||
@@ -319,7 +318,7 @@ namespace detail {
|
||||
/// A helper to derive the type to use with `Self` for cast traits, when the
|
||||
/// provided CRTP derived type is allowed to be void.
|
||||
template <typename OptionalDerived, typename Default>
|
||||
using SelfType = std::conditional_t<std::is_same<OptionalDerived, void>::value,
|
||||
using SelfType = std::conditional_t<std::is_same_v<OptionalDerived, void>,
|
||||
Default, OptionalDerived>;
|
||||
} // namespace detail
|
||||
|
||||
@@ -390,8 +389,8 @@ struct ConstStrippingForwardingCast {
|
||||
// Remove the pointer if it exists, then we can get rid of consts/volatiles.
|
||||
using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>;
|
||||
// Now if it's a pointer, add it back. Otherwise, we want a ref.
|
||||
using NonConstFrom = std::conditional_t<std::is_pointer<From>::value,
|
||||
DecayedFrom *, DecayedFrom &>;
|
||||
using NonConstFrom =
|
||||
std::conditional_t<std::is_pointer_v<From>, DecayedFrom *, DecayedFrom &>;
|
||||
|
||||
static inline bool isPossible(const From &f) {
|
||||
return ForwardTo::isPossible(const_cast<NonConstFrom>(f));
|
||||
|
||||
@@ -114,12 +114,24 @@
|
||||
/// LLVM_EXTERNAL_VISIBILITY - classes, functions, and variables marked with
|
||||
/// this attribute will be made public and visible outside of any shared library
|
||||
/// they are linked in to.
|
||||
#if __has_attribute(visibility) && \
|
||||
(!(defined(_WIN32) || defined(__CYGWIN__)) || \
|
||||
|
||||
#if LLVM_HAS_CPP_ATTRIBUTE(gnu::visibility)
|
||||
#define LLVM_ATTRIBUTE_VISIBILITY_HIDDEN [[gnu::visibility("hidden")]]
|
||||
#define LLVM_ATTRIBUTE_VISIBILITY_DEFAULT [[gnu::visibility("default")]]
|
||||
#elif __has_attribute(visibility)
|
||||
#define LLVM_ATTRIBUTE_VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
|
||||
#define LLVM_ATTRIBUTE_VISIBILITY_DEFAULT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_VISIBILITY_HIDDEN
|
||||
#define LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
|
||||
#endif
|
||||
|
||||
|
||||
#if (!(defined(_WIN32) || defined(__CYGWIN__)) || \
|
||||
(defined(__MINGW32__) && defined(__clang__)))
|
||||
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
|
||||
#define LLVM_LIBRARY_VISIBILITY LLVM_ATTRIBUTE_VISIBILITY_HIDDEN
|
||||
#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
|
||||
#define LLVM_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
|
||||
#define LLVM_EXTERNAL_VISIBILITY LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
|
||||
#else
|
||||
#define LLVM_EXTERNAL_VISIBILITY
|
||||
#endif
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
//===-- llvm/Support/DJB.h ---DJB Hash --------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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 contains support for the DJ Bernstein hash function.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_DJB_H
|
||||
#define WPIUTIL_WPI_DJB_H
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
/// The Bernstein hash function used by the DWARF accelerator tables.
|
||||
inline uint32_t djbHash(std::string_view Buffer, uint32_t H = 5381) {
|
||||
for (unsigned char C : Buffer)
|
||||
H = (H << 5) + H + C;
|
||||
return H;
|
||||
}
|
||||
|
||||
} // namespace wpi
|
||||
|
||||
#endif // WPIUTIL_WPI_DJB_H
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "wpi/ReverseIteration.h"
|
||||
#include "wpi/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
@@ -141,10 +142,15 @@ public:
|
||||
setNumTombstones(0);
|
||||
}
|
||||
|
||||
/// Return true if the specified key is in the map, false otherwise.
|
||||
bool contains(const_arg_type_t<KeyT> Val) const {
|
||||
const BucketT *TheBucket;
|
||||
return LookupBucketFor(Val, TheBucket);
|
||||
}
|
||||
|
||||
/// Return 1 if the specified key is in the map, 0 otherwise.
|
||||
size_type count(const_arg_type_t<KeyT> Val) const {
|
||||
const BucketT *TheBucket;
|
||||
return LookupBucketFor(Val, TheBucket) ? 1 : 0;
|
||||
return contains(Val) ? 1 : 0;
|
||||
}
|
||||
|
||||
iterator find(const_arg_type_t<KeyT> Val) {
|
||||
@@ -201,6 +207,14 @@ public:
|
||||
return ValueT();
|
||||
}
|
||||
|
||||
/// at - Return the entry for the specified key, or abort if no such
|
||||
/// entry exists.
|
||||
const ValueT &at(const_arg_type_t<KeyT> Val) const {
|
||||
auto Iter = this->find(std::move(Val));
|
||||
assert(Iter != this->end() && "DenseMap::at failed due to a missing key");
|
||||
return Iter->second;
|
||||
}
|
||||
|
||||
// Inserts key,value pair into the map if the key isn't already in the map.
|
||||
// If the key is already in the map, it returns false and doesn't update the
|
||||
// value.
|
||||
@@ -299,6 +313,20 @@ public:
|
||||
insert(*I);
|
||||
}
|
||||
|
||||
/// Returns the value associated to the key in the map if it exists. If it
|
||||
/// does not exist, emplace a default value for the key and returns a
|
||||
/// reference to the newly created value.
|
||||
ValueT &getOrInsertDefault(KeyT &&Key) {
|
||||
return try_emplace(Key).first->second;
|
||||
}
|
||||
|
||||
/// Returns the value associated to the key in the map if it exists. If it
|
||||
/// does not exist, emplace a default value for the key and returns a
|
||||
/// reference to the newly created value.
|
||||
ValueT &getOrInsertDefault(const KeyT &Key) {
|
||||
return try_emplace(Key).first->second;
|
||||
}
|
||||
|
||||
bool erase(const KeyT &Val) {
|
||||
BucketT *TheBucket;
|
||||
if (!LookupBucketFor(Val, TheBucket))
|
||||
@@ -906,7 +934,7 @@ class SmallDenseMap
|
||||
public:
|
||||
explicit SmallDenseMap(unsigned NumInitBuckets = 0) {
|
||||
if (NumInitBuckets > InlineBuckets)
|
||||
NumInitBuckets = NextPowerOf2(NumInitBuckets - 1);
|
||||
NumInitBuckets = std::bit_ceil(NumInitBuckets);
|
||||
init(NumInitBuckets);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
@@ -234,6 +233,14 @@ struct DenseMapInfo<std::pair<T, U>> {
|
||||
SecondInfo::getHashValue(PairVal.second));
|
||||
}
|
||||
|
||||
// Expose an additional function intended to be used by other
|
||||
// specializations of DenseMapInfo without needing to know how
|
||||
// to combine hash values manually
|
||||
static unsigned getHashValuePiecewise(const T &First, const U &Second) {
|
||||
return detail::combineHashValue(FirstInfo::getHashValue(First),
|
||||
SecondInfo::getHashValue(Second));
|
||||
}
|
||||
|
||||
static bool isEqual(const Pair &LHS, const Pair &RHS) {
|
||||
return FirstInfo::isEqual(LHS.first, RHS.first) &&
|
||||
SecondInfo::isEqual(LHS.second, RHS.second);
|
||||
@@ -290,37 +297,6 @@ template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
|
||||
}
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for variants whose all alternatives have DenseMapInfo.
|
||||
template <typename... Ts> struct DenseMapInfo<std::variant<Ts...>> {
|
||||
using Variant = std::variant<Ts...>;
|
||||
using FirstT = std::variant_alternative_t<0, Variant>;
|
||||
|
||||
static inline Variant getEmptyKey() {
|
||||
return Variant(std::in_place_index<0>, DenseMapInfo<FirstT>::getEmptyKey());
|
||||
}
|
||||
|
||||
static inline Variant getTombstoneKey() {
|
||||
return Variant(std::in_place_index<0>,
|
||||
DenseMapInfo<FirstT>::getTombstoneKey());
|
||||
}
|
||||
|
||||
static unsigned getHashValue(const Variant &Val) {
|
||||
return std::visit(
|
||||
[&Val](auto &&Alternative) {
|
||||
using T = std::decay_t<decltype(Alternative)>;
|
||||
// Include index in hash to make sure same value as different
|
||||
// alternatives don't collide.
|
||||
return detail::combineHashValue(
|
||||
DenseMapInfo<size_t>::getHashValue(Val.index()),
|
||||
DenseMapInfo<T>::getHashValue(Alternative));
|
||||
},
|
||||
Val);
|
||||
}
|
||||
|
||||
static bool isEqual(const Variant &LHS, const Variant &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
} // end namespace wpi
|
||||
|
||||
#endif // WPIUTIL_WPI_DENSEMAPINFO_H
|
||||
|
||||
71
wpiutil/src/main/native/thirdparty/llvm/include/wpi/DenseMapInfoVariant.h
vendored
Normal file
71
wpiutil/src/main/native/thirdparty/llvm/include/wpi/DenseMapInfoVariant.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
//===- DenseMapInfoVariant.h - Type traits for DenseMap<variant> *- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines DenseMapInfo traits for DenseMap<std::variant<Ts...>>.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_DENSEMAPINFOVARIANT_H
|
||||
#define WPIUTIL_WPI_DENSEMAPINFOVARIANT_H
|
||||
|
||||
#include "wpi/DenseMapInfo.h"
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
// Provide DenseMapInfo for variants whose all alternatives have DenseMapInfo.
|
||||
template <typename... Ts> struct DenseMapInfo<std::variant<Ts...>> {
|
||||
using Variant = std::variant<Ts...>;
|
||||
using FirstT = std::variant_alternative_t<0, Variant>;
|
||||
|
||||
static inline Variant getEmptyKey() {
|
||||
return Variant(std::in_place_index<0>, DenseMapInfo<FirstT>::getEmptyKey());
|
||||
}
|
||||
|
||||
static inline Variant getTombstoneKey() {
|
||||
return Variant(std::in_place_index<0>,
|
||||
DenseMapInfo<FirstT>::getTombstoneKey());
|
||||
}
|
||||
|
||||
static unsigned getHashValue(const Variant &Val) {
|
||||
return std::visit(
|
||||
[&Val](auto &&Alternative) {
|
||||
using T = std::decay_t<decltype(Alternative)>;
|
||||
// Include index in hash to make sure same value as different
|
||||
// alternatives don't collide.
|
||||
return DenseMapInfo<std::pair<size_t, T>>::getHashValuePiecewise(
|
||||
Val.index(), Alternative);
|
||||
},
|
||||
Val);
|
||||
}
|
||||
|
||||
static bool isEqual(const Variant &LHS, const Variant &RHS) {
|
||||
if (LHS.index() != RHS.index())
|
||||
return false;
|
||||
if (LHS.valueless_by_exception())
|
||||
return true;
|
||||
// We want to dispatch to DenseMapInfo<T>::isEqual(LHS.get(I), RHS.get(I))
|
||||
// We know the types are the same, but std::visit(V, LHS, RHS) doesn't.
|
||||
// We erase the type held in LHS to void*, and dispatch over RHS.
|
||||
const void *ErasedLHS =
|
||||
std::visit([](const auto &LHS) -> const void * { return &LHS; }, LHS);
|
||||
return std::visit(
|
||||
[&](const auto &RHS) -> bool {
|
||||
using T = std::remove_cv_t<std::remove_reference_t<decltype(RHS)>>;
|
||||
return DenseMapInfo<T>::isEqual(*static_cast<const T *>(ErasedLHS),
|
||||
RHS);
|
||||
},
|
||||
RHS);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace wpi
|
||||
|
||||
#endif // WPIUTIL_WPI_DENSEMAPINFOVARIANT_H
|
||||
@@ -22,6 +22,7 @@
|
||||
namespace wpi {
|
||||
|
||||
#ifndef NDEBUG //ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
|
||||
#define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE
|
||||
|
||||
/// A base class for data structure classes wishing to make iterators
|
||||
/// ("handles") pointing into themselves fail-fast. When building without
|
||||
@@ -77,6 +78,11 @@ public:
|
||||
};
|
||||
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE __declspec(empty_bases)
|
||||
#else
|
||||
#define LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE
|
||||
#endif // _MSC_VER
|
||||
|
||||
class DebugEpochBase {
|
||||
public:
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace wpi {
|
||||
void install_fatal_error_handler(fatal_error_handler_t handler,
|
||||
void *user_data = nullptr);
|
||||
|
||||
/// Restores default error handling behavior.
|
||||
/// Restores default error handling behaviour.
|
||||
void remove_fatal_error_handler();
|
||||
|
||||
/// ScopedFatalErrorHandler - This is a simple helper class which just
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace detail {
|
||||
|
||||
template <typename T>
|
||||
using EnableIfTrivial =
|
||||
std::enable_if_t<wpi::is_trivially_move_constructible<T>::value &&
|
||||
std::enable_if_t<std::is_trivially_move_constructible<T>::value &&
|
||||
std::is_trivially_destructible<T>::value>;
|
||||
template <typename CallableT, typename ThisT>
|
||||
using EnableUnlessSameType =
|
||||
@@ -107,11 +107,11 @@ protected:
|
||||
template <typename T> struct AdjustedParamTBase {
|
||||
static_assert(!std::is_reference<T>::value,
|
||||
"references should be handled by template specialization");
|
||||
using type = std::conditional_t<
|
||||
wpi::is_trivially_copy_constructible<T>::value &&
|
||||
wpi::is_trivially_move_constructible<T>::value &&
|
||||
IsSizeLessThanThresholdT<T>::value,
|
||||
T, T &>;
|
||||
using type =
|
||||
std::conditional_t<std::is_trivially_copy_constructible<T>::value &&
|
||||
std::is_trivially_move_constructible<T>::value &&
|
||||
IsSizeLessThanThresholdT<T>::value,
|
||||
T, T &>;
|
||||
};
|
||||
|
||||
// This specialization ensures that 'AdjustedParam<V<T>&>' or
|
||||
@@ -179,16 +179,15 @@ protected:
|
||||
bool isInlineStorage() const { return CallbackAndInlineFlag.getInt(); }
|
||||
|
||||
bool isTrivialCallback() const {
|
||||
return CallbackAndInlineFlag.getPointer().template is<TrivialCallback *>();
|
||||
return isa<TrivialCallback *>(CallbackAndInlineFlag.getPointer());
|
||||
}
|
||||
|
||||
CallPtrT getTrivialCallback() const {
|
||||
return CallbackAndInlineFlag.getPointer().template get<TrivialCallback *>()->CallPtr;
|
||||
return cast<TrivialCallback *>(CallbackAndInlineFlag.getPointer())->CallPtr;
|
||||
}
|
||||
|
||||
NonTrivialCallbacks *getNonTrivialCallbacks() const {
|
||||
return CallbackAndInlineFlag.getPointer()
|
||||
.template get<NonTrivialCallbacks *>();
|
||||
return cast<NonTrivialCallbacks *>(CallbackAndInlineFlag.getPointer());
|
||||
}
|
||||
|
||||
CallPtrT getCallPtr() const {
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "wpi/SwapByteOrder.h"
|
||||
#include "wpi/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
@@ -223,29 +224,30 @@ inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t b = fetch64(s + 8);
|
||||
uint64_t c = fetch64(s + len - 8) * k2;
|
||||
uint64_t d = fetch64(s + len - 16) * k0;
|
||||
return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d,
|
||||
a + rotate(b ^ k3, 20) - c + len + seed);
|
||||
return hash_16_bytes(std::rotr<uint64_t>(a - b, 43) +
|
||||
std::rotr<uint64_t>(c ^ seed, 30) + d,
|
||||
a + std::rotr<uint64_t>(b ^ k3, 20) - c + len + seed);
|
||||
}
|
||||
|
||||
inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t z = fetch64(s + 24);
|
||||
uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0;
|
||||
uint64_t b = rotate(a + z, 52);
|
||||
uint64_t c = rotate(a, 37);
|
||||
uint64_t b = std::rotr<uint64_t>(a + z, 52);
|
||||
uint64_t c = std::rotr<uint64_t>(a, 37);
|
||||
a += fetch64(s + 8);
|
||||
c += rotate(a, 7);
|
||||
c += std::rotr<uint64_t>(a, 7);
|
||||
a += fetch64(s + 16);
|
||||
uint64_t vf = a + z;
|
||||
uint64_t vs = b + rotate(a, 31) + c;
|
||||
uint64_t vs = b + std::rotr<uint64_t>(a, 31) + c;
|
||||
a = fetch64(s + 16) + fetch64(s + len - 32);
|
||||
z = fetch64(s + len - 8);
|
||||
b = rotate(a + z, 52);
|
||||
c = rotate(a, 37);
|
||||
b = std::rotr<uint64_t>(a + z, 52);
|
||||
c = std::rotr<uint64_t>(a, 37);
|
||||
a += fetch64(s + len - 24);
|
||||
c += rotate(a, 7);
|
||||
c += std::rotr<uint64_t>(a, 7);
|
||||
a += fetch64(s + len - 16);
|
||||
uint64_t wf = a + z;
|
||||
uint64_t ws = b + rotate(a, 31) + c;
|
||||
uint64_t ws = b + std::rotr<uint64_t>(a, 31) + c;
|
||||
uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0);
|
||||
return shift_mix((seed ^ (r * k0)) + vs) * k2;
|
||||
}
|
||||
@@ -275,9 +277,13 @@ struct hash_state {
|
||||
/// seed and the first 64-byte chunk.
|
||||
/// This effectively performs the initial mix.
|
||||
static hash_state create(const char *s, uint64_t seed) {
|
||||
hash_state state = {
|
||||
0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49),
|
||||
seed * k1, shift_mix(seed), 0 };
|
||||
hash_state state = {0,
|
||||
seed,
|
||||
hash_16_bytes(seed, k1),
|
||||
std::rotr<uint64_t>(seed ^ k1, 49),
|
||||
seed * k1,
|
||||
shift_mix(seed),
|
||||
0};
|
||||
state.h6 = hash_16_bytes(state.h4, state.h5);
|
||||
state.mix(s);
|
||||
return state;
|
||||
@@ -288,10 +294,10 @@ struct hash_state {
|
||||
static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) {
|
||||
a += fetch64(s);
|
||||
uint64_t c = fetch64(s + 24);
|
||||
b = rotate(b + a + c, 21);
|
||||
b = std::rotr<uint64_t>(b + a + c, 21);
|
||||
uint64_t d = a;
|
||||
a += fetch64(s + 8) + fetch64(s + 16);
|
||||
b += rotate(a, 44) + d;
|
||||
b += std::rotr<uint64_t>(a, 44) + d;
|
||||
a += c;
|
||||
}
|
||||
|
||||
@@ -299,11 +305,11 @@ struct hash_state {
|
||||
/// We mix all 64 bytes even when the chunk length is smaller, but we
|
||||
/// record the actual length.
|
||||
void mix(const char *s) {
|
||||
h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1;
|
||||
h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1;
|
||||
h0 = std::rotr<uint64_t>(h0 + h1 + h3 + fetch64(s + 8), 37) * k1;
|
||||
h1 = std::rotr<uint64_t>(h1 + h4 + fetch64(s + 48), 42) * k1;
|
||||
h0 ^= h6;
|
||||
h1 += h3 + fetch64(s + 40);
|
||||
h2 = rotate(h2 + h5, 33) * k1;
|
||||
h2 = std::rotr<uint64_t>(h2 + h5, 33) * k1;
|
||||
h3 = h4 * k1;
|
||||
h4 = h0 + h5;
|
||||
mix_32_bytes(s, h3, h4);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/// This file implements a map that provides insertion order iteration. The
|
||||
/// interface is purposefully minimal. The key is assumed to be cheap to copy
|
||||
/// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
|
||||
/// a std::vector.
|
||||
/// a SmallVector.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -24,16 +24,15 @@
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
/// This class implements a map that also provides access to all stored values
|
||||
/// in a deterministic order. The values are kept in a std::vector and the
|
||||
/// in a deterministic order. The values are kept in a SmallVector<*, 0> and the
|
||||
/// mapping is done with DenseMap from Keys to indexes in that vector.
|
||||
template<typename KeyT, typename ValueT,
|
||||
typename MapType = DenseMap<KeyT, unsigned>,
|
||||
typename VectorType = std::vector<std::pair<KeyT, ValueT>>>
|
||||
template <typename KeyT, typename ValueT,
|
||||
typename MapType = DenseMap<KeyT, unsigned>,
|
||||
typename VectorType = SmallVector<std::pair<KeyT, ValueT>, 0>>
|
||||
class MapVector {
|
||||
MapType Map;
|
||||
VectorType Vector;
|
||||
@@ -140,10 +139,9 @@ public:
|
||||
return std::make_pair(begin() + I, false);
|
||||
}
|
||||
|
||||
size_type count(const KeyT &Key) const {
|
||||
typename MapType::const_iterator Pos = Map.find(Key);
|
||||
return Pos == Map.end()? 0 : 1;
|
||||
}
|
||||
bool contains(const KeyT &Key) const { return Map.find(Key) != Map.end(); }
|
||||
|
||||
size_type count(const KeyT &Key) const { return contains(Key) ? 1 : 0; }
|
||||
|
||||
iterator find(const KeyT &Key) {
|
||||
typename MapType::const_iterator Pos = Map.find(Key);
|
||||
|
||||
@@ -25,55 +25,10 @@
|
||||
|
||||
namespace wpi {
|
||||
|
||||
/// The behavior an operation has on an input of 0.
|
||||
enum ZeroBehavior {
|
||||
/// The returned value is undefined.
|
||||
ZB_Undefined,
|
||||
/// The returned value is numeric_limits<T>::max()
|
||||
ZB_Max
|
||||
};
|
||||
|
||||
/// Count number of 0's from the least significant bit to the most
|
||||
/// stopping at the first 1.
|
||||
///
|
||||
/// Only unsigned integral types are allowed.
|
||||
///
|
||||
/// Returns std::numeric_limits<T>::digits on an input of 0.
|
||||
template <typename T> unsigned countTrailingZeros(T Val) {
|
||||
static_assert(std::is_unsigned_v<T>,
|
||||
"Only unsigned integral types are allowed.");
|
||||
return std::countr_zero(Val);
|
||||
}
|
||||
|
||||
/// Count number of 0's from the most significant bit to the least
|
||||
/// stopping at the first 1.
|
||||
///
|
||||
/// Only unsigned integral types are allowed.
|
||||
///
|
||||
/// Returns std::numeric_limits<T>::digits on an input of 0.
|
||||
template <typename T> unsigned countLeadingZeros(T Val) {
|
||||
static_assert(std::is_unsigned_v<T>,
|
||||
"Only unsigned integral types are allowed.");
|
||||
return std::countl_zero(Val);
|
||||
}
|
||||
|
||||
/// Get the index of the first set bit starting from the least
|
||||
/// significant bit.
|
||||
///
|
||||
/// Only unsigned integral types are allowed.
|
||||
///
|
||||
/// \param ZB the behavior on an input of 0.
|
||||
template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
||||
if (ZB == ZB_Max && Val == 0)
|
||||
return (std::numeric_limits<T>::max)();
|
||||
|
||||
return std::countr_zero(Val);
|
||||
}
|
||||
|
||||
/// Create a bitmask with the N right-most bits set to 1, and all other
|
||||
/// bits set to 0. Only unsigned types are allowed.
|
||||
template <typename T> T maskTrailingOnes(unsigned N) {
|
||||
static_assert(std::is_unsigned<T>::value, "Invalid type!");
|
||||
static_assert(std::is_unsigned_v<T>, "Invalid type!");
|
||||
const unsigned Bits = CHAR_BIT * sizeof(T);
|
||||
assert(N <= Bits && "Invalid bit index");
|
||||
return N == 0 ? 0 : (T(-1) >> (Bits - N));
|
||||
@@ -97,21 +52,6 @@ template <typename T> T maskLeadingZeros(unsigned N) {
|
||||
return maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
|
||||
}
|
||||
|
||||
/// Get the index of the last set bit starting from the least
|
||||
/// significant bit.
|
||||
///
|
||||
/// Only unsigned integral types are allowed.
|
||||
///
|
||||
/// \param ZB the behavior on an input of 0.
|
||||
template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
||||
if (ZB == ZB_Max && Val == 0)
|
||||
return (std::numeric_limits<T>::max)();
|
||||
|
||||
// Use ^ instead of - because both gcc and llvm can remove the associated ^
|
||||
// in the __builtin_clz intrinsic on x86.
|
||||
return std::countl_zero(Val) ^ (std::numeric_limits<T>::digits - 1);
|
||||
}
|
||||
|
||||
/// Macro compressed bit reversal table for 256 bits.
|
||||
///
|
||||
/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
|
||||
@@ -304,42 +244,6 @@ constexpr inline bool isPowerOf2_64(uint64_t Value) {
|
||||
return std::has_single_bit(Value);
|
||||
}
|
||||
|
||||
/// Count the number of ones from the most significant bit to the first
|
||||
/// zero bit.
|
||||
///
|
||||
/// Ex. countLeadingOnes(0xFF0FFF00) == 8.
|
||||
/// Only unsigned integral types are allowed.
|
||||
///
|
||||
/// Returns std::numeric_limits<T>::digits on an input of all ones.
|
||||
template <typename T> unsigned countLeadingOnes(T Value) {
|
||||
static_assert(std::is_unsigned_v<T>,
|
||||
"Only unsigned integral types are allowed.");
|
||||
return std::countl_one<T>(Value);
|
||||
}
|
||||
|
||||
/// Count the number of ones from the least significant bit to the first
|
||||
/// zero bit.
|
||||
///
|
||||
/// Ex. countTrailingOnes(0x00FF00FF) == 8.
|
||||
/// Only unsigned integral types are allowed.
|
||||
///
|
||||
/// Returns std::numeric_limits<T>::digits on an input of all ones.
|
||||
template <typename T> unsigned countTrailingOnes(T Value) {
|
||||
static_assert(std::is_unsigned_v<T>,
|
||||
"Only unsigned integral types are allowed.");
|
||||
return std::countr_one<T>(Value);
|
||||
}
|
||||
|
||||
/// Count the number of set bits in a value.
|
||||
/// Ex. countPopulation(0xF000F000) = 8
|
||||
/// Returns 0 if the word is zero.
|
||||
template <typename T>
|
||||
inline unsigned countPopulation(T Value) {
|
||||
static_assert(std::is_unsigned_v<T>,
|
||||
"Only unsigned integral types are allowed.");
|
||||
return (unsigned)std::popcount(Value);
|
||||
}
|
||||
|
||||
/// Return true if the argument contains a non-empty sequence of ones with the
|
||||
/// remainder zero (32 bit version.) Ex. isShiftedMask_32(0x0000FF00U) == true.
|
||||
/// If true, \p MaskIdx will specify the index of the lowest set bit and \p
|
||||
@@ -403,34 +307,6 @@ inline unsigned Log2_64_Ceil(uint64_t Value) {
|
||||
return static_cast<unsigned>(64 - std::countl_zero(Value - 1));
|
||||
}
|
||||
|
||||
/// This function takes a 64-bit integer and returns the bit equivalent double.
|
||||
inline double BitsToDouble(uint64_t Bits) {
|
||||
static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes");
|
||||
return wpi::bit_cast<double>(Bits);
|
||||
}
|
||||
|
||||
/// This function takes a 32-bit integer and returns the bit equivalent float.
|
||||
inline float BitsToFloat(uint32_t Bits) {
|
||||
static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes");
|
||||
return wpi::bit_cast<float>(Bits);
|
||||
}
|
||||
|
||||
/// This function takes a double and returns the bit equivalent 64-bit integer.
|
||||
/// Note that copying doubles around changes the bits of NaNs on some hosts,
|
||||
/// notably x86, so this routine cannot be used if these bits are needed.
|
||||
inline uint64_t DoubleToBits(double Double) {
|
||||
static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes");
|
||||
return wpi::bit_cast<uint64_t>(Double);
|
||||
}
|
||||
|
||||
/// This function takes a float and returns the bit equivalent 32-bit integer.
|
||||
/// Note that copying floats around changes the bits of NaNs on some hosts,
|
||||
/// notably x86, so this routine cannot be used if these bits are needed.
|
||||
inline uint32_t FloatToBits(float Float) {
|
||||
static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes");
|
||||
return wpi::bit_cast<uint32_t>(Float);
|
||||
}
|
||||
|
||||
/// A and B are either alignments or offsets. Return the minimum alignment that
|
||||
/// may be assumed after adding the two together.
|
||||
constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) {
|
||||
@@ -454,12 +330,6 @@ constexpr inline uint64_t NextPowerOf2(uint64_t A) {
|
||||
return A + 1;
|
||||
}
|
||||
|
||||
/// Returns the power of two which is less than or equal to the given value.
|
||||
/// Essentially, it is a floor operation across the domain of powers of two.
|
||||
inline uint64_t PowerOf2Floor(uint64_t A) {
|
||||
return std::bit_floor(A);
|
||||
}
|
||||
|
||||
/// Returns the power of two which is greater than or equal to the given value.
|
||||
/// Essentially, it is a ceil operation across the domain of powers of two.
|
||||
inline uint64_t PowerOf2Ceil(uint64_t A) {
|
||||
@@ -567,7 +437,7 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
|
||||
/// Subtract two unsigned integers, X and Y, of type T and return the absolute
|
||||
/// value of the result.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_unsigned<T>::value, T> AbsoluteDifference(T X, T Y) {
|
||||
std::enable_if_t<std::is_unsigned_v<T>, T> AbsoluteDifference(T X, T Y) {
|
||||
return X > Y ? (X - Y) : (Y - X);
|
||||
}
|
||||
|
||||
@@ -575,7 +445,7 @@ std::enable_if_t<std::is_unsigned<T>::value, T> AbsoluteDifference(T X, T Y) {
|
||||
/// maximum representable value of T on overflow. ResultOverflowed indicates if
|
||||
/// the result is larger than the maximum representable value of type T.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_unsigned<T>::value, T>
|
||||
std::enable_if_t<std::is_unsigned_v<T>, T>
|
||||
SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
|
||||
bool Dummy;
|
||||
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
|
||||
@@ -604,7 +474,7 @@ std::enable_if_t<std::is_unsigned_v<T>, T> SaturatingAdd(T X, T Y, T Z,
|
||||
/// maximum representable value of T on overflow. ResultOverflowed indicates if
|
||||
/// the result is larger than the maximum representable value of type T.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_unsigned<T>::value, T>
|
||||
std::enable_if_t<std::is_unsigned_v<T>, T>
|
||||
SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
|
||||
bool Dummy;
|
||||
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
|
||||
@@ -650,7 +520,7 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
|
||||
/// overflow. ResultOverflowed indicates if the result is larger than the
|
||||
/// maximum representable value of type T.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_unsigned<T>::value, T>
|
||||
std::enable_if_t<std::is_unsigned_v<T>, T>
|
||||
SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
|
||||
bool Dummy;
|
||||
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
|
||||
@@ -669,7 +539,7 @@ extern const float huge_valf;
|
||||
/// Add two signed integers, computing the two's complement truncated result,
|
||||
/// returning true if overflow occurred.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_signed<T>::value, T> AddOverflow(T X, T Y, T &Result) {
|
||||
std::enable_if_t<std::is_signed_v<T>, T> AddOverflow(T X, T Y, T &Result) {
|
||||
#if __has_builtin(__builtin_add_overflow)
|
||||
return __builtin_add_overflow(X, Y, &Result);
|
||||
#else
|
||||
@@ -695,7 +565,7 @@ std::enable_if_t<std::is_signed<T>::value, T> AddOverflow(T X, T Y, T &Result) {
|
||||
/// Subtract two signed integers, computing the two's complement truncated
|
||||
/// result, returning true if an overflow ocurred.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_signed<T>::value, T> SubOverflow(T X, T Y, T &Result) {
|
||||
std::enable_if_t<std::is_signed_v<T>, T> SubOverflow(T X, T Y, T &Result) {
|
||||
#if __has_builtin(__builtin_sub_overflow)
|
||||
return __builtin_sub_overflow(X, Y, &Result);
|
||||
#else
|
||||
@@ -721,7 +591,7 @@ std::enable_if_t<std::is_signed<T>::value, T> SubOverflow(T X, T Y, T &Result) {
|
||||
/// Multiply two signed integers, computing the two's complement truncated
|
||||
/// result, returning true if an overflow ocurred.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_signed<T>::value, T> MulOverflow(T X, T Y, T &Result) {
|
||||
std::enable_if_t<std::is_signed_v<T>, T> MulOverflow(T X, T Y, T &Result) {
|
||||
// Perform the unsigned multiplication on absolute values.
|
||||
using U = std::make_unsigned_t<T>;
|
||||
const U UX = X < 0 ? (0 - static_cast<U>(X)) : static_cast<U>(X);
|
||||
|
||||
@@ -19,10 +19,44 @@
|
||||
#include "wpi/type_traits.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
namespace detail {
|
||||
template <typename Ptr> struct PunnedPointer {
|
||||
static_assert(sizeof(Ptr) == sizeof(intptr_t), "");
|
||||
|
||||
// Asserts that allow us to let the compiler implement the destructor and
|
||||
// copy/move constructors
|
||||
static_assert(std::is_trivially_destructible<Ptr>::value, "");
|
||||
static_assert(std::is_trivially_copy_constructible<Ptr>::value, "");
|
||||
static_assert(std::is_trivially_move_constructible<Ptr>::value, "");
|
||||
|
||||
explicit constexpr PunnedPointer(intptr_t i = 0) { *this = i; }
|
||||
|
||||
constexpr intptr_t asInt() const {
|
||||
intptr_t R = 0;
|
||||
std::memcpy(&R, Data, sizeof(R));
|
||||
return R;
|
||||
}
|
||||
|
||||
constexpr operator intptr_t() const { return asInt(); }
|
||||
|
||||
constexpr PunnedPointer &operator=(intptr_t V) {
|
||||
std::memcpy(Data, &V, sizeof(Data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ptr *getPointerAddress() { return reinterpret_cast<Ptr *>(Data); }
|
||||
const Ptr *getPointerAddress() const { return reinterpret_cast<Ptr *>(Data); }
|
||||
|
||||
private:
|
||||
alignas(Ptr) unsigned char Data[sizeof(Ptr)];
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename Enable> struct DenseMapInfo;
|
||||
template <typename PointerT, unsigned IntBits, typename PtrTraits>
|
||||
struct PointerIntPairInfo;
|
||||
@@ -46,7 +80,7 @@ template <typename PointerTy, unsigned IntBits, typename IntType = unsigned,
|
||||
class PointerIntPair {
|
||||
// Used by MSVC visualizer and generally helpful for debugging/visualizing.
|
||||
using InfoTy = Info;
|
||||
intptr_t Value = 0;
|
||||
detail::PunnedPointer<PointerTy> Value;
|
||||
|
||||
public:
|
||||
constexpr PointerIntPair() = default;
|
||||
@@ -86,10 +120,12 @@ public:
|
||||
assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
|
||||
"Can only return the address if IntBits is cleared and "
|
||||
"PtrTraits doesn't change the pointer");
|
||||
return reinterpret_cast<PointerTy *>(&Value);
|
||||
return Value.getPointerAddress();
|
||||
}
|
||||
|
||||
void *getOpaqueValue() const { return reinterpret_cast<void *>(Value); }
|
||||
void *getOpaqueValue() const {
|
||||
return reinterpret_cast<void *>(Value.asInt());
|
||||
}
|
||||
|
||||
void setFromOpaqueValue(void *Val) & {
|
||||
Value = reinterpret_cast<intptr_t>(Val);
|
||||
|
||||
@@ -217,9 +217,9 @@ public:
|
||||
/// If the union is set to the first pointer type get an address pointing to
|
||||
/// it.
|
||||
First *getAddrOfPtr1() {
|
||||
assert(is<First>() && "Val is not the first pointer");
|
||||
assert(isa<First>(*this) && "Val is not the first pointer");
|
||||
assert(
|
||||
PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) ==
|
||||
PointerLikeTypeTraits<First>::getAsVoidPointer(cast<First>(*this)) ==
|
||||
this->Val.getPointer() &&
|
||||
"Can't get the address because PointerLikeTypeTraits changes the ptr");
|
||||
return const_cast<First *>(
|
||||
@@ -276,7 +276,7 @@ template <typename... PTs> struct CastInfoPointerUnionImpl {
|
||||
}
|
||||
|
||||
template <typename To> static To doCast(From &F) {
|
||||
assert(isPossible<To>(F) && "cast to an incompatible type !");
|
||||
assert(isPossible<To>(F) && "cast to an incompatible type!");
|
||||
return PointerLikeTypeTraits<To>::getFromVoidPointer(F.Val.getPointer());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,5 +14,5 @@ bool shouldReverseIterate() {
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace wpi
|
||||
#endif
|
||||
|
||||
@@ -264,8 +264,9 @@ protected:
|
||||
|
||||
/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
|
||||
template <typename PtrTy>
|
||||
class SmallPtrSetIterator : public SmallPtrSetIteratorImpl,
|
||||
DebugEpochBase::HandleBase {
|
||||
class LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE SmallPtrSetIterator
|
||||
: public SmallPtrSetIteratorImpl,
|
||||
DebugEpochBase::HandleBase {
|
||||
using PtrTraits = PointerLikeTypeTraits<PtrTy>;
|
||||
|
||||
public:
|
||||
|
||||
@@ -149,7 +149,9 @@ class SmallSet {
|
||||
static_assert(N <= 32, "N should be small");
|
||||
|
||||
public:
|
||||
using key_type = T;
|
||||
using size_type = size_t;
|
||||
using value_type = T;
|
||||
using const_iterator = SmallSetIterator<T, N, C>;
|
||||
|
||||
SmallSet() = default;
|
||||
|
||||
@@ -328,8 +328,8 @@ public:
|
||||
/// copy these types with memcpy, there is no way for the type to observe this.
|
||||
/// This catches the important case of std::pair<POD, POD>, which is not
|
||||
/// trivially assignable.
|
||||
template <typename T, bool = (is_trivially_copy_constructible<T>::value) &&
|
||||
(is_trivially_move_constructible<T>::value) &&
|
||||
template <typename T, bool = (std::is_trivially_copy_constructible<T>::value) &&
|
||||
(std::is_trivially_move_constructible<T>::value) &&
|
||||
std::is_trivially_destructible<T>::value>
|
||||
class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
|
||||
friend class SmallVectorTemplateCommon<T>;
|
||||
@@ -1208,7 +1208,12 @@ public:
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
}
|
||||
|
||||
explicit SmallVector(size_t Size, const T &Value = T())
|
||||
explicit SmallVector(size_t Size)
|
||||
: SmallVectorImpl<T>(N) {
|
||||
this->resize(Size);
|
||||
}
|
||||
|
||||
SmallVector(size_t Size, const T &Value)
|
||||
: SmallVectorImpl<T>(N) {
|
||||
this->assign(Size, Value);
|
||||
}
|
||||
|
||||
@@ -111,8 +111,9 @@ public:
|
||||
/// funky memory allocation and hashing things to make it extremely efficient,
|
||||
/// storing the string data *after* the value in the map.
|
||||
template <typename ValueTy, typename AllocatorTy = MallocAllocator>
|
||||
class StringMap : public StringMapImpl,
|
||||
private detail::AllocatorHolder<AllocatorTy> {
|
||||
class LLVM_ALLOCATORHOLDER_EMPTYBASE StringMap
|
||||
: public StringMapImpl,
|
||||
private detail::AllocatorHolder<AllocatorTy> {
|
||||
using AllocTy = detail::AllocatorHolder<AllocatorTy>;
|
||||
|
||||
public:
|
||||
@@ -235,18 +236,29 @@ public:
|
||||
/// lookup - Return the entry for the specified key, or a default
|
||||
/// constructed value if no such entry exists.
|
||||
ValueTy lookup(std::string_view Key) const {
|
||||
const_iterator it = find(Key);
|
||||
if (it != end())
|
||||
return it->second;
|
||||
const_iterator Iter = find(Key);
|
||||
if (Iter != end())
|
||||
return Iter->second;
|
||||
return ValueTy();
|
||||
}
|
||||
|
||||
/// at - Return the entry for the specified key, or abort if no such
|
||||
/// entry exists.
|
||||
const ValueTy &at(std::string_view Val) const {
|
||||
auto Iter = this->find(std::move(Val));
|
||||
assert(Iter != this->end() && "StringMap::at failed due to a missing key");
|
||||
return Iter->second;
|
||||
}
|
||||
|
||||
/// Lookup the ValueTy for the \p Key, or create a default constructed value
|
||||
/// if the key is not in the map.
|
||||
ValueTy &operator[](std::string_view Key) { return try_emplace(Key).first->second; }
|
||||
|
||||
/// contains - Return true if the element is in the map, false otherwise.
|
||||
bool contains(std::string_view Key) const { return find(Key) != end(); }
|
||||
|
||||
/// count - Return 1 if the element is in the map, 0 otherwise.
|
||||
size_type count(std::string_view Key) const { return find(Key) == end() ? 0 : 1; }
|
||||
size_type count(std::string_view Key) const { return contains(Key) ? 1 : 0; }
|
||||
|
||||
template <typename InputTy>
|
||||
size_type count(const StringMapEntry<InputTy> &MapEntry) const {
|
||||
|
||||
@@ -46,16 +46,6 @@
|
||||
|
||||
namespace wpi {
|
||||
|
||||
/// ByteSwap_16 - This function returns a byte-swapped representation of
|
||||
/// the 16-bit argument.
|
||||
inline uint16_t ByteSwap_16(uint16_t value) { return wpi::byteswap(value); }
|
||||
|
||||
/// This function returns a byte-swapped representation of the 32-bit argument.
|
||||
inline uint32_t ByteSwap_32(uint32_t value) { return wpi::byteswap(value); }
|
||||
|
||||
/// This function returns a byte-swapped representation of the 64-bit argument.
|
||||
inline uint64_t ByteSwap_64(uint64_t value) { return wpi::byteswap(value); }
|
||||
|
||||
namespace sys {
|
||||
|
||||
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
|
||||
@@ -103,7 +93,7 @@ inline double getSwappedBytes(double C) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::enable_if_t<std::is_enum<T>::value, T> getSwappedBytes(T C) {
|
||||
inline std::enable_if_t<std::is_enum_v<T>, T> getSwappedBytes(T C) {
|
||||
return static_cast<T>(
|
||||
wpi::byteswap(static_cast<std::underlying_type_t<T>>(C)));
|
||||
}
|
||||
|
||||
@@ -18,10 +18,22 @@
|
||||
#ifndef WPIUTIL_WPI_ITERATOR_RANGE_H
|
||||
#define WPIUTIL_WPI_ITERATOR_RANGE_H
|
||||
|
||||
#include "wpi/ADL.h"
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
template <typename From, typename To, typename = void>
|
||||
struct explicitly_convertible : std::false_type {};
|
||||
|
||||
template <typename From, typename To>
|
||||
struct explicitly_convertible<
|
||||
From, To,
|
||||
std::void_t<decltype(static_cast<To>(
|
||||
std::declval<std::add_rvalue_reference_t<From>>()))>> : std::true_type {
|
||||
};
|
||||
|
||||
/// A range adaptor for a pair of iterators.
|
||||
///
|
||||
/// This just wraps two iterators into a range-compatible interface. Nothing
|
||||
@@ -31,12 +43,19 @@ class iterator_range {
|
||||
IteratorT begin_iterator, end_iterator;
|
||||
|
||||
public:
|
||||
//TODO: Add SFINAE to test that the Container's iterators match the range's
|
||||
// iterators.
|
||||
#if __GNUC__ == 7
|
||||
// Be careful no to break gcc-7 on the mlir target.
|
||||
// See https://github.com/llvm/llvm-project/issues/63843
|
||||
template <typename Container>
|
||||
#else
|
||||
template <typename Container,
|
||||
std::enable_if_t<explicitly_convertible<
|
||||
detail::IterOfRange<Container>, IteratorT>::value> * = nullptr>
|
||||
#endif
|
||||
iterator_range(Container &&c)
|
||||
//TODO: Consider ADL/non-member begin/end calls.
|
||||
: begin_iterator(c.begin()), end_iterator(c.end()) {}
|
||||
: begin_iterator(adl_begin(std::forward<Container>(c))),
|
||||
end_iterator(adl_end(std::forward<Container>(c))) {
|
||||
}
|
||||
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
|
||||
: begin_iterator(std::move(begin_iterator)),
|
||||
end_iterator(std::move(end_iterator)) {}
|
||||
@@ -46,6 +65,9 @@ public:
|
||||
bool empty() const { return begin_iterator == end_iterator; }
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
iterator_range(Container &&) -> iterator_range<detail::IterOfRange<Container>>;
|
||||
|
||||
/// Convenience function for iterating over sub-ranges.
|
||||
///
|
||||
/// This provides a bit of syntactic sugar to make using sub-ranges
|
||||
|
||||
@@ -387,8 +387,8 @@ private:
|
||||
/// Call the appropriate insertion operator, given an rvalue reference to a
|
||||
/// raw_ostream object and return a stream of the same type as the argument.
|
||||
template <typename OStream, typename T>
|
||||
std::enable_if_t<!std::is_reference<OStream>::value &&
|
||||
std::is_base_of<raw_ostream, OStream>::value,
|
||||
std::enable_if_t<!std::is_reference_v<OStream> &&
|
||||
std::is_base_of_v<raw_ostream, OStream>,
|
||||
OStream &&>
|
||||
operator<<(OStream &&OS, const T &Value) {
|
||||
OS << Value;
|
||||
|
||||
@@ -32,11 +32,11 @@ template <typename T> class is_integral_or_enum {
|
||||
|
||||
public:
|
||||
static const bool value =
|
||||
!std::is_class<UnderlyingT>::value && // Filter conversion operators.
|
||||
!std::is_pointer<UnderlyingT>::value &&
|
||||
!std::is_floating_point<UnderlyingT>::value &&
|
||||
(std::is_enum<UnderlyingT>::value ||
|
||||
std::is_convertible<UnderlyingT, unsigned long long>::value);
|
||||
!std::is_class_v<UnderlyingT> && // Filter conversion operators.
|
||||
!std::is_pointer_v<UnderlyingT> &&
|
||||
!std::is_floating_point_v<UnderlyingT> &&
|
||||
(std::is_enum_v<UnderlyingT> ||
|
||||
std::is_convertible_v<UnderlyingT, unsigned long long>);
|
||||
};
|
||||
|
||||
/// If T is a pointer, just return it. If it is not, return T&.
|
||||
@@ -45,7 +45,7 @@ struct add_lvalue_reference_if_not_pointer { using type = T &; };
|
||||
|
||||
template <typename T>
|
||||
struct add_lvalue_reference_if_not_pointer<
|
||||
T, std::enable_if_t<std::is_pointer<T>::value>> {
|
||||
T, std::enable_if_t<std::is_pointer_v<T>>> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
@@ -55,7 +55,7 @@ template<typename T, typename Enable = void>
|
||||
struct add_const_past_pointer { using type = const T; };
|
||||
|
||||
template <typename T>
|
||||
struct add_const_past_pointer<T, std::enable_if_t<std::is_pointer<T>::value>> {
|
||||
struct add_const_past_pointer<T, std::enable_if_t<std::is_pointer_v<T>>> {
|
||||
using type = const std::remove_pointer_t<T> *;
|
||||
};
|
||||
|
||||
@@ -64,27 +64,11 @@ struct const_pointer_or_const_ref {
|
||||
using type = const T &;
|
||||
};
|
||||
template <typename T>
|
||||
struct const_pointer_or_const_ref<T,
|
||||
std::enable_if_t<std::is_pointer<T>::value>> {
|
||||
struct const_pointer_or_const_ref<T, std::enable_if_t<std::is_pointer_v<T>>> {
|
||||
using type = typename add_const_past_pointer<T>::type;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
/// Internal utility to detect trivial copy construction.
|
||||
template<typename T> union copy_construction_triviality_helper {
|
||||
T t;
|
||||
copy_construction_triviality_helper() = default;
|
||||
copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default;
|
||||
~copy_construction_triviality_helper() = default;
|
||||
};
|
||||
/// Internal utility to detect trivial move construction.
|
||||
template<typename T> union move_construction_triviality_helper {
|
||||
T t;
|
||||
move_construction_triviality_helper() = default;
|
||||
move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
|
||||
~move_construction_triviality_helper() = default;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
union trivial_helper {
|
||||
T t;
|
||||
@@ -92,12 +76,6 @@ union trivial_helper {
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
template <typename T>
|
||||
using is_trivially_move_constructible = std::is_trivially_move_constructible<T>;
|
||||
|
||||
template <typename T>
|
||||
using is_trivially_copy_constructible = std::is_trivially_copy_constructible<T>;
|
||||
|
||||
} // end namespace wpi
|
||||
|
||||
#endif // WPIUTIL_WPI_TYPE_TRAITS_H
|
||||
|
||||
56
wpiutil/src/main/native/thirdparty/llvm/include/wpi/xxhash.h
vendored
Normal file
56
wpiutil/src/main/native/thirdparty/llvm/include/wpi/xxhash.h
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
xxHash - Extremely Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
/* based on revision d2df04efcbef7d7f6886d345861e5dfda4edacc1 Removed
|
||||
* everything but a simple interface for computing XXh64. */
|
||||
|
||||
#ifndef WPIUTIL_WPI_XXHASH_H
|
||||
#define WPIUTIL_WPI_XXHASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
|
||||
namespace wpi {
|
||||
uint64_t xxHash64(std::string_view Data);
|
||||
uint64_t xxHash64(std::span<const uint8_t> Data);
|
||||
|
||||
uint64_t xxh3_64bits(std::span<const uint8_t> data);
|
||||
inline uint64_t xxh3_64bits(std::string_view data) {
|
||||
return xxh3_64bits(std::span(reinterpret_cast<const uint8_t*>(data.data()), data.size()));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user