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