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