LLVM  8.0.1
JITSymbol.h
Go to the documentation of this file.
1 //===- JITSymbol.h - JIT symbol abstraction ---------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Abstraction for target process addresses.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_JITSYMBOL_H
15 #define LLVM_EXECUTIONENGINE_JITSYMBOL_H
16 
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 
26 #include "llvm/ADT/BitmaskEnum.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/Support/Error.h"
29 
30 namespace llvm {
31 
32 class GlobalValue;
33 
34 namespace object {
35 
36 class SymbolRef;
37 
38 } // end namespace object
39 
40 /// Represents an address in the target process's address space.
41 using JITTargetAddress = uint64_t;
42 
43 /// Convert a JITTargetAddress to a pointer.
44 template <typename T> T jitTargetAddressToPointer(JITTargetAddress Addr) {
45  static_assert(std::is_pointer<T>::value, "T must be a pointer type");
46  uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
47  assert(IntPtr == Addr && "JITTargetAddress value out of range for uintptr_t");
48  return reinterpret_cast<T>(IntPtr);
49 }
50 
51 template <typename T> JITTargetAddress pointerToJITTargetAddress(T *Ptr) {
52  return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Ptr));
53 }
54 
55 /// Flags for symbols in the JIT.
57 public:
58  using UnderlyingType = uint8_t;
59  using TargetFlagsType = uint64_t;
60 
62  None = 0,
63  HasError = 1U << 0,
64  Weak = 1U << 1,
65  Common = 1U << 2,
66  Absolute = 1U << 3,
67  Exported = 1U << 4,
68  Callable = 1U << 5,
69  Lazy = 1U << 6,
70  Materializing = 1U << 7,
71  LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Materializing)
72  };
73 
75  return static_cast<FlagNames>(Orig.Flags & ~Lazy & ~Materializing);
76  }
77 
78  /// Default-construct a JITSymbolFlags instance.
79  JITSymbolFlags() = default;
80 
81  /// Construct a JITSymbolFlags instance from the given flags.
82  JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
83 
84  /// Construct a JITSymbolFlags instance from the given flags and target
85  /// flags.
87  : Flags(Flags), TargetFlags(TargetFlags) {}
88 
89  /// Implicitly convert to bool. Returs true if any flag is set.
90  explicit operator bool() const { return Flags != None || TargetFlags != 0; }
91 
92  /// Compare for equality.
93  bool operator==(const JITSymbolFlags &RHS) const {
94  return Flags == RHS.Flags && TargetFlags == RHS.TargetFlags;
95  }
96 
97  /// Bitwise AND-assignment for FlagNames.
99  Flags &= RHS;
100  return *this;
101  }
102 
103  /// Bitwise OR-assignment for FlagNames.
105  Flags |= RHS;
106  return *this;
107  }
108 
109  /// Return true if there was an error retrieving this symbol.
110  bool hasError() const {
111  return (Flags & HasError) == HasError;
112  }
113 
114  /// Returns true if this is a lazy symbol.
115  /// This flag is used internally by the JIT APIs to track
116  /// materialization states.
117  bool isLazy() const { return Flags & Lazy; }
118 
119  /// Returns true if this symbol is in the process of being
120  /// materialized.
121  bool isMaterializing() const { return Flags & Materializing; }
122 
123  /// Returns true if this symbol is fully materialized.
124  /// (i.e. neither lazy, nor materializing).
125  bool isMaterialized() const { return !(Flags & (Lazy | Materializing)); }
126 
127  /// Returns true if the Weak flag is set.
128  bool isWeak() const {
129  return (Flags & Weak) == Weak;
130  }
131 
132  /// Returns true if the Common flag is set.
133  bool isCommon() const {
134  return (Flags & Common) == Common;
135  }
136 
137  /// Returns true if the symbol isn't weak or common.
138  bool isStrong() const {
139  return !isWeak() && !isCommon();
140  }
141 
142  /// Returns true if the Exported flag is set.
143  bool isExported() const {
144  return (Flags & Exported) == Exported;
145  }
146 
147  /// Returns true if the given symbol is known to be callable.
148  bool isCallable() const { return (Flags & Callable) == Callable; }
149 
150  /// Get the underlying flags value as an integer.
152  return static_cast<UnderlyingType>(Flags);
153  }
154 
155  /// Return a reference to the target-specific flags.
157 
158  /// Return a reference to the target-specific flags.
159  const TargetFlagsType& getTargetFlags() const { return TargetFlags; }
160 
161  /// Construct a JITSymbolFlags value based on the flags of the given global
162  /// value.
163  static JITSymbolFlags fromGlobalValue(const GlobalValue &GV);
164 
165  /// Construct a JITSymbolFlags value based on the flags of the given libobject
166  /// symbol.
168  fromObjectSymbol(const object::SymbolRef &Symbol);
169 
170 private:
171  FlagNames Flags = None;
173 };
174 
176  const JITSymbolFlags::FlagNames &RHS) {
177  JITSymbolFlags Tmp = LHS;
178  Tmp &= RHS;
179  return Tmp;
180 }
181 
183  const JITSymbolFlags::FlagNames &RHS) {
184  JITSymbolFlags Tmp = LHS;
185  Tmp |= RHS;
186  return Tmp;
187 }
188 
189 /// ARM-specific JIT symbol flags.
190 /// FIXME: This should be moved into a target-specific header.
192 public:
193  ARMJITSymbolFlags() = default;
194 
195  enum FlagNames {
196  None = 0,
197  Thumb = 1 << 0
198  };
199 
200  operator JITSymbolFlags::TargetFlagsType&() { return Flags; }
201 
202  static ARMJITSymbolFlags fromObjectSymbol(const object::SymbolRef &Symbol);
203 
204 private:
206 };
207 
208 /// Represents a symbol that has been evaluated to an address already.
210 public:
211  JITEvaluatedSymbol() = default;
212 
213  /// Create a 'null' symbol.
214  JITEvaluatedSymbol(std::nullptr_t) {}
215 
216  /// Create a symbol for the given address and flags.
218  : Address(Address), Flags(Flags) {}
219 
220  /// An evaluated symbol converts to 'true' if its address is non-zero.
221  explicit operator bool() const { return Address != 0; }
222 
223  /// Return the address of this symbol.
224  JITTargetAddress getAddress() const { return Address; }
225 
226  /// Return the flags for this symbol.
227  JITSymbolFlags getFlags() const { return Flags; }
228 
229  /// Set the flags for this symbol.
230  void setFlags(JITSymbolFlags Flags) { this->Flags = std::move(Flags); }
231 
232 private:
234  JITSymbolFlags Flags;
235 };
236 
237 /// Represents a symbol in the JIT.
238 class JITSymbol {
239 public:
240  using GetAddressFtor = std::function<Expected<JITTargetAddress>()>;
241 
242  /// Create a 'null' symbol, used to represent a "symbol not found"
243  /// result from a successful (non-erroneous) lookup.
244  JITSymbol(std::nullptr_t)
245  : CachedAddr(0) {}
246 
247  /// Create a JITSymbol representing an error in the symbol lookup
248  /// process (e.g. a network failure during a remote lookup).
250  : Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
251 
252  /// Create a symbol for a definition with a known address.
254  : CachedAddr(Addr), Flags(Flags) {}
255 
256  /// Construct a JITSymbol from a JITEvaluatedSymbol.
258  : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
259 
260  /// Create a symbol for a definition that doesn't have a known address
261  /// yet.
262  /// @param GetAddress A functor to materialize a definition (fixing the
263  /// address) on demand.
264  ///
265  /// This constructor allows a JIT layer to provide a reference to a symbol
266  /// definition without actually materializing the definition up front. The
267  /// user can materialize the definition at any time by calling the getAddress
268  /// method.
270  : GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {}
271 
272  JITSymbol(const JITSymbol&) = delete;
273  JITSymbol& operator=(const JITSymbol&) = delete;
274 
276  : GetAddress(std::move(Other.GetAddress)), Flags(std::move(Other.Flags)) {
277  if (Flags.hasError())
278  Err = std::move(Other.Err);
279  else
280  CachedAddr = std::move(Other.CachedAddr);
281  }
282 
284  GetAddress = std::move(Other.GetAddress);
285  Flags = std::move(Other.Flags);
286  if (Flags.hasError())
287  Err = std::move(Other.Err);
288  else
289  CachedAddr = std::move(Other.CachedAddr);
290  return *this;
291  }
292 
294  if (Flags.hasError())
295  Err.~Error();
296  else
297  CachedAddr.~JITTargetAddress();
298  }
299 
300  /// Returns true if the symbol exists, false otherwise.
301  explicit operator bool() const {
302  return !Flags.hasError() && (CachedAddr || GetAddress);
303  }
304 
305  /// Move the error field value out of this JITSymbol.
307  if (Flags.hasError())
308  return std::move(Err);
309  return Error::success();
310  }
311 
312  /// Get the address of the symbol in the target address space. Returns
313  /// '0' if the symbol does not exist.
315  assert(!Flags.hasError() && "getAddress called on error value");
316  if (GetAddress) {
317  if (auto CachedAddrOrErr = GetAddress()) {
318  GetAddress = nullptr;
319  CachedAddr = *CachedAddrOrErr;
320  assert(CachedAddr && "Symbol could not be materialized.");
321  } else
322  return CachedAddrOrErr.takeError();
323  }
324  return CachedAddr;
325  }
326 
327  JITSymbolFlags getFlags() const { return Flags; }
328 
329 private:
330  GetAddressFtor GetAddress;
331  union {
334  };
335  JITSymbolFlags Flags;
336 };
337 
338 /// Symbol resolution interface.
339 ///
340 /// Allows symbol flags and addresses to be looked up by name.
341 /// Symbol queries are done in bulk (i.e. you request resolution of a set of
342 /// symbols, rather than a single one) to reduce IPC overhead in the case of
343 /// remote JITing, and expose opportunities for parallel compilation.
345 public:
346  using LookupSet = std::set<StringRef>;
347  using LookupResult = std::map<StringRef, JITEvaluatedSymbol>;
348  using OnResolvedFunction = std::function<void(Expected<LookupResult>)>;
349 
350  virtual ~JITSymbolResolver() = default;
351 
352  /// Returns the fully resolved address and flags for each of the given
353  /// symbols.
354  ///
355  /// This method will return an error if any of the given symbols can not be
356  /// resolved, or if the resolution process itself triggers an error.
357  virtual void lookup(const LookupSet &Symbols,
358  OnResolvedFunction OnResolved) = 0;
359 
360  /// Returns the subset of the given symbols that should be materialized by
361  /// the caller. Only weak/common symbols should be looked up, as strong
362  /// definitions are implicitly always part of the caller's responsibility.
363  virtual Expected<LookupSet>
364  getResponsibilitySet(const LookupSet &Symbols) = 0;
365 
366 private:
367  virtual void anchor();
368 };
369 
370 /// Legacy symbol resolution interface.
372 public:
373  /// Performs lookup by, for each symbol, first calling
374  /// findSymbolInLogicalDylib and if that fails calling
375  /// findSymbol.
376  void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) final;
377 
378  /// Performs flags lookup by calling findSymbolInLogicalDylib and
379  /// returning the flags value for that symbol.
380  Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) final;
381 
382  /// This method returns the address of the specified symbol if it exists
383  /// within the logical dynamic library represented by this JITSymbolResolver.
384  /// Unlike findSymbol, queries through this interface should return addresses
385  /// for hidden symbols.
386  ///
387  /// This is of particular importance for the Orc JIT APIs, which support lazy
388  /// compilation by breaking up modules: Each of those broken out modules
389  /// must be able to resolve hidden symbols provided by the others. Clients
390  /// writing memory managers for MCJIT can usually ignore this method.
391  ///
392  /// This method will be queried by RuntimeDyld when checking for previous
393  /// definitions of common symbols.
394  virtual JITSymbol findSymbolInLogicalDylib(const std::string &Name) = 0;
395 
396  /// This method returns the address of the specified function or variable.
397  /// It is used to resolve symbols during module linking.
398  ///
399  /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will
400  /// skip all relocations for that symbol, and the client will be responsible
401  /// for handling them manually.
402  virtual JITSymbol findSymbol(const std::string &Name) = 0;
403 
404 private:
405  virtual void anchor();
406 };
407 
408 } // end namespace llvm
409 
410 #endif // LLVM_EXECUTIONENGINE_JITSYMBOL_H
bool isLazy() const
Returns true if this is a lazy symbol.
Definition: JITSymbol.h:117
const NoneType None
Definition: None.h:24
std::function< void(Expected< LookupResult >)> OnResolvedFunction
Definition: JITSymbol.h:348
#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue)
LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can perform bitwise operatio...
Definition: BitmaskEnum.h:42
Represents a symbol in the JIT.
Definition: JITSymbol.h:238
bool isCommon() const
Returns true if the Common flag is set.
Definition: JITSymbol.h:133
This class represents lattice values for constants.
Definition: AllocatorList.h:24
JITSymbolFlags getFlags() const
Return the flags for this symbol.
Definition: JITSymbol.h:227
Legacy symbol resolution interface.
Definition: JITSymbol.h:371
bool isStrong() const
Returns true if the symbol isn&#39;t weak or common.
Definition: JITSymbol.h:138
APInt operator &(APInt a, const APInt &b)
Definition: APInt.h:1979
bool operator==(const JITSymbolFlags &RHS) const
Compare for equality.
Definition: JITSymbol.h:93
std::set< StringRef > LookupSet
Definition: JITSymbol.h:346
T jitTargetAddressToPointer(JITTargetAddress Addr)
Convert a JITTargetAddress to a pointer.
Definition: JITSymbol.h:44
JITSymbol & operator=(JITSymbol &&Other)
Definition: JITSymbol.h:283
bool isWeak() const
Returns true if the Weak flag is set.
Definition: JITSymbol.h:128
JITSymbolFlags getFlags() const
Definition: JITSymbol.h:327
bool isMaterializing() const
Returns true if this symbol is in the process of being materialized.
Definition: JITSymbol.h:121
void setFlags(JITSymbolFlags Flags)
Set the flags for this symbol.
Definition: JITSymbol.h:230
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Definition: BitVector.h:938
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
static const uint16_t * lookup(unsigned opcode, unsigned domain, ArrayRef< uint16_t[3]> Table)
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:784
const TargetFlagsType & getTargetFlags() const
Return a reference to the target-specific flags.
Definition: JITSymbol.h:159
JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
Construct a JITSymbolFlags instance from the given flags and target flags.
Definition: JITSymbol.h:86
uint64_t TargetFlagsType
Definition: JITSymbol.h:59
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:41
JITSymbol(Error Err)
Create a JITSymbol representing an error in the symbol lookup process (e.g.
Definition: JITSymbol.h:249
bool isCallable() const
Returns true if the given symbol is known to be callable.
Definition: JITSymbol.h:148
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Definition: JITSymbol.h:51
JITEvaluatedSymbol(std::nullptr_t)
Create a &#39;null&#39; symbol.
Definition: JITSymbol.h:214
JITSymbolFlags(FlagNames Flags)
Construct a JITSymbolFlags instance from the given flags.
Definition: JITSymbol.h:82
Flags for symbols in the JIT.
Definition: JITSymbol.h:56
Symbol resolution interface.
Definition: JITSymbol.h:344
JITSymbol(JITEvaluatedSymbol Sym)
Construct a JITSymbol from a JITEvaluatedSymbol.
Definition: JITSymbol.h:257
JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
Create a symbol for the given address and flags.
Definition: JITSymbol.h:217
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
bool isMaterialized() const
Returns true if this symbol is fully materialized.
Definition: JITSymbol.h:125
JITSymbol(JITSymbol &&Other)
Definition: JITSymbol.h:275
Expected< JITTargetAddress > getAddress()
Get the address of the symbol in the target address space.
Definition: JITSymbol.h:314
bool hasError() const
Return true if there was an error retrieving this symbol.
Definition: JITSymbol.h:110
UnderlyingType getRawFlagsValue() const
Get the underlying flags value as an integer.
Definition: JITSymbol.h:151
uint8_t UnderlyingType
Definition: JITSymbol.h:58
static bool isWeak(const MCSymbolELF &Sym)
JITSymbol(std::nullptr_t)
Create a &#39;null&#39; symbol, used to represent a "symbol not found" result from a successful (non-erroneou...
Definition: JITSymbol.h:244
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:209
This is a value type class that represents a single symbol in the list of symbols in the object file...
Definition: ObjectFile.h:141
std::function< Expected< JITTargetAddress >()> GetAddressFtor
Definition: JITSymbol.h:240
bool isExported() const
Returns true if the Exported flag is set.
Definition: JITSymbol.h:143
JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
Create a symbol for a definition with a known address.
Definition: JITSymbol.h:253
TargetFlagsType & getTargetFlags()
Return a reference to the target-specific flags.
Definition: JITSymbol.h:156
JITSymbolFlags & operator|=(const FlagNames &RHS)
Bitwise OR-assignment for FlagNames.
Definition: JITSymbol.h:104
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
E & operator &=(E &LHS, E RHS)
Definition: BitmaskEnum.h:134
std::map< StringRef, JITEvaluatedSymbol > LookupResult
Definition: JITSymbol.h:347
ARM-specific JIT symbol flags.
Definition: JITSymbol.h:191
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
static JITSymbolFlags stripTransientFlags(JITSymbolFlags Orig)
Definition: JITSymbol.h:74
JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
Create a symbol for a definition that doesn&#39;t have a known address yet.
Definition: JITSymbol.h:269
Error takeError()
Move the error field value out of this JITSymbol.
Definition: JITSymbol.h:306
JITTargetAddress getAddress() const
Return the address of this symbol.
Definition: JITSymbol.h:224
APInt operator|(APInt a, const APInt &b)
Definition: APInt.h:1999
JITTargetAddress CachedAddr
Definition: JITSymbol.h:332