1+ // ===------ AutoLoadDylibUtils.h - Auto-Loading Dynamic Library -------*- C++
2+ // -*-===//
3+ //
4+ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+ // See https://llvm.org/LICENSE.txt for license information.
6+ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+ //
8+ // ===----------------------------------------------------------------------===//
9+
10+ #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_AUTOLOADDYLIBUTILS_H
11+ #define LLVM_EXECUTIONENGINE_ORC_SHARED_AUTOLOADDYLIBUTILS_H
12+
13+ #include " llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
14+ #include " llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
15+
16+ #include < math.h>
17+ #include < type_traits>
18+ #include < vector>
19+
20+ namespace llvm {
21+ namespace orc {
22+
23+ namespace shared {
24+ using SPSBloomFilter =
25+ SPSTuple<bool , uint32_t , uint32_t , uint32_t , SPSSequence<uint64_t >>;
26+ }
27+
28+ constexpr uint32_t log2u (std::uint32_t n) {
29+ return (n > 1 ) ? 1 + log2u (n >> 1 ) : 0 ;
30+ }
31+
32+ class BloomFilter {
33+ private:
34+ static constexpr int Bits = 8 * sizeof (uint64_t );
35+ static constexpr float P = 0 .02f ;
36+
37+ bool Initialized = false ;
38+ uint32_t SymbolsCount = 0 ;
39+ uint32_t BloomSize = 0 ;
40+ uint32_t BloomShift = 0 ;
41+ std::vector<uint64_t > BloomTable;
42+
43+ // This is a GNU implementation of hash used in bloom filter!
44+ static uint32_t GNUHash (StringRef S) {
45+ uint32_t H = 5381 ;
46+ for (uint8_t C : S)
47+ H = (H << 5 ) + H + C;
48+ return H;
49+ }
50+ // Helper method for hash testing
51+ bool TestHash (uint32_t hash) const {
52+ assert (IsInitialized && " Bloom filter is not initialized!" );
53+ uint32_t hash2 = hash >> BloomShift;
54+ uint32_t n = (hash >> log2u (Bits)) % BloomSize;
55+ uint64_t mask = ((1ULL << (hash % Bits)) | (1ULL << (hash2 % Bits)));
56+ return (mask & BloomTable[n]) == mask;
57+ }
58+
59+ // Helper method to add a hash
60+ void AddHash (uint32_t hash) {
61+ assert (IsInitialized && " Bloom filter is not initialized!" );
62+ uint32_t hash2 = hash >> BloomShift;
63+ uint32_t n = (hash >> log2u (Bits)) % BloomSize;
64+ uint64_t mask = ((1ULL << (hash % Bits)) | (1ULL << (hash2 % Bits)));
65+ BloomTable[n] |= mask;
66+ }
67+
68+ // Resizes the Bloom filter table based on symbol count
69+ void ResizeTable (uint32_t newSymbolsCount) {
70+ assert (SymbolsCount == 0 && " Resize not supported after initialization!" );
71+ SymbolsCount = newSymbolsCount;
72+ BloomSize =
73+ static_cast <uint32_t >(ceil ((-1 .44f * SymbolsCount * log2f (P)) / Bits));
74+ BloomShift = std::min (6u , log2u (SymbolsCount));
75+ BloomTable.resize (BloomSize, 0 );
76+ }
77+
78+ friend class shared ::SPSSerializationTraits<shared::SPSBloomFilter,
79+ BloomFilter>;
80+
81+ public:
82+ BloomFilter () = default ;
83+ BloomFilter (const BloomFilter &other) noexcept
84+ : Initialized(other.Initialized), SymbolsCount(other.SymbolsCount),
85+ BloomSize (other.BloomSize), BloomShift(other.BloomShift),
86+ BloomTable(other.BloomTable) {
87+ }
88+ BloomFilter &operator =(const BloomFilter &other) = delete ;
89+
90+ BloomFilter (BloomFilter &&other) noexcept
91+ : Initialized(other.Initialized), SymbolsCount(other.SymbolsCount),
92+ BloomSize(other.BloomSize), BloomShift(other.BloomShift),
93+ BloomTable(std::move(other.BloomTable)) {
94+ other.Initialized = false ;
95+ other.SymbolsCount = 0 ;
96+ other.BloomSize = 0 ;
97+ other.BloomShift = 0 ;
98+ }
99+
100+ BloomFilter &operator =(BloomFilter &&other) noexcept {
101+ if (this != &other) {
102+ Initialized = other.Initialized ;
103+ SymbolsCount = other.SymbolsCount ;
104+ BloomSize = other.BloomSize ;
105+ BloomShift = other.BloomShift ;
106+ BloomTable = std::move (other.BloomTable );
107+
108+ other.Initialized = false ;
109+ other.SymbolsCount = 0 ;
110+ other.BloomSize = 0 ;
111+ other.BloomShift = 0 ;
112+ }
113+ return *this ;
114+ }
115+
116+ void swap (BloomFilter &other) noexcept {
117+ std::swap (Initialized, other.Initialized );
118+ std::swap (SymbolsCount, other.SymbolsCount );
119+ std::swap (BloomSize, other.BloomSize );
120+ std::swap (BloomShift, other.BloomShift );
121+ std::swap (BloomTable, other.BloomTable );
122+ }
123+
124+ void Initialize (uint32_t newSymbolsCount) {
125+ assert (!Initialized && " Cannot reinitialize the Bloom filter!" );
126+ Initialized = true ;
127+ ResizeTable (newSymbolsCount);
128+ }
129+
130+ bool IsEmpty () const { return SymbolsCount == 0 ; }
131+
132+ uint32_t getSymCount () const { return SymbolsCount; }
133+
134+ bool IsInitialized () const { return Initialized; }
135+
136+ bool MayContain (uint32_t hash) const {
137+ if (IsEmpty ())
138+ return false ;
139+ return TestHash (hash);
140+ }
141+
142+ bool MayContain (StringRef symbol) const {
143+ return MayContain (GNUHash (symbol));
144+ }
145+
146+ void AddSymbol (StringRef symbol) { AddHash (GNUHash (symbol)); }
147+ };
148+
149+ struct ResolveResult {
150+ std::optional<BloomFilter> Filter;
151+ std::vector<ExecutorSymbolDef> SymbolDef;
152+ };
153+
154+ namespace shared {
155+
156+ template <> class SPSSerializationTraits <SPSBloomFilter, BloomFilter> {
157+ public:
158+ static size_t size (const BloomFilter &Filter) {
159+ return SPSBloomFilter::AsArgList::size (
160+ Filter.Initialized , Filter.SymbolsCount , Filter.BloomSize ,
161+ Filter.BloomShift , Filter.BloomTable );
162+ }
163+
164+ static bool serialize (SPSOutputBuffer &OB, const BloomFilter &Filter) {
165+ return SPSBloomFilter::AsArgList::serialize (
166+ OB, Filter.Initialized , Filter.SymbolsCount , Filter.BloomSize ,
167+ Filter.BloomShift , Filter.BloomTable );
168+ }
169+
170+ static bool deserialize (SPSInputBuffer &IB, BloomFilter &Filter) {
171+ bool IsInitialized;
172+ uint32_t SymbolsCount = 0 , BloomSize = 0 , BloomShift = 0 ;
173+ std::vector<uint64_t > BloomTable;
174+
175+ if (!SPSBloomFilter::AsArgList::deserialize (
176+ IB, IsInitialized, SymbolsCount, BloomSize, BloomShift, BloomTable))
177+ return false ;
178+
179+ Filter.Initialized = IsInitialized;
180+ Filter.SymbolsCount = SymbolsCount;
181+ Filter.BloomSize = BloomSize;
182+ Filter.BloomShift = BloomShift;
183+ Filter.BloomTable = std::move (BloomTable);
184+
185+ return true ;
186+ }
187+ };
188+
189+ using SPSResolveResult =
190+ SPSTuple<SPSOptional<SPSBloomFilter>, SPSSequence<SPSExecutorSymbolDef>>;
191+ template <> class SPSSerializationTraits <SPSResolveResult, ResolveResult> {
192+ public:
193+ static size_t size (const ResolveResult &Result) {
194+ return SPSResolveResult::AsArgList::size (Result.Filter , Result.SymbolDef );
195+ }
196+
197+ static bool serialize (SPSOutputBuffer &OB, const ResolveResult &Result) {
198+ return SPSResolveResult::AsArgList::serialize (OB, Result.Filter ,
199+ Result.SymbolDef );
200+ }
201+
202+ static bool deserialize (SPSInputBuffer &IB, ResolveResult &Result) {
203+ return SPSResolveResult::AsArgList::deserialize (IB, Result.Filter ,
204+ Result.SymbolDef );
205+ }
206+ };
207+
208+ } // end namespace shared
209+ } // end namespace orc
210+ } // end namespace llvm
211+
212+ #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_AUTOLOADDYLIBUTILS_H
0 commit comments