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