LLVM 22.0.0git
JITSymbol.h
Go to the documentation of this file.
1//===- JITSymbol.h - JIT symbol abstraction ---------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Abstraction for target process addresses.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_JITSYMBOL_H
14#define LLVM_EXECUTIONENGINE_JITSYMBOL_H
15
17#include <algorithm>
18#include <cassert>
19#include <cstddef>
20#include <cstdint>
21#include <functional>
22#include <map>
23#include <set>
24#include <string>
25
28#include "llvm/ADT/StringRef.h"
29#include "llvm/Support/Error.h"
30
31namespace llvm {
32
33class GlobalValue;
34class GlobalValueSummary;
35
36namespace object {
37
38class SymbolRef;
39
40} // end namespace object
41
42/// Represents an address in the target process's address space.
44
45/// Convert a JITTargetAddress to a pointer.
46///
47/// Note: This is a raw cast of the address bit pattern to the given pointer
48/// type. When casting to a function pointer in order to execute JIT'd code
49/// jitTargetAddressToFunction should be preferred, as it will also perform
50/// pointer signing on targets that require it.
52 static_assert(std::is_pointer<T>::value, "T must be a pointer type");
53 uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
54 assert(IntPtr == Addr && "JITTargetAddress value out of range for uintptr_t");
55 return reinterpret_cast<T>(IntPtr);
56}
57
58/// Convert a JITTargetAddress to a callable function pointer.
59///
60/// Casts the given address to a callable function pointer. This operation
61/// will perform pointer signing for platforms that require it (e.g. arm64e).
63 static_assert(std::is_pointer<T>::value &&
64 std::is_function<std::remove_pointer_t<T>>::value,
65 "T must be a function pointer type");
66 return jitTargetAddressToPointer<T>(Addr);
67}
68
69/// Convert a pointer to a JITTargetAddress.
71 return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Ptr));
72}
73
74/// Flags for symbols in the JIT.
76public:
79
81 None = 0,
82 HasError = 1U << 0,
83 Weak = 1U << 1,
84 Common = 1U << 2,
85 Absolute = 1U << 3,
86 Exported = 1U << 4,
87 Callable = 1U << 5,
89 LLVM_MARK_AS_BITMASK_ENUM( // LargestValue =
91 };
92
93 /// Default-construct a JITSymbolFlags instance.
94 JITSymbolFlags() = default;
95
96 /// Construct a JITSymbolFlags instance from the given flags.
97 JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
98
99 /// Construct a JITSymbolFlags instance from the given flags and target
100 /// flags.
102 : TargetFlags(TargetFlags), Flags(Flags) {}
103
104 /// Implicitly convert to bool. Returns true if any flag is set.
105 explicit operator bool() const { return Flags != None || TargetFlags != 0; }
106
107 /// Compare for equality.
108 bool operator==(const JITSymbolFlags &RHS) const {
109 return Flags == RHS.Flags && TargetFlags == RHS.TargetFlags;
110 }
111
112 /// Bitwise AND-assignment for FlagNames.
114 Flags &= RHS;
115 return *this;
116 }
117
118 /// Bitwise OR-assignment for FlagNames.
120 Flags |= RHS;
121 return *this;
122 }
123
124 /// Return true if there was an error retrieving this symbol.
125 bool hasError() const {
126 return (Flags & HasError) == HasError;
127 }
128
129 /// Returns true if the Weak flag is set.
130 bool isWeak() const {
131 return (Flags & Weak) == Weak;
132 }
133
134 /// Returns true if the Common flag is set.
135 bool isCommon() const {
136 return (Flags & Common) == Common;
137 }
138
139 /// Returns true if the symbol isn't weak or common.
140 bool isStrong() const {
141 return !isWeak() && !isCommon();
142 }
143
144 /// Returns true if the Exported flag is set.
145 bool isExported() const {
146 return (Flags & Exported) == Exported;
147 }
148
149 /// Returns true if the given symbol is known to be callable.
150 bool isCallable() const { return (Flags & Callable) == Callable; }
151
152 /// Returns true if this symbol is a materialization-side-effects-only
153 /// symbol. Such symbols do not have a real address. They exist to trigger
154 /// and support synchronization of materialization side effects, e.g. for
155 /// collecting initialization information. These symbols will vanish from
156 /// the symbol table immediately upon reaching the ready state, and will
157 /// appear to queries as if they were never defined (except that query
158 /// callback execution will be delayed until they reach the ready state).
159 /// MaterializationSideEffectOnly symbols should only be queried using the
160 /// SymbolLookupFlags::WeaklyReferencedSymbol flag (see
161 /// llvm/include/llvm/ExecutionEngine/Orc/Core.h).
163 return (Flags & MaterializationSideEffectsOnly) ==
165 }
166
167 /// Get the underlying flags value as an integer.
169 return static_cast<UnderlyingType>(Flags);
170 }
171
172 /// Return a reference to the target-specific flags.
173 TargetFlagsType& getTargetFlags() { return TargetFlags; }
174
175 /// Return a reference to the target-specific flags.
176 const TargetFlagsType& getTargetFlags() const { return TargetFlags; }
177
178 /// Construct a JITSymbolFlags value based on the flags of the given global
179 /// value.
181
182 /// Construct a JITSymbolFlags value based on the flags of the given global
183 /// value summary.
185
186 /// Construct a JITSymbolFlags value based on the flags of the given libobject
187 /// symbol.
189 fromObjectSymbol(const object::SymbolRef &Symbol);
190
191private:
192 TargetFlagsType TargetFlags = 0;
193 FlagNames Flags = None;
194};
195
198 JITSymbolFlags Tmp = LHS;
199 Tmp &= RHS;
200 return Tmp;
201}
202
205 JITSymbolFlags Tmp = LHS;
206 Tmp |= RHS;
207 return Tmp;
208}
209
210/// ARM-specific JIT symbol flags.
211/// FIXME: This should be moved into a target-specific header.
213public:
214 ARMJITSymbolFlags() = default;
215
217 None = 0,
218 Thumb = 1 << 0
219 };
220
221 operator JITSymbolFlags::TargetFlagsType&() { return Flags; }
222
224 fromObjectSymbol(const object::SymbolRef &Symbol);
225
226private:
228};
229
230/// Represents a symbol that has been evaluated to an address already.
232public:
234
235 /// Create a 'null' symbol.
236 JITEvaluatedSymbol(std::nullptr_t) {}
237
238 /// Create a symbol for the given address and flags.
240 : Address(Address), Flags(Flags) {}
241
242 /// Create a symbol from the given pointer with the given flags.
243 template <typename T>
244 static JITEvaluatedSymbol
247 }
248
249 /// An evaluated symbol converts to 'true' if its address is non-zero.
250 explicit operator bool() const { return Address != 0; }
251
252 /// Return the address of this symbol.
253 JITTargetAddress getAddress() const { return Address; }
254
255 /// Return the flags for this symbol.
256 JITSymbolFlags getFlags() const { return Flags; }
257
258 /// Set the flags for this symbol.
259 void setFlags(JITSymbolFlags Flags) { this->Flags = std::move(Flags); }
260
261private:
262 JITTargetAddress Address = 0;
263 JITSymbolFlags Flags;
264};
265
266/// Represents a symbol in the JIT.
268public:
270
271 /// Create a 'null' symbol, used to represent a "symbol not found"
272 /// result from a successful (non-erroneous) lookup.
273 JITSymbol(std::nullptr_t)
274 : CachedAddr(0) {}
275
276 /// Create a JITSymbol representing an error in the symbol lookup
277 /// process (e.g. a network failure during a remote lookup).
279 : Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
280
281 /// Create a symbol for a definition with a known address.
283 : CachedAddr(Addr), Flags(Flags) {}
284
285 /// Construct a JITSymbol from a JITEvaluatedSymbol.
287 : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
288
289 /// Create a symbol for a definition that doesn't have a known address
290 /// yet.
291 /// @param GetAddress A functor to materialize a definition (fixing the
292 /// address) on demand.
293 ///
294 /// This constructor allows a JIT layer to provide a reference to a symbol
295 /// definition without actually materializing the definition up front. The
296 /// user can materialize the definition at any time by calling the getAddress
297 /// method.
299 : GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {}
300
301 JITSymbol(const JITSymbol&) = delete;
302 JITSymbol& operator=(const JITSymbol&) = delete;
303
305 : GetAddress(std::move(Other.GetAddress)), Flags(std::move(Other.Flags)) {
306 if (Flags.hasError())
307 Err = std::move(Other.Err);
308 else
309 CachedAddr = std::move(Other.CachedAddr);
310 }
311
313 GetAddress = std::move(Other.GetAddress);
314 Flags = std::move(Other.Flags);
315 if (Flags.hasError())
316 Err = std::move(Other.Err);
317 else
318 CachedAddr = std::move(Other.CachedAddr);
319 return *this;
320 }
321
323 if (Flags.hasError())
324 Err.~Error();
325 else
326 CachedAddr.~JITTargetAddress();
327 }
328
329 /// Returns true if the symbol exists, false otherwise.
330 explicit operator bool() const {
331 return !Flags.hasError() && (CachedAddr || GetAddress);
332 }
333
334 /// Move the error field value out of this JITSymbol.
336 if (Flags.hasError())
337 return std::move(Err);
338 return Error::success();
339 }
340
341 /// Get the address of the symbol in the target address space. Returns
342 /// '0' if the symbol does not exist.
344 assert(!Flags.hasError() && "getAddress called on error value");
345 if (GetAddress) {
346 if (auto CachedAddrOrErr = GetAddress()) {
347 GetAddress = nullptr;
348 CachedAddr = *CachedAddrOrErr;
349 assert(CachedAddr && "Symbol could not be materialized.");
350 } else
351 return CachedAddrOrErr.takeError();
352 }
353 return CachedAddr;
354 }
355
356 JITSymbolFlags getFlags() const { return Flags; }
357
358private:
359 GetAddressFtor GetAddress;
360 union {
363 };
364 JITSymbolFlags Flags;
365};
366
367/// Symbol resolution interface.
368///
369/// Allows symbol flags and addresses to be looked up by name.
370/// Symbol queries are done in bulk (i.e. you request resolution of a set of
371/// symbols, rather than a single one) to reduce IPC overhead in the case of
372/// remote JITing, and expose opportunities for parallel compilation.
374public:
375 using LookupSet = std::set<StringRef>;
376 using LookupResult = std::map<StringRef, JITEvaluatedSymbol>;
378
379 virtual ~JITSymbolResolver() = default;
380
381 /// Returns the fully resolved address and flags for each of the given
382 /// symbols.
383 ///
384 /// This method will return an error if any of the given symbols can not be
385 /// resolved, or if the resolution process itself triggers an error.
386 virtual void lookup(const LookupSet &Symbols,
387 OnResolvedFunction OnResolved) = 0;
388
389 /// Returns the subset of the given symbols that should be materialized by
390 /// the caller. Only weak/common symbols should be looked up, as strong
391 /// definitions are implicitly always part of the caller's responsibility.
392 virtual Expected<LookupSet>
393 getResponsibilitySet(const LookupSet &Symbols) = 0;
394
395 /// Specify if this resolver can return valid symbols with zero value.
396 virtual bool allowsZeroSymbols() { return false; }
397
398private:
399 virtual void anchor();
400};
401
402/// Legacy symbol resolution interface.
404public:
405 /// Performs lookup by, for each symbol, first calling
406 /// findSymbolInLogicalDylib and if that fails calling
407 /// findSymbol.
408 void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) final;
409
410 /// Performs flags lookup by calling findSymbolInLogicalDylib and
411 /// returning the flags value for that symbol.
412 Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) final;
413
414 /// This method returns the address of the specified symbol if it exists
415 /// within the logical dynamic library represented by this JITSymbolResolver.
416 /// Unlike findSymbol, queries through this interface should return addresses
417 /// for hidden symbols.
418 ///
419 /// This is of particular importance for the Orc JIT APIs, which support lazy
420 /// compilation by breaking up modules: Each of those broken out modules
421 /// must be able to resolve hidden symbols provided by the others. Clients
422 /// writing memory managers for MCJIT can usually ignore this method.
423 ///
424 /// This method will be queried by RuntimeDyld when checking for previous
425 /// definitions of common symbols.
426 virtual JITSymbol findSymbolInLogicalDylib(const std::string &Name) = 0;
427
428 /// This method returns the address of the specified function or variable.
429 /// It is used to resolve symbols during module linking.
430 ///
431 /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will
432 /// skip all relocations for that symbol, and the client will be responsible
433 /// for handling them manually.
434 virtual JITSymbol findSymbol(const std::string &Name) = 0;
435
436private:
437 void anchor() override;
438};
439
440} // end namespace llvm
441
442#endif // LLVM_EXECUTIONENGINE_JITSYMBOL_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition: Compiler.h:213
Given that RA is a live value
uint64_t Addr
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:479
This file provides a collection of function (or more generally, callable) type erasure utilities supp...
static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
Definition: InlineInfo.cpp:108
#define P(N)
Value * RHS
Value * LHS
ARM-specific JIT symbol flags.
Definition: JITSymbol.h:212
static LLVM_ABI ARMJITSymbolFlags fromObjectSymbol(const object::SymbolRef &Symbol)
Definition: JITSymbol.cpp:94
Lightweight error class with error context and mandatory checking.
Definition: Error.h:159
~Error()
Destroy a Error.
Definition: Error.h:232
static ErrorSuccess success()
Create a success value.
Definition: Error.h:336
Tagged union holding either a T or a Error.
Definition: Error.h:485
Function and variable summary information to aid decisions and implementation of importing.
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:231
JITSymbolFlags getFlags() const
Return the flags for this symbol.
Definition: JITSymbol.h:256
JITTargetAddress getAddress() const
Return the address of this symbol.
Definition: JITSymbol.h:253
JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
Create a symbol for the given address and flags.
Definition: JITSymbol.h:239
void setFlags(JITSymbolFlags Flags)
Set the flags for this symbol.
Definition: JITSymbol.h:259
static JITEvaluatedSymbol fromPointer(T *P, JITSymbolFlags Flags=JITSymbolFlags::Exported)
Create a symbol from the given pointer with the given flags.
Definition: JITSymbol.h:245
JITEvaluatedSymbol(std::nullptr_t)
Create a 'null' symbol.
Definition: JITSymbol.h:236
Flags for symbols in the JIT.
Definition: JITSymbol.h:75
JITSymbolFlags(FlagNames Flags)
Construct a JITSymbolFlags instance from the given flags.
Definition: JITSymbol.h:97
bool hasError() const
Return true if there was an error retrieving this symbol.
Definition: JITSymbol.h:125
TargetFlagsType & getTargetFlags()
Return a reference to the target-specific flags.
Definition: JITSymbol.h:173
const TargetFlagsType & getTargetFlags() const
Return a reference to the target-specific flags.
Definition: JITSymbol.h:176
UnderlyingType getRawFlagsValue() const
Get the underlying flags value as an integer.
Definition: JITSymbol.h:168
JITSymbolFlags & operator|=(const FlagNames &RHS)
Bitwise OR-assignment for FlagNames.
Definition: JITSymbol.h:119
JITSymbolFlags & operator&=(const FlagNames &RHS)
Bitwise AND-assignment for FlagNames.
Definition: JITSymbol.h:113
bool isStrong() const
Returns true if the symbol isn't weak or common.
Definition: JITSymbol.h:140
bool isExported() const
Returns true if the Exported flag is set.
Definition: JITSymbol.h:145
bool hasMaterializationSideEffectsOnly() const
Returns true if this symbol is a materialization-side-effects-only symbol.
Definition: JITSymbol.h:162
bool isCallable() const
Returns true if the given symbol is known to be callable.
Definition: JITSymbol.h:150
static LLVM_ABI Expected< JITSymbolFlags > fromObjectSymbol(const object::SymbolRef &Symbol)
Construct a JITSymbolFlags value based on the flags of the given libobject symbol.
Definition: JITSymbol.cpp:69
JITSymbolFlags()=default
Default-construct a JITSymbolFlags instance.
static LLVM_ABI JITSymbolFlags fromSummary(GlobalValueSummary *S)
Construct a JITSymbolFlags value based on the flags of the given global value summary.
Definition: JITSymbol.cpp:52
bool isCommon() const
Returns true if the Common flag is set.
Definition: JITSymbol.h:135
static LLVM_ABI JITSymbolFlags fromGlobalValue(const GlobalValue &GV)
Construct a JITSymbolFlags value based on the flags of the given global value.
Definition: JITSymbol.cpp:22
bool operator==(const JITSymbolFlags &RHS) const
Compare for equality.
Definition: JITSymbol.h:108
@ MaterializationSideEffectsOnly
Definition: JITSymbol.h:88
bool isWeak() const
Returns true if the Weak flag is set.
Definition: JITSymbol.h:130
JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
Construct a JITSymbolFlags instance from the given flags and target flags.
Definition: JITSymbol.h:101
Symbol resolution interface.
Definition: JITSymbol.h:373
virtual void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved)=0
Returns the fully resolved address and flags for each of the given symbols.
virtual ~JITSymbolResolver()=default
virtual bool allowsZeroSymbols()
Specify if this resolver can return valid symbols with zero value.
Definition: JITSymbol.h:396
std::map< StringRef, JITEvaluatedSymbol > LookupResult
Definition: JITSymbol.h:376
std::set< StringRef > LookupSet
Definition: JITSymbol.h:375
virtual Expected< LookupSet > getResponsibilitySet(const LookupSet &Symbols)=0
Returns the subset of the given symbols that should be materialized by the caller.
Represents a symbol in the JIT.
Definition: JITSymbol.h:267
JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
Create a symbol for a definition with a known address.
Definition: JITSymbol.h:282
JITSymbol & operator=(JITSymbol &&Other)
Definition: JITSymbol.h:312
JITTargetAddress CachedAddr
Definition: JITSymbol.h:361
Error takeError()
Move the error field value out of this JITSymbol.
Definition: JITSymbol.h:335
JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
Create a symbol for a definition that doesn't have a known address yet.
Definition: JITSymbol.h:298
Expected< JITTargetAddress > getAddress()
Get the address of the symbol in the target address space.
Definition: JITSymbol.h:343
JITSymbol(JITSymbol &&Other)
Definition: JITSymbol.h:304
JITSymbol & operator=(const JITSymbol &)=delete
JITSymbol(Error Err)
Create a JITSymbol representing an error in the symbol lookup process (e.g.
Definition: JITSymbol.h:278
JITSymbol(const JITSymbol &)=delete
JITSymbol(JITEvaluatedSymbol Sym)
Construct a JITSymbol from a JITEvaluatedSymbol.
Definition: JITSymbol.h:286
unique_function< Expected< JITTargetAddress >()> GetAddressFtor
Definition: JITSymbol.h:269
JITSymbolFlags getFlags() const
Definition: JITSymbol.h:356
JITSymbol(std::nullptr_t)
Create a 'null' symbol, used to represent a "symbol not found" result from a successful (non-erroneou...
Definition: JITSymbol.h:273
Legacy symbol resolution interface.
Definition: JITSymbol.h:403
virtual JITSymbol findSymbol(const std::string &Name)=0
This method returns the address of the specified function or variable.
virtual JITSymbol findSymbolInLogicalDylib(const std::string &Name)=0
This method returns the address of the specified symbol if it exists within the logical dynamic libra...
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: ObjectFile.h:170
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
APInt operator&(APInt a, const APInt &b)
Definition: APInt.h:2123
T jitTargetAddressToFunction(JITTargetAddress Addr)
Convert a JITTargetAddress to a callable function pointer.
Definition: JITSymbol.h:62
T jitTargetAddressToPointer(JITTargetAddress Addr)
Convert a JITTargetAddress to a pointer.
Definition: JITSymbol.h:51
@ Other
Any other memory.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1886
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Convert a pointer to a JITTargetAddress.
Definition: JITSymbol.h:70
APInt operator|(APInt a, const APInt &b)
Definition: APInt.h:2143
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856