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