LLVM 19.0.0git
Public Types | Public Member Functions | List of all members
llvm::HashBuilder< HasherT, Endianness > Class Template Reference

Interface to help hash various types through a hasher type. More...

#include "llvm/Support/HashBuilder.h"

Inheritance diagram for llvm::HashBuilder< HasherT, Endianness >:
Inheritance graph
[legend]

Public Types

template<typename T >
using HasAddHashT = decltype(addHash(std::declval< HashBuilder & >(), std::declval< T & >()))
 
template<typename T >
using HasByteSwapT = decltype(support::endian::byte_swap(std::declval< T & >(), llvm::endianness::little))
 
- Public Types inherited from llvm::HashBuilderBase< HasherT >
template<typename HasherT_ = HasherT>
using HashResultTy = decltype(std::declval< HasherT_ & >().final())
 

Public Member Functions

 HashBuilder (HasherT &Hasher)
 
template<typename... ArgTypes>
 HashBuilder (ArgTypes &&...Args)
 
template<typename T >
std::enable_if_t< hashbuilder_detail::IsHashableData< T >::value, HashBuilder & > add (T Value)
 Implement hashing for hashable data types, e.g. integral or enum values.
 
template<typename T >
HashBuilderadd (ArrayRef< T > Value)
 Support hashing ArrayRef.
 
HashBuilderadd (StringRef Value)
 Support hashing StringRef.
 
template<typename T >
std::enable_if_t< is_detected< HasAddHashT, T >::value &&!hashbuilder_detail::IsHashableData< T >::value, HashBuilder & > add (const T &Value)
 Implement hashing for user-defined structs.
 
template<typename T1 , typename T2 >
HashBuilderadd (const std::pair< T1, T2 > &Value)
 
template<typename... Ts>
HashBuilderadd (const std::tuple< Ts... > &Arg)
 
template<typename... Ts>
std::enable_if_t<(sizeof...(Ts) > 1), HashBuilder & > add (const Ts &...Args)
 A convenenience variadic helper.
 
template<typename ForwardIteratorT >
HashBuilderaddRange (ForwardIteratorT First, ForwardIteratorT Last)
 
template<typename RangeT >
HashBuilderaddRange (const RangeT &Range)
 
template<typename ForwardIteratorT >
HashBuilderaddRangeElements (ForwardIteratorT First, ForwardIteratorT Last)
 
template<typename RangeT >
HashBuilderaddRangeElements (const RangeT &Range)
 
template<typename T >
std::enable_if_t< is_detected< HasByteSwapT, T >::value, HashBuilder & > adjustForEndiannessAndAdd (const T &Value)
 Adjust Value for the target endianness and add it to the hash.
 
- Public Member Functions inherited from llvm::HashBuilderBase< HasherT >
HasherT & getHasher ()
 
void update (ArrayRef< uint8_t > Data)
 Forward to HasherT::update(ArrayRef<uint8_t>).
 
void update (StringRef Data)
 Forward to HasherT::update(ArrayRef<uint8_t>).
 
template<typename HasherT_ = HasherT>
HashResultTy< HasherT_ > final ()
 Forward to HasherT::final() if available.
 
template<typename HasherT_ = HasherT>
HashResultTy< HasherT_ > result ()
 Forward to HasherT::result() if available.
 

Additional Inherited Members

- Protected Member Functions inherited from llvm::HashBuilderBase< HasherT >
 HashBuilderBase (HasherT &Hasher)
 
template<typename... ArgTypes>
 HashBuilderBase (ArgTypes &&...Args)
 

Detailed Description

template<typename HasherT, llvm::endianness Endianness>
class llvm::HashBuilder< HasherT, Endianness >

Interface to help hash various types through a hasher type.

Via provided specializations of add, addRange, and addRangeElements functions, various types (e.g. ArrayRef, StringRef, etc.) can be hashed without requiring any knowledge of hashed types from the hasher type.

The only method expected from the templated hasher type HasherT is:

Additionally, the following methods will be forwarded to the hasher type:

From a user point of view, the interface provides the following:

User-defined struct types can participate in this interface by providing an addHash templated function. See the associated template specialization for details.

This interface does not impose requirements on the hasher update(ArrayRef<uint8_t> Data) method. We want to avoid collisions for variable-size types; for example for

builder.add({1});
builder.add({2, 3});

and

builder.add({1, 2});
builder.add({3});

. Thus, specializations of add and addHash for variable-size types must not assume that the hasher type considers the size as part of the hash; they must explicitly add the size to the hash. See for example specializations for ArrayRef and StringRef.

Additionally, since types are eventually forwarded to the hasher's void update(ArrayRef<uint8_t>) method, endianness plays a role in the hash computation (for example when computing add((int)123)). Specifiying a non-native Endianness template parameter allows to compute stable hash across platforms with different endianness.

Definition at line 139 of file HashBuilder.h.

Member Typedef Documentation

◆ HasAddHashT

template<typename HasherT , llvm::endianness Endianness>
template<typename T >
using llvm::HashBuilder< HasherT, Endianness >::HasAddHashT = decltype(addHash(std::declval<HashBuilder &>(), std::declval<T &>()))

Definition at line 208 of file HashBuilder.h.

◆ HasByteSwapT

template<typename HasherT , llvm::endianness Endianness>
template<typename T >
using llvm::HashBuilder< HasherT, Endianness >::HasByteSwapT = decltype(support::endian::byte_swap( std::declval<T &>(), llvm::endianness::little))

Definition at line 350 of file HashBuilder.h.

Constructor & Destructor Documentation

◆ HashBuilder() [1/2]

template<typename HasherT , llvm::endianness Endianness>
llvm::HashBuilder< HasherT, Endianness >::HashBuilder ( HasherT &  Hasher)
inlineexplicit

Definition at line 141 of file HashBuilder.h.

◆ HashBuilder() [2/2]

template<typename HasherT , llvm::endianness Endianness>
template<typename... ArgTypes>
llvm::HashBuilder< HasherT, Endianness >::HashBuilder ( ArgTypes &&...  Args)
inlineexplicit

Definition at line 143 of file HashBuilder.h.

Member Function Documentation

◆ add() [1/7]

template<typename HasherT , llvm::endianness Endianness>
template<typename T >
HashBuilder & llvm::HashBuilder< HasherT, Endianness >::add ( ArrayRef< T Value)
inline

Support hashing ArrayRef.

Value.size() is taken into account to ensure cases like

builder.add({1});
builder.add({2, 3});

and

builder.add({1, 2});
builder.add({3});

do not collide.

Definition at line 166 of file HashBuilder.h.

References llvm::HashBuilder< HasherT, Endianness >::add(), llvm::native, and llvm::HashBuilderBase< HasherT >::update().

◆ add() [2/7]

template<typename HasherT , llvm::endianness Endianness>
template<typename T1 , typename T2 >
HashBuilder & llvm::HashBuilder< HasherT, Endianness >::add ( const std::pair< T1, T2 > &  Value)
inline

Definition at line 303 of file HashBuilder.h.

References llvm::HashBuilder< HasherT, Endianness >::add().

◆ add() [3/7]

template<typename HasherT , llvm::endianness Endianness>
template<typename... Ts>
HashBuilder & llvm::HashBuilder< HasherT, Endianness >::add ( const std::tuple< Ts... > &  Arg)
inline

Definition at line 307 of file HashBuilder.h.

References llvm::HashBuilder< HasherT, Endianness >::add().

◆ add() [4/7]

template<typename HasherT , llvm::endianness Endianness>
template<typename T >
std::enable_if_t< is_detected< HasAddHashT, T >::value && !hashbuilder_detail::IsHashableData< T >::value, HashBuilder & > llvm::HashBuilder< HasherT, Endianness >::add ( const T Value)
inline

Implement hashing for user-defined structs.

Any user-define struct can participate in hashing via HashBuilder by providing a addHash templated function.

template <typename HasherT, llvm::endianness Endianness>
void addHash(HashBuilder<HasherT, Endianness> &HBuilder,
const UserDefinedStruct &Value);
Interface to help hash various types through a hasher type.
Definition: HashBuilder.h:139
LLVM Value Representation.
Definition: Value.h:74

For example:

struct SimpleStruct {
char c;
int i;
};
template <typename HasherT, llvm::endianness Endianness>
void addHash(HashBuilder<HasherT, Endianness> &HBuilder,
const SimpleStruct &Value) {
HBuilder.add(Value.c);
HBuilder.add(Value.i);
}
std::enable_if_t< hashbuilder_detail::IsHashableData< T >::value, HashBuilder & > add(T Value)
Implement hashing for hashable data types, e.g. integral or enum values.
Definition: HashBuilder.h:149

To avoid endianness issues, specializations of addHash should generally rely on exising add, addRange, and addRangeElements functions. If directly using update, an implementation must correctly handle endianness.

struct __attribute__ ((packed)) StructWithFastHash {
int I;
char C;
// If possible, we want to hash both `I` and `C` in a single
// `update` call for performance concerns.
template <typename HasherT, llvm::endianness Endianness>
friend void addHash(HashBuilder<HasherT, Endianness> &HBuilder,
const StructWithFastHash &Value) {
if (Endianness == llvm::endianness::native) {
HBuilder.update(ArrayRef(
reinterpret_cast<const uint8_t *>(&Value), sizeof(Value)));
} else {
// Rely on existing `add` methods to handle endianness.
HBuilder.add(Value.I);
HBuilder.add(Value.C);
}
}
};
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define I(x, y, z)
Definition: MD5.cpp:58
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
void update(ArrayRef< uint8_t > Data)
Forward to HasherT::update(ArrayRef<uint8_t>).
Definition: HashBuilder.h:53

To avoid collisions, specialization of addHash for variable-size types must take the size into account.

For example:

struct CustomContainer {
private:
size_t Size;
int Elements[100];
public:
CustomContainer(size_t Size) : Size(Size) {
for (size_t I = 0; I != Size; ++I)
Elements[I] = I;
}
template <typename HasherT, llvm::endianness Endianness>
friend void addHash(HashBuilder<HasherT, Endianness> &HBuilder,
const CustomContainer &Value) {
if (Endianness == llvm::endianness::native) {
HBuilder.update(ArrayRef(
reinterpret_cast<const uint8_t *>(&Value.Size),
sizeof(Value.Size) + Value.Size * sizeof(Value.Elements[0])));
} else {
// `addRange` will take care of encoding the size.
HBuilder.addRange(&Value.Elements[0], &Value.Elements[0] +
Value.Size);
}
}
};
uint64_t Size
HashBuilder & addRange(ForwardIteratorT First, ForwardIteratorT Last)
Definition: HashBuilder.h:328

Definition at line 297 of file HashBuilder.h.

◆ add() [5/7]

template<typename HasherT , llvm::endianness Endianness>
template<typename... Ts>
std::enable_if_t<(sizeof...(Ts) > 1), HashBuilder & > llvm::HashBuilder< HasherT, Endianness >::add ( const Ts &...  Args)
inline

A convenenience variadic helper.

It simply iterates over its arguments, in order.

add(Arg1, Arg2);

is equivalent to

add(Arg1)
add(Arg2)

Definition at line 323 of file HashBuilder.h.

References llvm::HashBuilder< HasherT, Endianness >::add().

◆ add() [6/7]

template<typename HasherT , llvm::endianness Endianness>
HashBuilder & llvm::HashBuilder< HasherT, Endianness >::add ( StringRef  Value)
inline

Support hashing StringRef.

Value.size() is taken into account to ensure cases like

builder.add("a");
builder.add("bc");

and

builder.add("ab");
builder.add("c");

do not collide.

Definition at line 196 of file HashBuilder.h.

References llvm::HashBuilder< HasherT, Endianness >::add(), and llvm::HashBuilderBase< HasherT >::update().

◆ add() [7/7]

template<typename HasherT , llvm::endianness Endianness>
template<typename T >
std::enable_if_t< hashbuilder_detail::IsHashableData< T >::value, HashBuilder & > llvm::HashBuilder< HasherT, Endianness >::add ( T  Value)
inline

◆ addRange() [1/2]

template<typename HasherT , llvm::endianness Endianness>
template<typename RangeT >
HashBuilder & llvm::HashBuilder< HasherT, Endianness >::addRange ( const RangeT &  Range)
inline

◆ addRange() [2/2]

template<typename HasherT , llvm::endianness Endianness>
template<typename ForwardIteratorT >
HashBuilder & llvm::HashBuilder< HasherT, Endianness >::addRange ( ForwardIteratorT  First,
ForwardIteratorT  Last 
)
inline

◆ addRangeElements() [1/2]

template<typename HasherT , llvm::endianness Endianness>
template<typename RangeT >
HashBuilder & llvm::HashBuilder< HasherT, Endianness >::addRangeElements ( const RangeT &  Range)
inline

◆ addRangeElements() [2/2]

template<typename HasherT , llvm::endianness Endianness>
template<typename ForwardIteratorT >
HashBuilder & llvm::HashBuilder< HasherT, Endianness >::addRangeElements ( ForwardIteratorT  First,
ForwardIteratorT  Last 
)
inline

◆ adjustForEndiannessAndAdd()

template<typename HasherT , llvm::endianness Endianness>
template<typename T >
std::enable_if_t< is_detected< HasByteSwapT, T >::value, HashBuilder & > llvm::HashBuilder< HasherT, Endianness >::adjustForEndiannessAndAdd ( const T Value)
inline

Adjust Value for the target endianness and add it to the hash.

Definition at line 355 of file HashBuilder.h.

References llvm::support::endian::byte_swap(), and llvm::HashBuilderBase< HasherT >::update().

Referenced by llvm::HashBuilder< HasherT, Endianness >::add().


The documentation for this class was generated from the following file: