13#ifndef LLVM_SUPPORT_ONDISKHASHTABLE_H
14#define LLVM_SUPPORT_ONDISKHASHTABLE_H
62 typename Info::key_type Key;
63 typename Info::data_type Data;
65 const typename Info::hash_value_type Hash;
67 Item(
typename Info::key_type_ref Key,
typename Info::data_type_ref Data,
69 : Key(Key), Data(Data), Next(
nullptr), Hash(InfoObj.ComputeHash(Key)) {}
72 typedef typename Info::offset_type offset_type;
73 offset_type NumBuckets;
74 offset_type NumEntries;
88 void insert(Bucket *Buckets,
size_t Size, Item *
E) {
89 Bucket &
B = Buckets[
E->Hash & (
Size - 1)];
96 void resize(
size_t NewSize) {
97 Bucket *NewBuckets =
static_cast<Bucket *
>(
100 for (
size_t I = 0;
I < NumBuckets; ++
I)
101 for (Item *
E = Buckets[
I].Head;
E;) {
104 insert(NewBuckets, NewSize,
E);
109 NumBuckets = NewSize;
110 Buckets = NewBuckets;
115 void insert(
typename Info::key_type_ref Key,
116 typename Info::data_type_ref
Data) {
118 insert(Key,
Data, InfoObj);
124 void insert(
typename Info::key_type_ref Key,
125 typename Info::data_type_ref
Data,
Info &InfoObj) {
127 if (4 * NumEntries >= 3 * NumBuckets)
128 resize(NumBuckets * 2);
129 insert(Buckets, NumBuckets,
new (BA.
Allocate()) Item(Key,
Data, InfoObj));
134 unsigned Hash = InfoObj.ComputeHash(Key);
135 for (Item *
I = Buckets[Hash & (NumBuckets - 1)].Head;
I;
I =
I->Next)
136 if (
I->Hash == Hash && InfoObj.EqualKey(
I->Key, Key))
144 return Emit(Out, InfoObj);
165 unsigned TargetNumBuckets =
167 if (TargetNumBuckets != NumBuckets)
168 resize(TargetNumBuckets);
171 for (offset_type
I = 0;
I < NumBuckets; ++
I) {
172 Bucket &
B = Buckets[
I];
178 assert(
B.Off &&
"Cannot write a bucket at offset 0. Please add padding.");
182 assert(
B.Length != 0 &&
"Bucket has a head but zero length?");
185 for (Item *
I =
B.Head;
I;
I =
I->Next) {
186 LE.write<
typename Info::hash_value_type>(
I->Hash);
187 const std::pair<offset_type, offset_type> &Len =
188 InfoObj.EmitKeyDataLength(Out,
I->Key,
I->Data);
190 InfoObj.EmitKey(Out,
I->Key, Len.first);
191 InfoObj.EmitData(Out,
I->Key,
I->Data, Len.second);
196 InfoObj.EmitKey(Out,
I->Key, Len.first);
198 InfoObj.EmitData(Out,
I->Key,
I->Data, Len.second);
200 assert(offset_type(DataStart - KeyStart) == Len.first &&
201 "key length does not match bytes written");
202 assert(offset_type(
End - DataStart) == Len.second &&
203 "data length does not match bytes written");
209 offset_type TableOff = Out.
tell();
213 LE.write<uint8_t>(0);
216 LE.write<offset_type>(NumBuckets);
217 LE.write<offset_type>(NumEntries);
218 for (offset_type
I = 0;
I < NumBuckets; ++
I)
219 LE.write<offset_type>(Buckets[
I].Off);
229 Buckets =
static_cast<Bucket *
>(
safe_calloc(NumBuckets,
sizeof(Bucket)));
274 const typename Info::offset_type NumBuckets;
275 const typename Info::offset_type NumEntries;
276 const unsigned char *
const Buckets;
277 const unsigned char *
const Base;
289 const unsigned char *Buckets,
290 const unsigned char *Base,
292 : NumBuckets(NumBuckets), NumEntries(NumEntries), Buckets(Buckets),
294 assert((
reinterpret_cast<uintptr_t
>(Buckets) & 0x3) == 0 &&
295 "'buckets' must have a 4-byte alignment");
301 static std::pair<offset_type, offset_type>
303 assert((
reinterpret_cast<uintptr_t
>(Buckets) & 0x3) == 0 &&
304 "buckets should be 4-byte aligned.");
307 endian::readNext<offset_type, llvm::endianness::little, aligned>(
310 endian::readNext<offset_type, llvm::endianness::little, aligned>(
312 return std::make_pair(NumBuckets, NumEntries);
320 bool isEmpty()
const {
return NumEntries == 0; }
324 const unsigned char *
const Data;
329 iterator() : Key(), Data(nullptr), Len(0), InfoObj(nullptr) {}
332 : Key(K), Data(
D), Len(L), InfoObj(InfoObj) {}
352 Info *InfoPtr =
nullptr) {
360 const unsigned char *Bucket = Buckets +
sizeof(
offset_type) *
Idx;
363 endian::readNext<offset_type, llvm::endianness::little, aligned>(
371 unsigned Len = endian::readNext<uint16_t, llvm::endianness::little>(Items);
373 for (
unsigned i = 0; i < Len; ++i) {
376 endian::readNext<hash_value_type, llvm::endianness::little>(Items);
379 const std::pair<offset_type, offset_type> &L =
380 Info::ReadKeyDataLength(Items);
384 if (ItemHash != KeyHash) {
391 InfoPtr->ReadKey((
const unsigned char *
const)Items, L.first);
394 if (!InfoPtr->EqualKey(
X, IKey)) {
400 return iterator(
X, Items + L.first, L.second, InfoPtr);
420 const unsigned char *
const Base,
425 NumBucketsAndEntries.second,
426 Buckets,
Base, InfoObj);
433template <
typename Info>
435 const unsigned char *Payload;
447 class iterator_base {
448 const unsigned char *
Ptr;
455 iterator_base(
const unsigned char *
const Ptr,
offset_type NumEntries)
456 :
Ptr(
Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries) {}
458 :
Ptr(
nullptr), NumItemsInBucketLeft(0), NumEntriesLeft(0) {}
460 friend bool operator==(
const iterator_base &
X,
const iterator_base &
Y) {
461 return X.NumEntriesLeft ==
Y.NumEntriesLeft;
463 friend bool operator!=(
const iterator_base &
X,
const iterator_base &
Y) {
464 return X.NumEntriesLeft !=
Y.NumEntriesLeft;
470 if (!NumItemsInBucketLeft) {
473 NumItemsInBucketLeft =
474 endian::readNext<uint16_t, llvm::endianness::little>(
Ptr);
478 const std::pair<offset_type, offset_type> &L =
479 Info::ReadKeyDataLength(
Ptr);
480 Ptr += L.first + L.second;
481 assert(NumItemsInBucketLeft);
482 --NumItemsInBucketLeft;
489 const unsigned char *getItem()
const {
496 const unsigned char *Buckets,
497 const unsigned char *Payload,
498 const unsigned char *Base,
512 : iterator_base(
Ptr, NumEntries), InfoObj(InfoObj) {}
526 auto *LocalPtr = this->getItem();
529 auto L = Info::ReadKeyDataLength(LocalPtr);
532 return InfoObj->ReadKey(LocalPtr, L.first);
558 : iterator_base(
Ptr, NumEntries), InfoObj(InfoObj) {}
572 auto *LocalPtr = this->getItem();
575 auto L = Info::ReadKeyDataLength(LocalPtr);
579 return InfoObj->ReadData(Key, LocalPtr + L.first, L.second);
606 Create(
const unsigned char *Buckets,
const unsigned char *
const Payload,
607 const unsigned char *
const Base,
const Info &InfoObj =
Info()) {
609 auto NumBucketsAndEntries =
612 NumBucketsAndEntries.first, NumBucketsAndEntries.second,
613 Buckets, Payload,
Base, InfoObj);
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Generates an on disk hash table.
~OnDiskChainedHashTableGenerator()
offset_type Emit(raw_ostream &Out)
Emit the table to Out, which must not be at offset 0.
void insert(typename Info::key_type_ref Key, typename Info::data_type_ref Data)
Insert an entry into the table.
OnDiskChainedHashTableGenerator()
bool contains(typename Info::key_type_ref Key, Info &InfoObj)
Determine whether an entry has been inserted.
offset_type Emit(raw_ostream &Out, Info &InfoObj)
Emit the table to Out, which must not be at offset 0.
void insert(typename Info::key_type_ref Key, typename Info::data_type_ref Data, Info &InfoObj)
Insert an entry into the table.
const unsigned char * getDataPtr() const
offset_type getDataLen() const
bool operator==(const iterator &X) const
bool operator!=(const iterator &X) const
data_type operator*() const
iterator(const internal_key_type K, const unsigned char *D, offset_type L, Info *InfoObj)
Provides lookup on an on disk hash table.
static std::pair< offset_type, offset_type > readNumBucketsAndEntries(const unsigned char *&Buckets)
Read the number of buckets and the number of entries from a hash table produced by OnDiskHashTableGen...
Info::offset_type offset_type
Info::hash_value_type hash_value_type
static OnDiskChainedHashTable * Create(const unsigned char *Buckets, const unsigned char *const Base, const Info &InfoObj=Info())
Create the hash table.
offset_type getNumEntries() const
iterator find_hashed(const internal_key_type &IKey, hash_value_type KeyHash, Info *InfoPtr=nullptr)
Look up the stored data for a particular key with a known hash.
offset_type getNumBuckets() const
Info::external_key_type external_key_type
Info::data_type data_type
Info::internal_key_type internal_key_type
const unsigned char * getBase() const
const unsigned char * getBuckets() const
iterator find(const external_key_type &EKey, Info *InfoPtr=nullptr)
Look up the stored data for a particular key.
OnDiskChainedHashTable(offset_type NumBuckets, offset_type NumEntries, const unsigned char *Buckets, const unsigned char *Base, const Info &InfoObj=Info())
Iterates over all the entries in the table, returning the data.
data_iterator & operator++()
value_type operator*() const
data_iterator(const unsigned char *const Ptr, offset_type NumEntries, Info *InfoObj)
data_iterator operator++(int)
Iterates over all of the keys in the table.
internal_key_type getInternalKey() const
external_key_type value_type
key_iterator operator++(int)
value_type operator*() const
key_iterator(const unsigned char *const Ptr, offset_type NumEntries, Info *InfoObj)
key_iterator & operator++()
Provides lookup and iteration over an on disk hash table.
iterator_range< key_iterator > keys()
static OnDiskIterableChainedHashTable * Create(const unsigned char *Buckets, const unsigned char *const Payload, const unsigned char *const Base, const Info &InfoObj=Info())
Create the hash table.
base_type::internal_key_type internal_key_type
base_type::data_type data_type
base_type::external_key_type external_key_type
iterator_range< data_iterator > data()
base_type::hash_value_type hash_value_type
data_iterator data_begin()
OnDiskIterableChainedHashTable(offset_type NumBuckets, offset_type NumEntries, const unsigned char *Buckets, const unsigned char *Payload, const unsigned char *Base, const Info &InfoObj=Info())
base_type::offset_type offset_type
OnDiskChainedHashTable< Info > base_type
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
T * Allocate(size_t num=1)
Allocate space for an array of objects without constructing them.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
uint64_t tell() const
tell - Return the current offset with the file.
This is an optimization pass for GlobalISel generic memory operations.
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ATTRIBUTE_RETURNS_NONNULL void * safe_calloc(size_t Count, size_t Sz)
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
This struct is a compact representation of a valid (non-zero power of two) alignment.
Adapter to write values to a stream in a particular byte order.