1 //===- JITSymbol.h - JIT symbol abstraction ---------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Abstraction for target process addresses.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_EXECUTIONENGINE_JITSYMBOL_H
15 #define LLVM_EXECUTIONENGINE_JITSYMBOL_H
24 #include "llvm/Support/Error.h"
34 } // end namespace object
36 /// @brief Represents an address in the target process's address space.
37 using JITTargetAddress = uint64_t;
39 /// @brief Flags for symbols in the JIT.
40 class JITSymbolFlags {
42 using UnderlyingType = uint8_t;
44 enum FlagNames : UnderlyingType {
53 /// @brief Default-construct a JITSymbolFlags instance.
54 JITSymbolFlags() = default;
56 /// @brief Construct a JITSymbolFlags instance from the given flags.
57 JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
59 /// @brief Return true if there was an error retrieving this symbol.
60 bool hasError() const {
61 return (Flags & HasError) == HasError;
64 /// @brief Returns true is the Weak flag is set.
66 return (Flags & Weak) == Weak;
69 /// @brief Returns true is the Weak flag is set.
70 bool isCommon() const {
71 return (Flags & Common) == Common;
74 bool isStrongDefinition() const {
75 return !isWeak() && !isCommon();
78 /// @brief Returns true is the Weak flag is set.
79 bool isExported() const {
80 return (Flags & Exported) == Exported;
83 operator UnderlyingType&() { return Flags; }
85 /// Construct a JITSymbolFlags value based on the flags of the given global
87 static JITSymbolFlags fromGlobalValue(const GlobalValue &GV);
89 /// Construct a JITSymbolFlags value based on the flags of the given libobject
91 static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol);
94 UnderlyingType Flags = None;
97 /// @brief Represents a symbol that has been evaluated to an address already.
98 class JITEvaluatedSymbol {
100 /// @brief Create a 'null' symbol.
101 JITEvaluatedSymbol(std::nullptr_t) {}
103 /// @brief Create a symbol for the given address and flags.
104 JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
105 : Address(Address), Flags(Flags) {}
107 /// @brief An evaluated symbol converts to 'true' if its address is non-zero.
108 explicit operator bool() const { return Address != 0; }
110 /// @brief Return the address of this symbol.
111 JITTargetAddress getAddress() const { return Address; }
113 /// @brief Return the flags for this symbol.
114 JITSymbolFlags getFlags() const { return Flags; }
117 JITTargetAddress Address = 0;
118 JITSymbolFlags Flags;
121 /// @brief Represents a symbol in the JIT.
124 using GetAddressFtor = std::function<Expected<JITTargetAddress>()>;
126 /// @brief Create a 'null' symbol, used to represent a "symbol not found"
127 /// result from a successful (non-erroneous) lookup.
128 JITSymbol(std::nullptr_t)
131 /// @brief Create a JITSymbol representing an error in the symbol lookup
132 /// process (e.g. a network failure during a remote lookup).
134 : Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
136 /// @brief Create a symbol for a definition with a known address.
137 JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
138 : CachedAddr(Addr), Flags(Flags) {}
140 /// @brief Construct a JITSymbol from a JITEvaluatedSymbol.
141 JITSymbol(JITEvaluatedSymbol Sym)
142 : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
144 /// @brief Create a symbol for a definition that doesn't have a known address
146 /// @param GetAddress A functor to materialize a definition (fixing the
147 /// address) on demand.
149 /// This constructor allows a JIT layer to provide a reference to a symbol
150 /// definition without actually materializing the definition up front. The
151 /// user can materialize the definition at any time by calling the getAddress
153 JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
154 : GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {}
156 JITSymbol(const JITSymbol&) = delete;
157 JITSymbol& operator=(const JITSymbol&) = delete;
159 JITSymbol(JITSymbol &&Other)
160 : GetAddress(std::move(Other.GetAddress)), Flags(std::move(Other.Flags)) {
161 if (Flags.hasError())
162 Err = std::move(Other.Err);
164 CachedAddr = std::move(Other.CachedAddr);
167 JITSymbol& operator=(JITSymbol &&Other) {
168 GetAddress = std::move(Other.GetAddress);
169 Flags = std::move(Other.Flags);
170 if (Flags.hasError())
171 Err = std::move(Other.Err);
173 CachedAddr = std::move(Other.CachedAddr);
178 if (Flags.hasError())
181 CachedAddr.~JITTargetAddress();
184 /// @brief Returns true if the symbol exists, false otherwise.
185 explicit operator bool() const {
186 return !Flags.hasError() && (CachedAddr || GetAddress);
189 /// @brief Move the error field value out of this JITSymbol.
191 if (Flags.hasError())
192 return std::move(Err);
193 return Error::success();
196 /// @brief Get the address of the symbol in the target address space. Returns
197 /// '0' if the symbol does not exist.
198 Expected<JITTargetAddress> getAddress() {
199 assert(!Flags.hasError() && "getAddress called on error value");
201 if (auto CachedAddrOrErr = GetAddress()) {
202 GetAddress = nullptr;
203 CachedAddr = *CachedAddrOrErr;
204 assert(CachedAddr && "Symbol could not be materialized.");
206 return CachedAddrOrErr.takeError();
211 JITSymbolFlags getFlags() const { return Flags; }
214 GetAddressFtor GetAddress;
216 JITTargetAddress CachedAddr;
219 JITSymbolFlags Flags;
222 /// \brief Symbol resolution.
223 class JITSymbolResolver {
225 virtual ~JITSymbolResolver() = default;
227 /// This method returns the address of the specified symbol if it exists
228 /// within the logical dynamic library represented by this JITSymbolResolver.
229 /// Unlike findSymbol, queries through this interface should return addresses
230 /// for hidden symbols.
232 /// This is of particular importance for the Orc JIT APIs, which support lazy
233 /// compilation by breaking up modules: Each of those broken out modules
234 /// must be able to resolve hidden symbols provided by the others. Clients
235 /// writing memory managers for MCJIT can usually ignore this method.
237 /// This method will be queried by RuntimeDyld when checking for previous
238 /// definitions of common symbols.
239 virtual JITSymbol findSymbolInLogicalDylib(const std::string &Name) = 0;
241 /// This method returns the address of the specified function or variable.
242 /// It is used to resolve symbols during module linking.
244 /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will
245 /// skip all relocations for that symbol, and the client will be responsible
246 /// for handling them manually.
247 virtual JITSymbol findSymbol(const std::string &Name) = 0;
250 virtual void anchor();
253 } // end namespace llvm
255 #endif // LLVM_EXECUTIONENGINE_JITSYMBOL_H