llvm.org GIT mirror llvm / 63cc4f5
[Orc] New JIT APIs. This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to cleanly support a wider range of JIT use cases in LLVM, and encourage the development and contribution of re-usable infrastructure for LLVM JIT use-cases. These APIs are intended to live alongside the MCJIT APIs, and should not affect existing clients. Included in this patch: 1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of components for building JIT infrastructure. Implementation code for these headers lives in lib/ExecutionEngine/Orc. 2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the new components. 3) Minor changes to RTDyldMemoryManager needed to support the new components. These changes should not impact existing clients. 4) A new flag for lli, -use-orcmcjit, which will cause lli to use the OrcMCJITReplacement class as its underlying execution engine, rather than MCJIT itself. Tests to follow shortly. Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher, Justin Bogner, and Jim Grosbach for extensive feedback and discussion. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226940 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 5 years ago
29 changed file(s) with 2428 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
142142 std::string *ErrorStr,
143143 std::unique_ptr MCJMM,
144144 std::unique_ptr TM);
145
146 static ExecutionEngine *(*OrcMCJITReplacementCtor)(
147 std::string *ErrorStr,
148 std::unique_ptr OrcJMM,
149 std::unique_ptr TM);
150
145151 static ExecutionEngine *(*InterpCtor)(std::unique_ptr M,
146152 std::string *ErrorStr);
147153
463469 }
464470
465471 protected:
472 ExecutionEngine() : EEState(*this) {}
466473 explicit ExecutionEngine(std::unique_ptr M);
467474
468475 void emitGlobals();
500507 std::string MCPU;
501508 SmallVector MAttrs;
502509 bool VerifyModules;
510 bool UseOrcMCJITReplacement;
503511
504512 /// InitEngine - Does the common initialization of default options.
505513 void InitEngine();
506514
507515 public:
516 /// Default constructor for EngineBuilder.
517 EngineBuilder();
518
508519 /// Constructor for EngineBuilder.
509520 EngineBuilder(std::unique_ptr M);
510521
589600 return *this;
590601 }
591602
603 // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default.
604 void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) {
605 this->UseOrcMCJITReplacement = UseOrcMCJITReplacement;
606 }
607
592608 TargetMachine *selectTarget();
593609
594610 /// selectTarget - Pick a target either via -march or by guessing the native
0 //===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares a wrapper class to hold the memory into which an
10 // object will be generated.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
15 #define LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
16
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/Support/MemoryBuffer.h"
19 #include "llvm/Support/raw_ostream.h"
20
21 namespace llvm {
22
23 /// \brief SmallVector-backed MemoryBuffer instance.
24 ///
25 /// This class enables efficient construction of MemoryBuffers from SmallVector
26 /// instances. This is useful for MCJIT and Orc, where object files are streamed
27 /// into SmallVectors, then inspected using ObjectFile (which takes a
28 /// MemoryBuffer).
29 class ObjectMemoryBuffer : public MemoryBuffer {
30 public:
31
32 /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value.
33 ///
34 /// FIXME: It'd be nice for this to be a non-templated constructor taking a
35 /// SmallVectorImpl here instead of a templated one taking a SmallVector,
36 /// but SmallVector's move-construction/assignment currently only take
37 /// SmallVectors. If/when that is fixed we can simplify this constructor and
38 /// the following one.
39 ObjectMemoryBuffer(SmallVectorImpl &&SV)
40 : SV(std::move(SV)), BufferName("") {
41 init(this->SV.begin(), this->SV.end(), false);
42 }
43
44 /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector
45 /// r-value and StringRef.
46 ObjectMemoryBuffer(SmallVectorImpl &&SV, StringRef Name)
47 : SV(std::move(SV)), BufferName(Name) {
48 init(this->SV.begin(), this->SV.end(), false);
49 }
50
51 const char* getBufferIdentifier() const override { return BufferName.c_str(); }
52
53 BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
54
55 private:
56 SmallVector SV;
57 std::string BufferName;
58 };
59
60 } // namespace llvm
61
62 #endif
0 //===-- CloneSubModule.h - Utilities for extracting sub-modules -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains utilities for extracting sub-modules. Useful for breaking up modules
10 // for lazy jitting.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H
15 #define LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H
16
17 #include "llvm/Transforms/Utils/ValueMapper.h"
18 #include
19
20 namespace llvm {
21
22 class Function;
23 class GlobalVariable;
24 class Module;
25
26 typedef std::function
27 ValueToValueMapTy &)> HandleGlobalVariableFtor;
28
29 typedef std::function
30 HandleFunctionFtor;
31
32 void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig,
33 ValueToValueMapTy &VMap);
34
35 void copyFunctionBody(Function &New, const Function &Orig,
36 ValueToValueMapTy &VMap);
37
38 std::unique_ptr
39 CloneSubModule(const Module &M, HandleGlobalVariableFtor HandleGlobalVariable,
40 HandleFunctionFtor HandleFunction, bool KeepInlineAsm);
41 }
42
43 #endif // LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H
0 //===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // JIT layer for breaking up modules and inserting callbacks to allow
10 // individual functions to be compiled on demand.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
16
17 #include "IndirectionUtils.h"
18
19 namespace llvm {
20
21 /// @brief Compile-on-demand layer.
22 ///
23 /// Modules added to this layer have their calls indirected, and are then
24 /// broken up into a set of single-function modules, each of which is added
25 /// to the layer below in a singleton set. The lower layer can be any layer that
26 /// accepts IR module sets.
27 ///
28 /// It is expected that this layer will frequently be used on top of a
29 /// LazyEmittingLayer. The combination of the two ensures that each function is
30 /// compiled only when it is first called.
31 template class CompileOnDemandLayer {
32 public:
33 /// @brief Lookup helper that provides compatibility with the classic
34 /// static-compilation symbol resolution process.
35 ///
36 /// The CompileOnDemand (COD) layer splits modules up into multiple
37 /// sub-modules, each held in its own llvm::Module instance, in order to
38 /// support lazy compilation. When a module that contains private symbols is
39 /// broken up symbol linkage changes may be required to enable access to
40 /// "private" data that now resides in a different llvm::Module instance. To
41 /// retain expected symbol resolution behavior for clients of the COD layer,
42 /// the CODScopedLookup class uses a two-tiered lookup system to resolve
43 /// symbols. Lookup first scans sibling modules that were split from the same
44 /// original module (logical-module scoped lookup), then scans all other
45 /// modules that have been added to the lookup scope (logical-dylib scoped
46 /// lookup).
47 class CODScopedLookup {
48 private:
49 typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
50 typedef std::vector SiblingHandlesList;
51 typedef std::list PseudoDylibModuleSetHandlesList;
52
53 public:
54 /// @brief Handle for a logical module.
55 typedef typename PseudoDylibModuleSetHandlesList::iterator LMHandle;
56
57 /// @brief Construct a scoped lookup.
58 CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
59
60 /// @brief Start a new context for a single logical module.
61 LMHandle createLogicalModule() {
62 Handles.push_back(SiblingHandlesList());
63 return std::prev(Handles.end());
64 }
65
66 /// @brief Add a concrete Module's handle to the given logical Module's
67 /// lookup scope.
68 void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) {
69 LMH->push_back(H);
70 }
71
72 /// @brief Remove a logical Module from the CODScopedLookup entirely.
73 void removeLogicalModule(LMHandle LMH) { Handles.erase(LMH); }
74
75 /// @brief Look up a symbol in this context.
76 uint64_t lookup(LMHandle LMH, const std::string &Name) {
77 if (uint64_t Addr = lookupOnlyIn(LMH, Name))
78 return Addr;
79
80 for (auto I = Handles.begin(), E = Handles.end(); I != E; ++I)
81 if (I != LMH)
82 if (uint64_t Addr = lookupOnlyIn(I, Name))
83 return Addr;
84
85 return 0;
86 }
87
88 private:
89 uint64_t lookupOnlyIn(LMHandle LMH, const std::string &Name) {
90 for (auto H : *LMH)
91 if (uint64_t Addr = BaseLayer.lookupSymbolAddressIn(H, Name, false))
92 return Addr;
93 return 0;
94 }
95
96 BaseLayerT &BaseLayer;
97 PseudoDylibModuleSetHandlesList Handles;
98 };
99
100 private:
101 typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
102 typedef std::vector BaseLayerModuleSetHandleListT;
103
104 struct ModuleSetInfo {
105 // Symbol lookup - just one for the whole module set.
106 std::shared_ptr Lookup;
107
108 // Logical module handles.
109 std::vector LMHandles;
110
111 // Persistent manglers - one per TU.
112 std::vector PersistentManglers;
113
114 // Symbol resolution callback handlers - one per TU.
115 std::vector>
116 JITResolveCallbackHandlers;
117
118 // List of vectors of module set handles:
119 // One vector per logical module - each vector holds the handles for the
120 // exploded modules for that logical module in the base layer.
121 BaseLayerModuleSetHandleListT BaseLayerModuleSetHandles;
122
123 ModuleSetInfo(std::shared_ptr Lookup)
124 : Lookup(std::move(Lookup)) {}
125
126 void releaseResources(BaseLayerT &BaseLayer) {
127 for (auto LMH : LMHandles)
128 Lookup->removeLogicalModule(LMH);
129 for (auto H : BaseLayerModuleSetHandles)
130 BaseLayer.removeModuleSet(H);
131 }
132 };
133
134 typedef std::list ModuleSetInfoListT;
135
136 public:
137 /// @brief Handle to a set of loaded modules.
138 typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT;
139
140 /// @brief Convenience typedef for callback inserter.
141 typedef std::function
142 InsertCallbackAsmFtor;
143
144 /// @brief Construct a compile-on-demand layer instance.
145 CompileOnDemandLayer(BaseLayerT &BaseLayer,
146 InsertCallbackAsmFtor InsertCallbackAsm)
147 : BaseLayer(BaseLayer), InsertCallbackAsm(InsertCallbackAsm) {}
148
149 /// @brief Add a module to the compile-on-demand layer.
150 template
151 ModuleSetHandleT addModuleSet(ModuleSetT Ms,
152 std::unique_ptr MM) {
153
154 const char *JITAddrSuffix = "$orc_addr";
155 const char *JITImplSuffix = "$orc_impl";
156
157 // Create a symbol lookup context and ModuleSetInfo for this module set.
158 auto DylibLookup = std::make_shared(BaseLayer);
159 ModuleSetHandleT H =
160 ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup));
161 ModuleSetInfo &MSI = ModuleSetInfos.back();
162
163 // Process each of the modules in this module set. All modules share the
164 // same lookup context, but each will get its own TU lookup context.
165 for (auto &M : Ms) {
166
167 // Create a TU lookup context for this module.
168 auto LMH = DylibLookup->createLogicalModule();
169 MSI.LMHandles.push_back(LMH);
170
171 // Create a persistent mangler for this module.
172 MSI.PersistentManglers.emplace_back(*M->getDataLayout());
173
174 // Make all calls to functions defined in this module indirect.
175 JITIndirections Indirections =
176 makeCallsDoubleIndirect(*M, [](const Function &) { return true; },
177 JITImplSuffix, JITAddrSuffix);
178
179 // Then carve up the module into a bunch of single-function modules.
180 std::vector> ExplodedModules =
181 explode(*M, Indirections);
182
183 // Add a resolve-callback handler for this module to look up symbol
184 // addresses when requested via a callback.
185 MSI.JITResolveCallbackHandlers.push_back(
186 createCallbackHandlerFromJITIndirections(
187 Indirections, MSI.PersistentManglers.back(),
188 [=](StringRef S) { return DylibLookup->lookup(LMH, S); }));
189
190 // Insert callback asm code into the first module.
191 InsertCallbackAsm(*ExplodedModules[0],
192 *MSI.JITResolveCallbackHandlers.back());
193
194 // Now we need to take each of the extracted Modules and add them to
195 // base layer. Each Module will be added individually to make sure they
196 // can be compiled separately, and each will get its own lookaside
197 // memory manager with lookup functors that resolve symbols in sibling
198 // modules first.OA
199 for (auto &M : ExplodedModules) {
200 std::vector> MSet;
201 MSet.push_back(std::move(M));
202
203 BaseLayerModuleSetHandleT H = BaseLayer.addModuleSet(
204 std::move(MSet),
205 createLookasideRTDyldMM(
206 [=](const std::string &Name) {
207 if (uint64_t Addr = DylibLookup->lookup(LMH, Name))
208 return Addr;
209 return getSymbolAddress(Name, true);
210 },
211 [=](const std::string &Name) {
212 return DylibLookup->lookup(LMH, Name);
213 }));
214 DylibLookup->addToLogicalModule(LMH, H);
215 MSI.BaseLayerModuleSetHandles.push_back(H);
216 }
217
218 initializeFuncAddrs(*MSI.JITResolveCallbackHandlers.back(), Indirections,
219 MSI.PersistentManglers.back(), [=](StringRef S) {
220 return DylibLookup->lookup(LMH, S);
221 });
222 }
223
224 return H;
225 }
226
227 /// @brief Remove the module represented by the given handle.
228 ///
229 /// This will remove all modules in the layers below that were derived from
230 /// the module represented by H.
231 void removeModuleSet(ModuleSetHandleT H) {
232 H->releaseResources(BaseLayer);
233 ModuleSetInfos.erase(H);
234 }
235
236 /// @brief Get the address of a symbol provided by this layer, or some layer
237 /// below this one.
238 uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
239 return BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly);
240 }
241
242 /// @brief Get the address of a symbol provided by this layer, or some layer
243 /// below this one.
244 uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
245 bool ExportedSymbolsOnly) {
246 BaseLayerModuleSetHandleListT &BaseLayerHandles = H->second;
247 for (auto &BH : BaseLayerHandles) {
248 if (uint64_t Addr =
249 BaseLayer.lookupSymbolAddressIn(BH, Name, ExportedSymbolsOnly))
250 return Addr;
251 }
252 return 0;
253 }
254
255 private:
256 BaseLayerT &BaseLayer;
257 InsertCallbackAsmFtor InsertCallbackAsm;
258 ModuleSetInfoListT ModuleSetInfos;
259 };
260 }
261
262 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
0 //===-- CompileUtils.h - Utilities for compiling IR in the JIT --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains utilities for compiling IR to object files.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
14 #define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
15
16 #include "llvm/PassManager.h"
17 #include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/Object/ObjectFile.h"
20 #include "llvm/Target/TargetMachine.h"
21
22 namespace llvm {
23
24 /// @brief Simple compile functor: Takes a single IR module and returns an
25 /// ObjectFile.
26 class SimpleCompiler {
27 public:
28 /// @brief Construct a simple compile functor with the given target.
29 SimpleCompiler(TargetMachine &TM) : TM(TM) {}
30
31 /// @brief Compile a Module to an ObjectFile.
32 object::OwningBinary operator()(Module &M) const {
33 SmallVector ObjBufferSV;
34 raw_svector_ostream ObjStream(ObjBufferSV);
35
36 PassManager PM;
37 MCContext *Ctx;
38 if (TM.addPassesToEmitMC(PM, Ctx, ObjStream))
39 llvm_unreachable("Target does not support MC emission.");
40 PM.run(M);
41 ObjStream.flush();
42 std::unique_ptr ObjBuffer(
43 new ObjectMemoryBuffer(std::move(ObjBufferSV)));
44 ErrorOr> Obj =
45 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
46 // TODO: Actually report errors helpfully.
47 typedef object::OwningBinary OwningObj;
48 if (Obj)
49 return OwningObj(std::move(*Obj), std::move(ObjBuffer));
50 return OwningObj(nullptr, nullptr);
51 }
52
53 private:
54 TargetMachine &TM;
55 };
56 }
57
58 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
0 //===------ IRCompileLayer.h -- Eagerly compile IR for JIT ------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains the definition for a basic, eagerly compiling layer of the JIT.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
15
16 #include "llvm/ExecutionEngine/ObjectCache.h"
17 #include
18
19 namespace llvm {
20
21 /// @brief Eager IR compiling layer.
22 ///
23 /// This layer accepts sets of LLVM IR Modules (via addModuleSet). It
24 /// immediately compiles each IR module to an object file (each IR Module is
25 /// compiled separately). The resulting set of object files is then added to
26 /// the layer below, which must implement the object layer concept.
27 template class IRCompileLayer {
28 public:
29 typedef std::function(Module &)>
30 CompileFtor;
31
32 private:
33 typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;
34
35 typedef std::vector> OwningObjectVec;
36 typedef std::vector> OwningBufferVec;
37
38 public:
39 /// @brief Handle to a set of compiled modules.
40 typedef ObjSetHandleT ModuleSetHandleT;
41
42 /// @brief Construct an IRCompileLayer with the given BaseLayer, which must
43 /// implement the ObjectLayer concept.
44 IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile)
45 : BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {}
46
47 /// @brief Set an ObjectCache to query before compiling.
48 void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
49
50 /// @brief Compile each module in the given module set, then then add the
51 /// resulting set of objects to the base layer, along with the memory
52 // manager MM.
53 ///
54 /// @return A handle for the added modules.
55 template
56 ModuleSetHandleT addModuleSet(ModuleSetT Ms,
57 std::unique_ptr MM) {
58 OwningObjectVec Objects;
59 OwningBufferVec Buffers;
60
61 for (const auto &M : Ms) {
62 std::unique_ptr Object;
63 std::unique_ptr Buffer;
64
65 if (ObjCache)
66 std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary();
67
68 if (!Object) {
69 std::tie(Object, Buffer) = Compile(*M).takeBinary();
70 if (ObjCache)
71 ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef());
72 }
73
74 Objects.push_back(std::move(Object));
75 Buffers.push_back(std::move(Buffer));
76 }
77
78 return BaseLayer.addObjectSet(std::move(Objects), std::move(MM));
79 }
80
81 /// @brief Remove the module set associated with the handle H.
82 void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); }
83
84 /// @brief Get the address of a loaded symbol. This call is forwarded to the
85 /// base layer's getSymbolAddress implementation.
86 uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
87 return BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly);
88 }
89
90 /// @brief Get the address of the given symbol in the context of the set of
91 /// compiled modules represented by the handle H. This call is
92 /// forwarded to the base layer's implementation.
93 uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
94 bool ExportedSymbolsOnly) {
95 return BaseLayer.lookupSymbolAddressIn(H, Name, ExportedSymbolsOnly);
96 }
97
98 private:
99 object::OwningBinary
100 tryToLoadFromObjectCache(const Module &M) {
101 std::unique_ptr ObjBuffer = ObjCache->getObject(&M);
102 if (!ObjBuffer)
103 return {nullptr, nullptr};
104
105 ErrorOr> Obj =
106 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
107 if (!Obj)
108 return {nullptr, nullptr};
109
110 return {std::move(*Obj), std::move(ObjBuffer)};
111 }
112
113 BaseLayerT &BaseLayer;
114 CompileFtor Compile;
115 ObjectCache *ObjCache;
116 };
117 }
118
119 #endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H
0 //===-- IndirectionUtils.h - Utilities for adding indirections --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains utilities for adding indirections and breaking up modules.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
14 #define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
15
16 #include "llvm/IR/Mangler.h"
17 #include "llvm/IR/Module.h"
18 #include
19
20 namespace llvm {
21
22 /// @brief Persistent name mangling.
23 ///
24 /// This class provides name mangling that can outlive a Module (and its
25 /// DataLayout).
26 class PersistentMangler {
27 public:
28 PersistentMangler(DataLayout DL) : DL(std::move(DL)), M(&this->DL) {}
29
30 std::string getMangledName(StringRef Name) const {
31 std::string MangledName;
32 {
33 raw_string_ostream MangledNameStream(MangledName);
34 M.getNameWithPrefix(MangledNameStream, Name);
35 }
36 return MangledName;
37 }
38
39 private:
40 DataLayout DL;
41 Mangler M;
42 };
43
44 /// @brief Handle callbacks from the JIT process requesting the definitions of
45 /// symbols.
46 ///
47 /// This utility is intended to be used to support compile-on-demand for
48 /// functions.
49 class JITResolveCallbackHandler {
50 private:
51 typedef std::vector FuncNameList;
52
53 public:
54 typedef FuncNameList::size_type StubIndex;
55
56 public:
57 /// @brief Create a JITResolveCallbackHandler with the given functors for
58 /// looking up symbols and updating their use-sites.
59 ///
60 /// @return A JITResolveCallbackHandler instance that will invoke the
61 /// Lookup and Update functors as needed to resolve missing symbol
62 /// definitions.
63 template
64 static std::unique_ptr create(LookupFtor Lookup,
65 UpdateFtor Update);
66
67 /// @brief Destroy instance. Does not modify existing emitted symbols.
68 ///
69 /// Not-yet-emitted symbols will need to be resolved some other way after
70 /// this class is destroyed.
71 virtual ~JITResolveCallbackHandler() {}
72
73 /// @brief Add a function to be resolved on demand.
74 void addFuncName(std::string Name) { FuncNames.push_back(std::move(Name)); }
75
76 /// @brief Get the name associated with the given index.
77 const std::string &getFuncName(StubIndex Idx) const { return FuncNames[Idx]; }
78
79 /// @brief Returns the number of symbols being managed by this instance.
80 StubIndex getNumFuncs() const { return FuncNames.size(); }
81
82 /// @brief Get the address for the symbol associated with the given index.
83 ///
84 /// This is expected to be called by code in the JIT process itself, in
85 /// order to resolve a function.
86 virtual uint64_t resolve(StubIndex StubIdx) = 0;
87
88 private:
89 FuncNameList FuncNames;
90 };
91
92 // Implementation class for JITResolveCallbackHandler.
93 template
94 class JITResolveCallbackHandlerImpl : public JITResolveCallbackHandler {
95 public:
96 JITResolveCallbackHandlerImpl(LookupFtor Lookup, UpdateFtor Update)
97 : Lookup(std::move(Lookup)), Update(std::move(Update)) {}
98
99 uint64_t resolve(StubIndex StubIdx) override {
100 const std::string &FuncName = getFuncName(StubIdx);
101 uint64_t Addr = Lookup(FuncName);
102 Update(FuncName, Addr);
103 return Addr;
104 }
105
106 private:
107 LookupFtor Lookup;
108 UpdateFtor Update;
109 };
110
111 template
112 std::unique_ptr
113 JITResolveCallbackHandler::create(LookupFtor Lookup, UpdateFtor Update) {
114 typedef JITResolveCallbackHandlerImpl Impl;
115 return make_unique(std::move(Lookup), std::move(Update));
116 }
117
118 /// @brief Holds a list of the function names that were indirected, plus
119 /// mappings from each of these names to (a) the name of function
120 /// providing the implementation for that name (GetImplNames), and
121 /// (b) the name of the global variable holding the address of the
122 /// implementation.
123 ///
124 /// This data structure can be used with a JITCallbackHandler to look up and
125 /// update function implementations when lazily compiling.
126 class JITIndirections {
127 public:
128 JITIndirections(std::vector IndirectedNames,
129 std::function GetImplName,
130 std::function GetAddrName)
131 : IndirectedNames(std::move(IndirectedNames)),
132 GetImplName(std::move(GetImplName)),
133 GetAddrName(std::move(GetAddrName)) {}
134
135 std::vector IndirectedNames;
136 std::function GetImplName;
137 std::function GetAddrName;
138 };
139
140 /// @brief Indirect all calls to functions matching the predicate
141 /// ShouldIndirect through a global variable containing the address
142 /// of the implementation.
143 ///
144 /// @return An indirection structure containing the functions that had their
145 /// call-sites re-written.
146 ///
147 /// For each function 'F' that meets the ShouldIndirect predicate, and that
148 /// is called in this Module, add a common-linkage global variable to the
149 /// module that will hold the address of the implementation of that function.
150 /// Rewrite all call-sites of 'F' to be indirect calls (via the global).
151 /// This allows clients, either directly or via a JITCallbackHandler, to
152 /// change the address of the implementation of 'F' at runtime.
153 ///
154 /// Important notes:
155 ///
156 /// Single indirection does not preserve pointer equality for 'F'. If the
157 /// program was already calling 'F' indirectly through function pointers, or
158 /// if it was taking the address of 'F' for the purpose of pointer comparisons
159 /// or arithmetic double indirection should be used instead.
160 ///
161 /// This method does *not* initialize the function implementation addresses.
162 /// The client must do this prior to running any call-sites that have been
163 /// indirected.
164 JITIndirections makeCallsSingleIndirect(
165 llvm::Module &M,
166 const std::function &ShouldIndirect,
167 const char *JITImplSuffix, const char *JITAddrSuffix);
168
169 /// @brief Replace the body of functions matching the predicate ShouldIndirect
170 /// with indirect calls to the implementation.
171 ///
172 /// @return An indirections structure containing the functions that had their
173 /// implementations re-written.
174 ///
175 /// For each function 'F' that meets the ShouldIndirect predicate, add a
176 /// common-linkage global variable to the module that will hold the address of
177 /// the implementation of that function and rewrite the implementation of 'F'
178 /// to call through to the implementation indirectly (via the global).
179 /// This allows clients, either directly or via a JITCallbackHandler, to
180 /// change the address of the implementation of 'F' at runtime.
181 ///
182 /// Important notes:
183 ///
184 /// Double indirection is slower than single indirection, but preserves
185 /// function pointer relation tests and correct behavior for function pointers
186 /// (all calls to 'F', direct or indirect) go the address stored in the global
187 /// variable at the time of the call.
188 ///
189 /// This method does *not* initialize the function implementation addresses.
190 /// The client must do this prior to running any call-sites that have been
191 /// indirected.
192 JITIndirections makeCallsDoubleIndirect(
193 llvm::Module &M,
194 const std::function &ShouldIndirect,
195 const char *JITImplSuffix, const char *JITAddrSuffix);
196
197 /// @brief Given a set of indirections and a symbol lookup functor, create a
198 /// JITResolveCallbackHandler instance that will resolve the
199 /// implementations for the indirected symbols on demand.
200 template
201 std::unique_ptr
202 createCallbackHandlerFromJITIndirections(const JITIndirections &Indirs,
203 const PersistentMangler &NM,
204 SymbolLookupFtor Lookup) {
205 auto GetImplName = Indirs.GetImplName;
206 auto GetAddrName = Indirs.GetAddrName;
207
208 std::unique_ptr J =
209 JITResolveCallbackHandler::create(
210 [=](const std::string &S) {
211 return Lookup(NM.getMangledName(GetImplName(S)));
212 },
213 [=](const std::string &S, uint64_t Addr) {
214 void *ImplPtr = reinterpret_cast(
215 Lookup(NM.getMangledName(GetAddrName(S))));
216 memcpy(ImplPtr, &Addr, sizeof(uint64_t));
217 });
218
219 for (const auto &FuncName : Indirs.IndirectedNames)
220 J->addFuncName(FuncName);
221
222 return J;
223 }
224
225 /// @brief Insert callback asm into module M for the symbols managed by
226 /// JITResolveCallbackHandler J.
227 void insertX86CallbackAsm(Module &M, JITResolveCallbackHandler &J);
228
229 /// @brief Initialize global indirects to point into the callback asm.
230 template
231 void initializeFuncAddrs(JITResolveCallbackHandler &J,
232 const JITIndirections &Indirs,
233 const PersistentMangler &NM, LookupFtor Lookup) {
234 // Forward declare so that we can access this, even though it's an
235 // implementation detail.
236 std::string getJITResolveCallbackIndexLabel(unsigned I);
237
238 if (J.getNumFuncs() == 0)
239 return;
240
241 // Force a look up one of the global addresses for a function that has been
242 // indirected. We need to do this to trigger the emission of the module
243 // holding the callback asm. We can't rely on that emission happening
244 // automatically when we look up the callback asm symbols, since lazy-emitting
245 // layers can't see those.
246 Lookup(NM.getMangledName(Indirs.GetAddrName(J.getFuncName(0))));
247
248 // Now update indirects to point to the JIT resolve callback asm.
249 for (JITResolveCallbackHandler::StubIndex I = 0; I < J.getNumFuncs(); ++I) {
250 uint64_t ResolveCallbackIdxAddr =
251 Lookup(getJITResolveCallbackIndexLabel(I));
252 void *AddrPtr = reinterpret_cast(
253 Lookup(NM.getMangledName(Indirs.GetAddrName(J.getFuncName(I)))));
254 assert(AddrPtr && "Can't find stub addr global to initialize.");
255 memcpy(AddrPtr, &ResolveCallbackIdxAddr, sizeof(uint64_t));
256 }
257 }
258
259 /// @brief Extract all functions matching the predicate ShouldExtract in to
260 /// their own modules. (Does not modify the original module.)
261 ///
262 /// @return A set of modules, the first containing all symbols (including
263 /// globals and aliases) that did not pass ShouldExtract, and each
264 /// subsequent module containing one of the functions that did meet
265 /// ShouldExtract.
266 ///
267 /// By adding the resulting modules separately (not as a set) to a
268 /// LazyEmittingLayer instance, compilation can be deferred until symbols are
269 /// actually needed.
270 std::vector>
271 explode(const llvm::Module &OrigMod,
272 const std::function &ShouldExtract);
273
274 /// @brief Given a module that has been indirectified, break each function
275 /// that has been indirected out into its own module. (Does not modify
276 /// the original module).
277 ///
278 /// @returns A set of modules covering the symbols provided by OrigMod.
279 std::vector>
280 explode(const llvm::Module &OrigMod, const JITIndirections &Indirections);
281 }
282
283 #endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
0 //===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains the definition for a lazy-emitting layer for the JIT.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
15
16 #include "LookasideRTDyldMM.h"
17 #include "llvm/IR/Mangler.h"
18 #include
19
20 namespace llvm {
21
22 /// @brief Lazy-emitting IR layer.
23 ///
24 /// This layer accepts sets of LLVM IR Modules (via addModuleSet), but does
25 /// not immediately emit them the layer below. Instead, emissing to the base
26 /// layer is deferred until some symbol in the module set is requested via
27 /// getSymbolAddress.
28 template class LazyEmittingLayer {
29 public:
30 typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
31
32 private:
33 class EmissionDeferredSet {
34 public:
35 EmissionDeferredSet() : EmitState(NotEmitted) {}
36 virtual ~EmissionDeferredSet() {}
37
38 uint64_t Search(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
39 switch (EmitState) {
40 case NotEmitted:
41 if (Provides(Name, ExportedSymbolsOnly)) {
42 EmitState = Emitting;
43 Handle = Emit(B);
44 EmitState = Emitted;
45 } else
46 return 0;
47 break;
48 case Emitting:
49 // The module has been added to the base layer but we haven't gotten a
50 // handle back yet so we can't use lookupSymbolAddressIn. Just return
51 // '0' here - LazyEmittingLayer::getSymbolAddress will do a global
52 // search in the base layer when it doesn't find the symbol here, so
53 // we'll find it in the end.
54 return 0;
55 case Emitted:
56 // Nothing to do. Go ahead and search the base layer.
57 break;
58 }
59
60 return B.lookupSymbolAddressIn(Handle, Name, ExportedSymbolsOnly);
61 }
62
63 void RemoveModulesFromBaseLayer(BaseLayerT &BaseLayer) {
64 if (EmitState != NotEmitted)
65 BaseLayer.removeModuleSet(Handle);
66 }
67
68 template
69 static std::unique_ptr
70 create(BaseLayerT &B, ModuleSetT Ms,
71 std::unique_ptr MM);
72
73 protected:
74 virtual bool Provides(StringRef Name, bool ExportedSymbolsOnly) const = 0;
75 virtual BaseLayerHandleT Emit(BaseLayerT &BaseLayer) = 0;
76
77 private:
78 enum { NotEmitted, Emitting, Emitted } EmitState;
79 BaseLayerHandleT Handle;
80 };
81
82 template
83 class EmissionDeferredSetImpl : public EmissionDeferredSet {
84 public:
85 EmissionDeferredSetImpl(ModuleSetT Ms,
86 std::unique_ptr MM)
87 : Ms(std::move(Ms)), MM(std::move(MM)) {}
88
89 protected:
90 BaseLayerHandleT Emit(BaseLayerT &BaseLayer) override {
91 // We don't need the mangled names set any more: Once we've emitted this
92 // to the base layer we'll just look for symbols there.
93 MangledNames.reset();
94 return BaseLayer.addModuleSet(std::move(Ms), std::move(MM));
95 }
96
97 bool Provides(StringRef Name, bool ExportedSymbolsOnly) const override {
98 // FIXME: We could clean all this up if we had a way to reliably demangle
99 // names: We could just demangle name and search, rather than
100 // mangling everything else.
101
102 // If we have already built the mangled name set then just search it.
103 if (MangledNames) {
104 auto VI = MangledNames->find(Name);
105 if (VI == MangledNames->end())
106 return false;
107 return !ExportedSymbolsOnly || VI->second;
108 }
109
110 // If we haven't built the mangled name set yet, try to build it. As an
111 // optimization this will leave MangledNames set to nullptr if we find
112 // Name in the process of building the set.
113 buildMangledNames(Name, ExportedSymbolsOnly);
114 if (!MangledNames)
115 return true;
116 return false;
117 }
118
119 private:
120 // If the mangled name of the given GlobalValue matches the given search
121 // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
122 // just return 'true'. Otherwise, add the mangled name to the Names map and
123 // return 'false'.
124 bool addGlobalValue(StringMap &Names, const GlobalValue &GV,
125 const Mangler &Mang, StringRef SearchName,
126 bool ExportedSymbolsOnly) const {
127 // Modules don't "provide" decls or common symbols.
128 if (GV.isDeclaration() || GV.hasCommonLinkage())
129 return false;
130
131 // Mangle the GV name.
132 std::string MangledName;
133 {
134 raw_string_ostream MangledNameStream(MangledName);
135 Mang.getNameWithPrefix(MangledNameStream, &GV, false);
136 }
137
138 // Check whether this is the name we were searching for, and if it is then
139 // bail out early.
140 if (MangledName == SearchName)
141 if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
142 return true;
143
144 // Otherwise add this to the map for later.
145 Names[MangledName] = GV.hasDefaultVisibility();
146 return false;
147 }
148
149 // Build the MangledNames map. Bails out early (with MangledNames left set
150 // to nullptr) if the given SearchName is found while building the map.
151 void buildMangledNames(StringRef SearchName,
152 bool ExportedSymbolsOnly) const {
153 assert(!MangledNames && "Mangled names map already exists?");
154
155 auto Names = llvm::make_unique>();
156
157 for (const auto &M : Ms) {
158 Mangler Mang(M->getDataLayout());
159
160 for (const auto &GV : M->globals())
161 if (addGlobalValue(*Names, GV, Mang, SearchName, ExportedSymbolsOnly))
162 return;
163
164 for (const auto &F : *M)
165 if (addGlobalValue(*Names, F, Mang, SearchName, ExportedSymbolsOnly))
166 return;
167 }
168
169 MangledNames = std::move(Names);
170 }
171
172 ModuleSetT Ms;
173 std::unique_ptr MM;
174 mutable std::unique_ptr> MangledNames;
175 };
176
177 typedef std::list> ModuleSetListT;
178
179 BaseLayerT &BaseLayer;
180 ModuleSetListT ModuleSetList;
181
182 public:
183 /// @brief Handle to a set of loaded modules.
184 typedef typename ModuleSetListT::iterator ModuleSetHandleT;
185
186 /// @brief Construct a lazy emitting layer.
187 LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
188
189 /// @brief Add the given set of modules to the lazy emitting layer.
190 ///
191 /// This method stores the set of modules in a side table, rather than
192 /// immediately emitting them to the next layer of the JIT. When the address
193 /// of a symbol provided by this set is requested (via getSymbolAddress) it
194 /// triggers the emission of this set to the layer below (along with the given
195 /// memory manager instance), and returns the address of the requested symbol.
196 template
197 ModuleSetHandleT addModuleSet(ModuleSetT Ms,
198 std::unique_ptr MM) {
199 return ModuleSetList.insert(
200 ModuleSetList.end(),
201 EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM)));
202 }
203
204 /// @brief Remove the module set represented by the given handle.
205 ///
206 /// This method will free the memory associated with the given module set,
207 /// both in this layer, and the base layer.
208 void removeModuleSet(ModuleSetHandleT H) {
209 H->RemoveModulesFromBaseLayer();
210 ModuleSetList.erase(H);
211 }
212
213 /// @brief Get the address of a symbol provided by this layer, or some layer
214 /// below this one.
215 ///
216 /// When called for a symbol that has been added to this layer (via
217 /// addModuleSet) but not yet emitted, this will trigger the emission of the
218 /// module set containing the definiton of the symbol.
219 uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
220 // Look up symbol among existing definitions.
221 if (uint64_t Addr = BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly))
222 return Addr;
223
224 // If not found then search the deferred sets. The call to 'Search' will
225 // cause the set to be emitted to the next layer if it provides a definition
226 // of 'Name'.
227 for (auto &DeferredSet : ModuleSetList)
228 if (uint64_t Addr =
229 DeferredSet->Search(Name, ExportedSymbolsOnly, BaseLayer))
230 return Addr;
231
232 // If no definition found anywhere return 0.
233 return 0;
234 }
235
236 /// @brief Get the address of the given symbol in the context of the set of
237 /// compiled modules represented by the handle H. This call is
238 /// forwarded to the base layer's implementation.
239 uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
240 bool ExportedSymbolsOnly) {
241 return (*H)->Search(Name, ExportedSymbolsOnly, BaseLayer);
242 }
243 };
244
245 template
246 template
247 std::unique_ptr::EmissionDeferredSet>
248 LazyEmittingLayer::EmissionDeferredSet::create(
249 BaseLayerT &B, ModuleSetT Ms, std::unique_ptr MM) {
250 return llvm::make_unique>(std::move(Ms),
251 std::move(MM));
252 }
253 }
254
255 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
0 //===- LookasideRTDyldMM - Redirect symbol lookup via a functor -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines an adapter for RuntimeDyldMM that allows lookups for external
10 // symbols to go via a functor.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H
15 #define LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H
16
17 #include
18 #include
19
20 namespace llvm {
21
22 /// @brief Defines an adapter for RuntimeDyldMM that allows lookups for external
23 /// symbols to go via a functor, before falling back to the lookup logic
24 /// provided by the underlying RuntimeDyldMM instance.
25 ///
26 /// This class is useful for redirecting symbol lookup back to various layers
27 /// of a JIT component stack, e.g. to enable lazy module emission.
28 ///
29 template
30 typename DylibLookupFtor>
31 class LookasideRTDyldMM : public BaseRTDyldMM {
32 public:
33 /// @brief Create a LookasideRTDyldMM intance.
34 LookasideRTDyldMM(ExternalLookupFtor ExternalLookup,
35 DylibLookupFtor DylibLookup)
36 : ExternalLookup(std::move(ExternalLookup)),
37 DylibLookup(std::move(DylibLookup)) {}
38
39 /// @brief Look up the given symbol address, first via the functor this
40 /// instance was created with, then (if the symbol isn't found)
41 /// via the underlying RuntimeDyldMM.
42 uint64_t getSymbolAddress(const std::string &Name) override {
43 if (uint64_t Addr = ExternalLookup(Name))
44 return Addr;
45 return BaseRTDyldMM::getSymbolAddress(Name);
46 }
47
48 uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) override {
49 if (uint64_t Addr = DylibLookup(Name))
50 return Addr;
51 return BaseRTDyldMM::getSymbolAddressInLogicalDylib(Name);
52 };
53
54 /// @brief Get a reference to the ExternalLookup functor.
55 ExternalLookupFtor &getExternalLookup() { return ExternalLookup; }
56
57 /// @brief Get a const-reference to the ExternalLookup functor.
58 const ExternalLookupFtor &getExternalLookup() const { return ExternalLookup; }
59
60 /// @brief Get a reference to the DylibLookup functor.
61 DylibLookupFtor &getDylibLookup() { return DylibLookup; }
62
63 /// @brief Get a const-reference to the DylibLookup functor.
64 const DylibLookupFtor &getDylibLookup() const { return DylibLookup; }
65
66 private:
67 ExternalLookupFtor ExternalLookup;
68 DylibLookupFtor DylibLookup;
69 };
70
71 /// @brief Create a LookasideRTDyldMM from a base memory manager type, an
72 /// external lookup functor, and a dylib lookup functor.
73 template
74 typename DylibLookupFtor>
75 std::unique_ptr<
76 LookasideRTDyldMM>
77 createLookasideRTDyldMM(ExternalLookupFtor &&ExternalLookup,
78 DylibLookupFtor &&DylibLookup) {
79 typedef LookasideRTDyldMM
80 ThisLookasideMM;
81 return llvm::make_unique(
82 std::forward(ExternalLookup),
83 std::forward(DylibLookup));
84 }
85 }
86
87 #endif // LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H
0 //===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains the definition for the object layer of the JIT.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
15
16 #include "LookasideRTDyldMM.h"
17 #include "llvm/ExecutionEngine/ExecutionEngine.h"
18 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
19 #include
20 #include
21
22 namespace llvm {
23
24 class ObjectLinkingLayerBase {
25 protected:
26 /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
27 ///
28 /// An instance of this class will be created for each set of objects added
29 /// via JITObjectLayer::addObjectSet. Deleting the instance (via
30 /// removeObjectSet) frees its memory, removing all symbol definitions that
31 /// had been provided by this instance. Higher level layers are responsible
32 /// for taking any action required to handle the missing symbols.
33 class LinkedObjectSet {
34 public:
35 LinkedObjectSet(std::unique_ptr MM)
36 : MM(std::move(MM)), RTDyld(llvm::make_unique(&*this->MM)),
37 State(Raw) {}
38
39 std::unique_ptr
40 addObject(const object::ObjectFile &Obj) {
41 return RTDyld->loadObject(Obj);
42 }
43
44 uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
45 if (ExportedSymbolsOnly)
46 return RTDyld->getExportedSymbolLoadAddress(Name);
47 return RTDyld->getSymbolLoadAddress(Name);
48 }
49
50 bool NeedsFinalization() const { return (State == Raw); }
51
52 void Finalize() {
53 State = Finalizing;
54 RTDyld->resolveRelocations();
55 RTDyld->registerEHFrames();
56 MM->finalizeMemory();
57 State = Finalized;
58 }
59
60 void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) {
61 assert((State != Finalized) &&
62 "Attempting to remap sections for finalized objects.");
63 RTDyld->mapSectionAddress(LocalAddress, TargetAddress);
64 }
65
66 private:
67 std::unique_ptr MM;
68 std::unique_ptr RTDyld;
69 enum { Raw, Finalizing, Finalized } State;
70 };
71
72 typedef std::list LinkedObjectSetListT;
73
74 public:
75 /// @brief Handle to a set of loaded objects.
76 typedef typename LinkedObjectSetListT::iterator ObjSetHandleT;
77 };
78
79 /// @brief Default (no-op) action to perform when loading objects.
80 class DoNothingOnNotifyLoaded {
81 public:
82 template
83 void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
84 const LoadResult &) {}
85 };
86
87 /// @brief Bare bones object linking layer.
88 ///
89 /// This class is intended to be used as the base layer for a JIT. It allows
90 /// object files to be loaded into memory, linked, and the addresses of their
91 /// symbols queried. All objects added to this layer can see each other's
92 /// symbols.
93 template
94 class ObjectLinkingLayer : public ObjectLinkingLayerBase {
95 public:
96 /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
97 /// RuntimeDyld::LoadedObjectInfo instances.
98 typedef std::vector>
99 LoadedObjInfoList;
100
101 /// @brief Default construct an ObjectLinkingLayer.
102 ObjectLinkingLayer() {}
103
104 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded
105 /// functor.
106 ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded)
107 : NotifyLoaded(std::move(NotifyLoaded)) {}
108
109 /// @brief Construct an ObjectLinkingLayer with the given NotifyFinalized
110 /// functor.
111 ObjectLinkingLayer(std::function NotifyFinalized)
112 : NotifyFinalized(std::move(NotifyFinalized)) {}
113
114 /// @brief Construct an ObjectLinkingLayer with the given CreateMemoryManager
115 /// functor.
116 ObjectLinkingLayer(
117 std::function()> CreateMemoryManager)
118 : CreateMemoryManager(std::move(CreateMemoryManager)) {}
119
120 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded and
121 /// NotifyFinalized functors.
122 ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded,
123 std::function NotifyFinalized)
124 : NotifyLoaded(std::move(NotifyLoaded)),
125 NotifyFinalized(std::move(NotifyFinalized)) {}
126
127 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded and
128 /// CreateMemoryManager functors.
129 ObjectLinkingLayer(
130 NotifyLoadedFtor NotifyLoaded,
131 std::function()> CreateMemoryManager)
132 : NotifyLoaded(std::move(NotifyLoaded)),
133 CreateMemoryManager(std::move(CreateMemoryManager)) {}
134
135 /// @brief Construct an ObjectLinkingLayer with the given NotifyFinalized and
136 /// CreateMemoryManager functors.
137 ObjectLinkingLayer(
138 std::function NotifyFinalized,
139 std::function()> CreateMemoryManager)
140 : NotifyFinalized(std::move(NotifyFinalized)),
141 CreateMemoryManager(std::move(CreateMemoryManager)) {}
142
143 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
144 /// NotifyFinalized and CreateMemoryManager functors.
145 ObjectLinkingLayer(
146 NotifyLoadedFtor NotifyLoaded,
147 std::function NotifyFinalized,
148 std::function()> CreateMemoryManager)
149 : NotifyLoaded(std::move(NotifyLoaded)),
150 NotifyFinalized(std::move(NotifyFinalized)),
151 CreateMemoryManager(std::move(CreateMemoryManager)) {}
152
153 /// @brief Add a set of objects (or archives) that will be treated as a unit
154 /// for the purposes of symbol lookup and memory management.
155 ///
156 /// @return A pair containing (1) A handle that can be used to free the memory
157 /// allocated for the objects, and (2) a LoadedObjInfoList containing
158 /// one LoadedObjInfo instance for each object at the corresponding
159 /// index in the Objects list.
160 ///
161 /// This version of this method allows the client to pass in an
162 /// RTDyldMemoryManager instance that will be used to allocate memory and look
163 /// up external symbol addresses for the given objects.
164 template
165 ObjSetHandleT addObjectSet(const ObjSetT &Objects,
166 std::unique_ptr MM) {
167
168 if (!MM) {
169 assert(CreateMemoryManager &&
170 "No memory manager or memory manager creator provided.");
171 MM = CreateMemoryManager();
172 }
173
174 ObjSetHandleT Handle = LinkedObjSetList.insert(
175 LinkedObjSetList.end(), LinkedObjectSet(std::move(MM)));
176 LinkedObjectSet &LOS = *Handle;
177 LoadedObjInfoList LoadedObjInfos;
178
179 for (auto &Obj : Objects)
180 LoadedObjInfos.push_back(LOS.addObject(*Obj));
181
182 NotifyLoaded(Handle, Objects, LoadedObjInfos);
183
184 return Handle;
185 }
186
187 /// @brief Map section addresses for the objects associated with the handle H.
188 void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
189 uint64_t TargetAddress) {
190 H->mapSectionAddress(LocalAddress, TargetAddress);
191 }
192
193 /// @brief Remove the set of objects associated with handle H.
194 ///
195 /// All memory allocated for the objects will be freed, and the sections and
196 /// symbols they provided will no longer be available. No attempt is made to
197 /// re-emit the missing symbols, and any use of these symbols (directly or
198 /// indirectly) will result in undefined behavior. If dependence tracking is
199 /// required to detect or resolve such issues it should be added at a higher
200 /// layer.
201 void removeObjectSet(ObjSetHandleT H) {
202 // How do we invalidate the symbols in H?
203 LinkedObjSetList.erase(H);
204 }
205
206 /// @brief Get the address of a loaded symbol.
207 ///
208 /// @return The address in the target process's address space of the named
209 /// symbol. Null if no such symbol is known.
210 ///
211 /// This method will trigger the finalization of the linked object set
212 /// containing the definition of the given symbol, if it is found.
213 uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
214 for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
215 ++I)
216 if (uint64_t Addr = lookupSymbolAddressIn(I, Name, ExportedSymbolsOnly))
217 return Addr;
218
219 return 0;
220 }
221
222 /// @brief Search for a given symbol in the context of the set of loaded
223 /// objects represented by the handle H.
224 ///
225 /// @return The address in the target process's address space of the named
226 /// symbol. Null if the given object set does not contain a definition
227 /// of this symbol.
228 ///
229 /// This method will trigger the finalization of the linked object set
230 /// represented by the handle H if that set contains the requested symbol.
231 uint64_t lookupSymbolAddressIn(ObjSetHandleT H, StringRef Name,
232 bool ExportedSymbolsOnly) {
233 if (uint64_t Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) {
234 if (H->NeedsFinalization()) {
235 H->Finalize();
236 if (NotifyFinalized)
237 NotifyFinalized(H);
238 }
239 return Addr;
240 }
241 return 0;
242 }
243
244 private:
245 LinkedObjectSetListT LinkedObjSetList;
246 NotifyLoadedFtor NotifyLoaded;
247 std::function NotifyFinalized;
248 std::function()> CreateMemoryManager;
249 };
250
251 } // end namespace llvm
252
253 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
0 //===-- OrcTargetSupport.h - Code to support specific targets --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Target specific code for Orc, e.g. callback assembly.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H
14 #define LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H
15
16 #include "IndirectionUtils.h"
17
18 namespace llvm {
19
20 /// @brief Insert callback asm into module M for the symbols managed by
21 /// JITResolveCallbackHandler J.
22 void insertX86CallbackAsm(Module &M, JITResolveCallbackHandler &J);
23 }
24
25 #endif // LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H
0 //===---- OrcMCJITReplacement.h - Orc-based MCJIT replacement ---*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file forces OrcMCJITReplacement to link in on certain operating systems.
10 // (Windows).
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H
15 #define LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H
16
17 #include "llvm/ExecutionEngine/ExecutionEngine.h"
18 #include
19
20 extern "C" void LLVMLinkInOrcMCJITReplacement();
21
22 namespace {
23 struct ForceOrcMCJITReplacementLinking {
24 ForceOrcMCJITReplacementLinking() {
25 // We must reference OrcMCJITReplacement in such a way that compilers will
26 // not delete it all as dead code, even with whole program optimization,
27 // yet is effectively a NO-OP. As the compiler isn't smart enough to know
28 // that getenv() never returns -1, this will do the job.
29 if (std::getenv("bar") != (char*) -1)
30 return;
31
32 LLVMLinkInOrcMCJITReplacement();
33 }
34 } ForceOrcMCJITReplacementLinking;
35 }
36
37 #endif
8888 return getSymbolAddressInProcess(Name);
8989 }
9090
91 /// This method returns the address of the specified symbol if it exists
92 /// within the logical dynamic library represented by this
93 /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this
94 /// interface should return addresses for hidden symbols.
95 ///
96 /// This is of particular importance for the Orc JIT APIs, which support lazy
97 /// compilation by breaking up modules: Each of those broken out modules
98 /// must be able to resolve hidden symbols provided by the others. Clients
99 /// writing memory managers for MCJIT can usually ignore this method.
100 ///
101 /// This method will be queried by RuntimeDyld when checking for previous
102 /// definitions of common symbols. It will *not* be queried by default when
103 /// resolving external symbols (this minimises the link-time overhead for
104 /// MCJIT clients who don't care about Orc features). If you are writing a
105 /// RTDyldMemoryManager for Orc and want "external" symbol resolution to
106 /// search the logical dylib, you should override your getSymbolAddress
107 /// method call this method directly.
108 virtual uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) {
109 return 0;
110 }
111
91112 /// This method returns the address of the specified function. As such it is
92113 /// only useful for resolving library symbols, not code generated symbols.
93114 ///
99
1010 add_subdirectory(Interpreter)
1111 add_subdirectory(MCJIT)
12 add_subdirectory(Orc)
1213 add_subdirectory(RuntimeDyld)
1314
1415 if( LLVM_USE_OPROFILE )
4545 std::unique_ptr M, std::string *ErrorStr,
4646 std::unique_ptr MCJMM,
4747 std::unique_ptr TM) = nullptr;
48
49 ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)(
50 std::string *ErrorStr, std::unique_ptr OrcJMM,
51 std::unique_ptr TM) = nullptr;
52
4853 ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr M,
4954 std::string *ErrorStr) =nullptr;
5055
392397 return runFunction(Fn, GVArgs).IntVal.getZExtValue();
393398 }
394399
400 EngineBuilder::EngineBuilder() {
401 InitEngine();
402 }
403
395404 EngineBuilder::EngineBuilder(std::unique_ptr M)
396405 : M(std::move(M)), MCJMM(nullptr) {
397406 InitEngine();
413422 Options = TargetOptions();
414423 RelocModel = Reloc::Default;
415424 CMModel = CodeModel::JITDefault;
425 UseOrcMCJITReplacement = false;
416426
417427 // IR module verification is enabled by default in debug builds, and disabled
418428 // by default in release builds.
455465 }
456466
457467 ExecutionEngine *EE = nullptr;
458 if (ExecutionEngine::MCJITCtor)
468 if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) {
469 EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MCJMM),
470 std::move(TheTM));
471 EE->addModule(std::move(M));
472 } else if (ExecutionEngine::MCJITCtor)
459473 EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MCJMM),
460474 std::move(TheTM));
475
461476 if (EE) {
462477 EE->setVerifyModules(VerifyModules);
463478 return EE;
1515 ;===------------------------------------------------------------------------===;
1616
1717 [common]
18 subdirectories = Interpreter MCJIT RuntimeDyld IntelJITEvents OProfileJIT
18 subdirectories = Interpreter MCJIT RuntimeDyld IntelJITEvents OProfileJIT Orc
1919
2020 [component_0]
2121 type = Library
99 #ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H
1010 #define LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H
1111
12 #include "ObjectBuffer.h"
1312 #include "llvm/ADT/DenseMap.h"
1413 #include "llvm/ADT/SmallPtrSet.h"
1514 #include "llvm/ADT/SmallVector.h"
1615 #include "llvm/ExecutionEngine/ExecutionEngine.h"
1716 #include "llvm/ExecutionEngine/ObjectCache.h"
17 #include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
1818 #include "llvm/ExecutionEngine/RuntimeDyld.h"
1919 #include "llvm/IR/Module.h"
2020
1010
1111 include $(LEVEL)/Makefile.config
1212
13 PARALLEL_DIRS = Interpreter MCJIT RuntimeDyld
13 PARALLEL_DIRS = Interpreter MCJIT Orc RuntimeDyld
1414
1515 ifeq ($(USE_INTEL_JITEVENTS), 1)
1616 PARALLEL_DIRS += IntelJITEvents
0 add_llvm_library(LLVMOrcJIT
1 CloneSubModule.cpp
2 IndirectionUtils.cpp
3 OrcMCJITReplacement.cpp
4 OrcTargetSupport.cpp
5 )
0 #include "llvm/ExecutionEngine/Orc/CloneSubModule.h"
1 #include "llvm/IR/Function.h"
2 #include "llvm/IR/GlobalVariable.h"
3 #include "llvm/IR/Module.h"
4 #include "llvm/Transforms/Utils/Cloning.h"
5
6 using namespace llvm;
7
8 void llvm::copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig,
9 ValueToValueMapTy &VMap) {
10 if (Orig.hasInitializer())
11 New.setInitializer(MapValue(Orig.getInitializer(), VMap));
12 }
13
14 void llvm::copyFunctionBody(Function &New, const Function &Orig,
15 ValueToValueMapTy &VMap) {
16 if (!Orig.isDeclaration()) {
17 Function::arg_iterator DestI = New.arg_begin();
18 for (Function::const_arg_iterator J = Orig.arg_begin(); J != Orig.arg_end();
19 ++J) {
20 DestI->setName(J->getName());
21 VMap[J] = DestI++;
22 }
23
24 SmallVector Returns; // Ignore returns cloned.
25 CloneFunctionInto(&New, &Orig, VMap, /*ModuleLevelChanges=*/true, Returns);
26 }
27 }
28
29 std::unique_ptr
30 llvm::CloneSubModule(const Module &M,
31 HandleGlobalVariableFtor HandleGlobalVariable,
32 HandleFunctionFtor HandleFunction, bool KeepInlineAsm) {
33
34 ValueToValueMapTy VMap;
35
36 // First off, we need to create the new module.
37 std::unique_ptr New =
38 llvm::make_unique(M.getModuleIdentifier(), M.getContext());
39
40 New->setDataLayout(M.getDataLayout());
41 New->setTargetTriple(M.getTargetTriple());
42 if (KeepInlineAsm)
43 New->setModuleInlineAsm(M.getModuleInlineAsm());
44
45 // Copy global variables (but not initializers, yet).
46 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
47 I != E; ++I) {
48 GlobalVariable *GV = new GlobalVariable(
49 *New, I->getType()->getElementType(), I->isConstant(), I->getLinkage(),
50 (Constant *)nullptr, I->getName(), (GlobalVariable *)nullptr,
51 I->getThreadLocalMode(), I->getType()->getAddressSpace());
52 GV->copyAttributesFrom(I);
53 VMap[I] = GV;
54 }
55
56 // Loop over the functions in the module, making external functions as before
57 for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
58 Function *NF =
59 Function::Create(cast(I->getType()->getElementType()),
60 I->getLinkage(), I->getName(), &*New);
61 NF->copyAttributesFrom(I);
62 VMap[I] = NF;
63 }
64
65 // Loop over the aliases in the module
66 for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
67 I != E; ++I) {
68 auto *PTy = cast(I->getType());
69 auto *GA =
70 GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
71 I->getLinkage(), I->getName(), &*New);
72 GA->copyAttributesFrom(I);
73 VMap[I] = GA;
74 }
75
76 // Now that all of the things that global variable initializer can refer to
77 // have been created, loop through and copy the global variable referrers
78 // over... We also set the attributes on the global now.
79 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
80 I != E; ++I) {
81 GlobalVariable &GV = *cast(VMap[I]);
82 HandleGlobalVariable(GV, *I, VMap);
83 }
84
85 // Similarly, copy over function bodies now...
86 //
87 for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
88 Function &F = *cast(VMap[I]);
89 HandleFunction(F, *I, VMap);
90 }
91
92 // And aliases
93 for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
94 I != E; ++I) {
95 GlobalAlias *GA = cast(VMap[I]);
96 if (const Constant *C = I->getAliasee())
97 GA->setAliasee(MapValue(C, VMap));
98 }
99
100 // And named metadata....
101 for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
102 E = M.named_metadata_end();
103 I != E; ++I) {
104 const NamedMDNode &NMD = *I;
105 NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName());
106 for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
107 NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap));
108 }
109
110 return New;
111 }
0 #include "llvm/ADT/Triple.h"
1 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
2 #include "llvm/ExecutionEngine/Orc/CloneSubModule.h"
3 #include "llvm/IR/CallSite.h"
4 #include "llvm/IR/IRBuilder.h"
5 #include
6
7 using namespace llvm;
8
9 namespace llvm {
10
11 JITIndirections makeCallsSingleIndirect(
12 Module &M, const std::function &ShouldIndirect,
13 const char *JITImplSuffix, const char *JITAddrSuffix) {
14 std::vector Worklist;
15 std::vector FuncNames;
16
17 for (auto &F : M)
18 if (ShouldIndirect(F) && (F.user_begin() != F.user_end())) {
19 Worklist.push_back(&F);
20 FuncNames.push_back(F.getName());
21 }
22
23 for (auto *F : Worklist) {
24 GlobalVariable *FImplAddr = new GlobalVariable(
25 M, F->getType(), false, GlobalValue::ExternalLinkage,
26 Constant::getNullValue(F->getType()), F->getName() + JITAddrSuffix,
27 nullptr, GlobalValue::NotThreadLocal, 0, true);
28 FImplAddr->setVisibility(GlobalValue::HiddenVisibility);
29
30 for (auto *U : F->users()) {
31 assert(isa(U) && "Cannot indirect non-instruction use");
32 IRBuilder<> Builder(cast(U));
33 U->replaceUsesOfWith(F, Builder.CreateLoad(FImplAddr));
34 }
35 }
36
37 return JITIndirections(
38 FuncNames, [=](StringRef S) -> std::string { return std::string(S); },
39 [=](StringRef S)
40 -> std::string { return std::string(S) + JITAddrSuffix; });
41 }
42
43 JITIndirections makeCallsDoubleIndirect(
44 Module &M, const std::function &ShouldIndirect,
45 const char *JITImplSuffix, const char *JITAddrSuffix) {
46
47 std::vector Worklist;
48 std::vector FuncNames;
49
50 for (auto &F : M)
51 if (!F.isDeclaration() && !F.hasAvailableExternallyLinkage() &&
52 ShouldIndirect(F))
53 Worklist.push_back(&F);
54
55 for (auto *F : Worklist) {
56 std::string OrigName = F->getName();
57 F->setName(OrigName + JITImplSuffix);
58 FuncNames.push_back(OrigName);
59
60 GlobalVariable *FImplAddr = new GlobalVariable(
61 M, F->getType(), false, GlobalValue::ExternalLinkage,
62 Constant::getNullValue(F->getType()), OrigName + JITAddrSuffix, nullptr,
63 GlobalValue::NotThreadLocal, 0, true);
64 FImplAddr->setVisibility(GlobalValue::HiddenVisibility);
65
66 Function *FRedirect =
67 Function::Create(F->getFunctionType(), F->getLinkage(), OrigName, &M);
68
69 F->replaceAllUsesWith(FRedirect);
70
71 BasicBlock *EntryBlock =
72 BasicBlock::Create(M.getContext(), "entry", FRedirect);
73
74 IRBuilder<> Builder(EntryBlock);
75 LoadInst *FImplLoadedAddr = Builder.CreateLoad(FImplAddr);
76
77 std::vector CallArgs;
78 for (Value &Arg : FRedirect->args())
79 CallArgs.push_back(&Arg);
80 CallInst *Call = Builder.CreateCall(FImplLoadedAddr, CallArgs);
81 Call->setTailCall();
82 Builder.CreateRet(Call);
83 }
84
85 return JITIndirections(
86 FuncNames, [=](StringRef S)
87 -> std::string { return std::string(S) + JITImplSuffix; },
88 [=](StringRef S)
89 -> std::string { return std::string(S) + JITAddrSuffix; });
90 }
91
92 std::vector>
93 explode(const Module &OrigMod,
94 const std::function &ShouldExtract) {
95
96 std::vector> NewModules;
97
98 // Split all the globals, non-indirected functions, etc. into a single module.
99 auto ExtractGlobalVars = [&](GlobalVariable &New, const GlobalVariable &Orig,
100 ValueToValueMapTy &VMap) {
101 copyGVInitializer(New, Orig, VMap);
102 if (New.getLinkage() == GlobalValue::PrivateLinkage) {
103 New.setLinkage(GlobalValue::ExternalLinkage);
104 New.setVisibility(GlobalValue::HiddenVisibility);
105 }
106 };
107
108 auto ExtractNonImplFunctions =
109 [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
110 if (!ShouldExtract(New))
111 copyFunctionBody(New, Orig, VMap);
112 };
113
114 NewModules.push_back(CloneSubModule(OrigMod, ExtractGlobalVars,
115 ExtractNonImplFunctions, true));
116
117 // Preserve initializers for Common linkage vars, and make private linkage
118 // globals external: they are now provided by the globals module extracted
119 // above.
120 auto DropGlobalVars = [&](GlobalVariable &New, const GlobalVariable &Orig,
121 ValueToValueMapTy &VMap) {
122 if (New.getLinkage() == GlobalValue::CommonLinkage)
123 copyGVInitializer(New, Orig, VMap);
124 else if (New.getLinkage() == GlobalValue::PrivateLinkage)
125 New.setLinkage(GlobalValue::ExternalLinkage);
126 };
127
128 // Split each 'impl' function out in to its own module.
129 for (const auto &Func : OrigMod) {
130 if (Func.isDeclaration() || !ShouldExtract(Func))
131 continue;
132
133 auto ExtractNamedFunction =
134 [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
135 if (New.getName() == Func.getName())
136 copyFunctionBody(New, Orig, VMap);
137 };
138
139 NewModules.push_back(
140 CloneSubModule(OrigMod, DropGlobalVars, ExtractNamedFunction, false));
141 }
142
143 return NewModules;
144 }
145
146 std::vector>
147 explode(const Module &OrigMod, const JITIndirections &Indirections) {
148 std::set ImplNames;
149
150 for (const auto &FuncName : Indirections.IndirectedNames)
151 ImplNames.insert(Indirections.GetImplName(FuncName));
152
153 return explode(
154 OrigMod, [&](const Function &F) { return ImplNames.count(F.getName()); });
155 }
156 }
0 ;===- ./lib/ExecutionEngine/MCJIT/LLVMBuild.txt ----------------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [component_0]
18 type = Library
19 name = OrcJIT
20 parent = ExecutionEngine
21 required_libraries = Core ExecutionEngine Object RuntimeDyld Support Target
0 ##===- lib/ExecutionEngine/OrcJIT/Makefile -----------------*- Makefile -*-===##
1 #
2 # The LLVM Compiler Infrastructure
3 #
4 # This file is distributed under the University of Illinois Open Source
5 # License. See LICENSE.TXT for details.
6 #
7 ##===----------------------------------------------------------------------===##
8
9 LEVEL = ../../..
10 LIBRARYNAME = LLVMOrcJIT
11
12 include $(LEVEL)/Makefile.common
0 //===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "OrcMCJITReplacement.h"
10 #include "llvm/ExecutionEngine/GenericValue.h"
11
12 namespace {
13
14 static struct RegisterJIT {
15 RegisterJIT() { llvm::OrcMCJITReplacement::Register(); }
16 } JITRegistrator;
17
18 extern "C" void LLVMLinkInOrcMCJITReplacement() {}
19 }
20
21 namespace llvm {
22
23 GenericValue
24 OrcMCJITReplacement::runFunction(Function *F,
25 const std::vector &ArgValues) {
26 assert(F && "Function *F was null at entry to run()");
27
28 void *FPtr = getPointerToFunction(F);
29 assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
30 FunctionType *FTy = F->getFunctionType();
31 Type *RetTy = FTy->getReturnType();
32
33 assert((FTy->getNumParams() == ArgValues.size() ||
34 (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
35 "Wrong number of arguments passed into function!");
36 assert(FTy->getNumParams() == ArgValues.size() &&
37 "This doesn't support passing arguments through varargs (yet)!");
38
39 // Handle some common cases first. These cases correspond to common `main'
40 // prototypes.
41 if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
42 switch (ArgValues.size()) {
43 case 3:
44 if (FTy->getParamType(0)->isIntegerTy(32) &&
45 FTy->getParamType(1)->isPointerTy() &&
46 FTy->getParamType(2)->isPointerTy()) {
47 int (*PF)(int, char **, const char **) =
48 (int (*)(int, char **, const char **))(intptr_t)FPtr;
49
50 // Call the function.
51 GenericValue rv;
52 rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
53 (char **)GVTOP(ArgValues[1]),
54 (const char **)GVTOP(ArgValues[2])));
55 return rv;
56 }
57 break;
58 case 2:
59 if (FTy->getParamType(0)->isIntegerTy(32) &&
60 FTy->getParamType(1)->isPointerTy()) {
61 int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr;
62
63 // Call the function.
64 GenericValue rv;
65 rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
66 (char **)GVTOP(ArgValues[1])));
67 return rv;
68 }
69 break;
70 case 1:
71 if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) {
72 GenericValue rv;
73 int (*PF)(int) = (int (*)(int))(intptr_t)FPtr;
74 rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
75 return rv;
76 }
77 break;
78 }
79 }
80
81 // Handle cases where no arguments are passed first.
82 if (ArgValues.empty()) {
83 GenericValue rv;
84 switch (RetTy->getTypeID()) {
85 default:
86 llvm_unreachable("Unknown return type for function call!");
87 case Type::IntegerTyID: {
88 unsigned BitWidth = cast(RetTy)->getBitWidth();
89 if (BitWidth == 1)
90 rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)());
91 else if (BitWidth <= 8)
92 rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)());
93 else if (BitWidth <= 16)
94 rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)());
95 else if (BitWidth <= 32)
96 rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)());
97 else if (BitWidth <= 64)
98 rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)());
99 else
100 llvm_unreachable("Integer types > 64 bits not supported");
101 return rv;
102 }
103 case Type::VoidTyID:
104 rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)());
105 return rv;
106 case Type::FloatTyID:
107 rv.FloatVal = ((float (*)())(intptr_t)FPtr)();
108 return rv;
109 case Type::DoubleTyID:
110 rv.DoubleVal = ((double (*)())(intptr_t)FPtr)();
111 return rv;
112 case Type::X86_FP80TyID:
113 case Type::FP128TyID:
114 case Type::PPC_FP128TyID:
115 llvm_unreachable("long double not supported yet");
116 case Type::PointerTyID:
117 return PTOGV(((void *(*)())(intptr_t)FPtr)());
118 }
119 }
120
121 llvm_unreachable("Full-featured argument passing not supported yet!");
122 }
123 }
0 //===---- OrcMCJITReplacement.h - Orc based MCJIT replacement ---*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Orc based MCJIT replacement.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
14 #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
15
16 #include "llvm/ExecutionEngine/ExecutionEngine.h"
17 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
18 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
19 #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
20 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
21 #include "llvm/Object/Archive.h"
22 #include "llvm/Target/TargetSubtargetInfo.h"
23
24 namespace llvm {
25
26 class OrcMCJITReplacement : public ExecutionEngine {
27
28 class ForwardingRTDyldMM : public RTDyldMemoryManager {
29 public:
30 ForwardingRTDyldMM(OrcMCJITReplacement &M) : M(M) {}
31
32 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
33 unsigned SectionID,
34 StringRef SectionName) override {
35 uint8_t *Addr =
36 M.MM->allocateCodeSection(Size, Alignment, SectionID, SectionName);
37 M.SectionsAllocatedSinceLastLoad.insert(Addr);
38 return Addr;
39 }
40
41 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
42 unsigned SectionID, StringRef SectionName,
43 bool IsReadOnly) override {
44 uint8_t *Addr = M.MM->allocateDataSection(Size, Alignment, SectionID,
45 SectionName, IsReadOnly);
46 M.SectionsAllocatedSinceLastLoad.insert(Addr);
47 return Addr;
48 }
49
50 void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO,
51 uintptr_t DataSizeRW) override {
52 return M.MM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
53 }
54
55 bool needsToReserveAllocationSpace() override {
56 return M.MM->needsToReserveAllocationSpace();
57 }
58
59 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
60 size_t Size) override {
61 return M.MM->registerEHFrames(Addr, LoadAddr, Size);
62 }
63
64 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
65 size_t Size) override {
66 return M.MM->deregisterEHFrames(Addr, LoadAddr, Size);
67 }
68
69 uint64_t getSymbolAddress(const std::string &Name) override {
70 return M.getSymbolAddressWithoutMangling(Name);
71 }
72
73 void *getPointerToNamedFunction(const std::string &Name,
74 bool AbortOnFailure = true) override {
75 return M.MM->getPointerToNamedFunction(Name, AbortOnFailure);
76 }
77
78 void notifyObjectLoaded(ExecutionEngine *EE,
79 const object::ObjectFile &O) override {
80 return M.MM->notifyObjectLoaded(EE, O);
81 }
82
83 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
84 // Each set of objects loaded will be finalized exactly once, but since
85 // symbol lookup during relocation may recursively trigger the
86 // loading/relocation of other modules, and since we're forwarding all
87 // finalizeMemory calls to a single underlying memory manager, we need to
88 // defer forwarding the call on until all necessary objects have been
89 // loaded. Otherwise, during the relocation of a leaf object, we will end
90 // up finalizing memory, causing a crash further up the stack when we
91 // attempt to apply relocations to finalized memory.
92 // To avoid finalizing too early, look at how many objects have been
93 // loaded but not yet finalized. This is a bit of a hack that relies on
94 // the fact that we're lazily emitting object files: The only way you can
95 // get more than one set of objects loaded but not yet finalized is if
96 // they were loaded during relocation of another set.
97 if (M.UnfinalizedSections.size() == 1)
98 return M.MM->finalizeMemory(ErrMsg);
99 return false;
100 }
101
102 private:
103 OrcMCJITReplacement &M;
104 };
105
106 private:
107 static ExecutionEngine *
108 createOrcMCJITReplacement(std::string *ErrorMsg,
109 std::unique_ptr OrcJMM,
110 std::unique_ptr TM) {
111 return new llvm::OrcMCJITReplacement(std::move(OrcJMM), std::move(TM));
112 }
113
114 public:
115 static void Register() {
116 OrcMCJITReplacementCtor = createOrcMCJITReplacement;
117 }
118
119 OrcMCJITReplacement(std::unique_ptr MM,
120 std::unique_ptr TM)
121 : TM(std::move(TM)), MM(std::move(MM)),
122 Mang(this->TM->getSubtargetImpl()->getDataLayout()),
123 NotifyObjectLoaded(*this), NotifyFinalized(*this),
124 ObjectLayer(NotifyObjectLoaded, NotifyFinalized),
125 CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
126 LazyEmitLayer(CompileLayer) {
127 setDataLayout(this->TM->getSubtargetImpl()->getDataLayout());
128 }
129
130 void addModule(std::unique_ptr M) {
131
132 // If this module doesn't have a DataLayout attached then attach the
133 // default.
134 if (!M->getDataLayout())
135 M->setDataLayout(getDataLayout());
136
137 OwnedModules.push_back(std::move(M));
138 std::vector Ms;
139 Ms.push_back(&*OwnedModules.back());
140 LazyEmitLayer.addModuleSet(std::move(Ms),
141 llvm::make_unique(*this));
142 }
143
144 void addObjectFile(std::unique_ptr O) override {
145 std::vector> Objs;
146 Objs.push_back(std::move(O));
147 ObjectLayer.addObjectSet(std::move(Objs),
148 llvm::make_unique(*this));
149 }
150
151 void addObjectFile(object::OwningBinary O) override {
152 std::unique_ptr Obj;
153 std::unique_ptr Buf;
154 std::tie(Obj, Buf) = O.takeBinary();
155 std::vector> Objs;
156 Objs.push_back(std::move(Obj));
157 ObjectLayer.addObjectSet(std::move(Objs),
158 llvm::make_unique(*this));
159 }
160
161 void addArchive(object::OwningBinary A) override {
162 Archives.push_back(std::move(A));
163 }
164
165 uint64_t getSymbolAddress(StringRef Name) {
166 return getSymbolAddressWithoutMangling(Mangle(Name));
167 }
168
169 void finalizeObject() override {
170 // This is deprecated - Aim to remove in ExecutionEngine.
171 // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
172 }
173
174 void mapSectionAddress(const void *LocalAddress,
175 uint64_t TargetAddress) override {
176 for (auto &P : UnfinalizedSections)
177 if (P.second.count(LocalAddress))
178 ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
179 }
180
181 uint64_t getGlobalValueAddress(const std::string &Name) override {
182 return getSymbolAddress(Name);
183 }
184
185 uint64_t getFunctionAddress(const std::string &Name) override {
186 return getSymbolAddress(Name);
187 }
188
189 void *getPointerToFunction(Function *F) override {
190 uint64_t FAddr = getSymbolAddress(F->getName());
191 return reinterpret_cast(static_cast(FAddr));
192 }
193
194 void *getPointerToNamedFunction(StringRef Name,
195 bool AbortOnFailure = true) override {
196 uint64_t Addr = getSymbolAddress(Name);
197 if (!Addr && AbortOnFailure)
198 llvm_unreachable("Missing symbol!");
199 return reinterpret_cast(static_cast(Addr));
200 }
201
202 GenericValue runFunction(Function *F,
203 const std::vector &ArgValues) override;
204
205 void setObjectCache(ObjectCache *NewCache) override {
206 CompileLayer.setObjectCache(NewCache);
207 }
208
209 private:
210 uint64_t getSymbolAddressWithoutMangling(StringRef Name) {
211 if (uint64_t Addr = LazyEmitLayer.getSymbolAddress(Name, false))
212 return Addr;
213 if (uint64_t Addr = MM->getSymbolAddress(Name))
214 return Addr;
215 if (uint64_t Addr = scanArchives(Name))
216 return Addr;
217
218 return 0;
219 }
220
221 uint64_t scanArchives(StringRef Name) {
222 for (object::OwningBinary &OB : Archives) {
223 object::Archive *A = OB.getBinary();
224 // Look for our symbols in each Archive
225 object::Archive::child_iterator ChildIt = A->findSym(Name);
226 if (ChildIt != A->child_end()) {
227 // FIXME: Support nested archives?
228 ErrorOr> ChildBinOrErr =
229 ChildIt->getAsBinary();
230 if (ChildBinOrErr.getError())
231 continue;
232 std::unique_ptr &ChildBin = ChildBinOrErr.get();
233 if (ChildBin->isObject()) {
234 std::vector> ObjSet;
235 ObjSet.push_back(std::unique_ptr(
236 static_cast(ChildBin.release())));
237 ObjectLayer.addObjectSet(
238 std::move(ObjSet), llvm::make_unique(*this));
239 if (uint64_t Addr = ObjectLayer.getSymbolAddress(Name, true))
240 return Addr;
241 }
242 }
243 }
244 return 0;
245 }
246
247 class NotifyObjectLoadedT {
248 public:
249 typedef std::vector> ObjListT;
250 typedef std::vector>
251 LoadedObjInfoListT;
252
253 NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
254
255 void operator()(ObjectLinkingLayerBase::ObjSetHandleT H,
256 const ObjListT &Objects,
257 const LoadedObjInfoListT &Infos) const {
258 M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
259 M.SectionsAllocatedSinceLastLoad = {};
260 assert(Objects.size() == Infos.size() &&
261 "Incorrect number of Infos for Objects.");
262 for (unsigned I = 0; I < Objects.size(); ++I)
263 M.MM->notifyObjectLoaded(&M, *Objects[I]);
264 };
265
266 private:
267 OrcMCJITReplacement &M;
268 };
269
270 class NotifyFinalizedT {
271 public:
272 NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
273 void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) {
274 M.UnfinalizedSections.erase(H);
275 }
276
277 private:
278 OrcMCJITReplacement &M;
279 };
280
281 std::string Mangle(StringRef Name) {
282 std::string MangledName;
283 {
284 raw_string_ostream MangledNameStream(MangledName);
285 Mang.getNameWithPrefix(MangledNameStream, Name);
286 }
287 return MangledName;
288 }
289
290 typedef ObjectLinkingLayer ObjectLayerT;
291 typedef IRCompileLayer CompileLayerT;
292 typedef LazyEmittingLayer LazyEmitLayerT;
293
294 std::unique_ptr TM;
295 std::unique_ptr MM;
296 Mangler Mang;
297
298 NotifyObjectLoadedT NotifyObjectLoaded;
299 NotifyFinalizedT NotifyFinalized;
300
301 ObjectLayerT ObjectLayer;
302 CompileLayerT CompileLayer;
303 LazyEmitLayerT LazyEmitLayer;
304
305 // MCJIT keeps modules alive - we need to do the same for backwards
306 // compatibility.
307 std::vector> OwnedModules;
308
309 // We need to store ObjLayerT::ObjSetHandles for each of the object sets
310 // that have been emitted but not yet finalized so that we can forward the
311 // mapSectionAddress calls appropriately.
312 typedef std::set SectionAddrSet;
313 struct ObjSetHandleCompare {
314 bool operator()(ObjectLayerT::ObjSetHandleT H1,
315 ObjectLayerT::ObjSetHandleT H2) const {
316 return &*H1 < &*H2;
317 }
318 };
319 SectionAddrSet SectionsAllocatedSinceLastLoad;
320 std::map
321 UnfinalizedSections;
322
323 std::vector> Archives;
324 };
325 }
326
327 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H
0 #include "llvm/ADT/Triple.h"
1 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
2
3 #include
4
5 using namespace llvm;
6
7 namespace {
8
9 const char *JITCallbackFuncName = "call_jit_for_lazy_compile";
10 const char *JITCallbackIndexLabelPrefix = "jit_resolve_";
11
12 std::array X86GPRsToSave = {{
13 "rbp", "rbx", "r12", "r13", "r14", "r15", // Callee saved.
14 "rdi", "rsi", "rdx", "rcx", "r8", "r9", // Int args.
15 }};
16
17 std::array X86XMMsToSave = {{
18 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" // FP args
19 }};
20
21 template unsigned saveX86Regs(OStream &OS) {
22 for (const auto &GPR : X86GPRsToSave)
23 OS << " pushq %" << GPR << "\n";
24
25 OS << " subq $" << (16 * X86XMMsToSave.size()) << ", %rsp\n";
26
27 for (unsigned i = 0; i < X86XMMsToSave.size(); ++i)
28 OS << " movdqu %" << X86XMMsToSave[i] << ", "
29 << (16 * (X86XMMsToSave.size() - i - 1)) << "(%rsp)\n";
30
31 return (8 * X86GPRsToSave.size()) + (16 * X86XMMsToSave.size());
32 }
33
34 template void restoreX86Regs(OStream &OS) {
35 for (unsigned i = 0; i < X86XMMsToSave.size(); ++i)
36 OS << " movdqu " << (16 * i) << "(%rsp), %"
37 << X86XMMsToSave[(X86XMMsToSave.size() - i - 1)] << "\n";
38 OS << " addq $" << (16 * X86XMMsToSave.size()) << ", %rsp\n";
39
40 for (unsigned i = 0; i < X86GPRsToSave.size(); ++i)
41 OS << " popq %" << X86GPRsToSave[X86GPRsToSave.size() - i - 1] << "\n";
42 }
43
44 uint64_t call_jit_for_fn(JITResolveCallbackHandler *J, uint64_t FuncIdx) {
45 return J->resolve(FuncIdx);
46 }
47 }
48
49 namespace llvm {
50
51 std::string getJITResolveCallbackIndexLabel(unsigned I) {
52 std::ostringstream LabelStream;
53 LabelStream << JITCallbackIndexLabelPrefix << I;
54 return LabelStream.str();
55 }
56
57 void insertX86CallbackAsm(Module &M, JITResolveCallbackHandler &J) {
58 uint64_t CallbackAddr =
59 static_cast(reinterpret_cast(call_jit_for_fn));
60
61 std::ostringstream JITCallbackAsm;
62 Triple TT(M.getTargetTriple());
63
64 if (TT.getOS() == Triple::Darwin)
65 JITCallbackAsm << ".section __TEXT,__text,regular,pure_instructions\n"
66 << ".align 4, 0x90\n";
67 else
68 JITCallbackAsm << ".text\n"
69 << ".align 16, 0x90\n";
70
71 JITCallbackAsm << "jit_object_addr:\n"
72 << " .quad " << &J << "\n" << JITCallbackFuncName << ":\n";
73
74 uint64_t ReturnAddrOffset = saveX86Regs(JITCallbackAsm);
75
76 // Compute index, load object address, and call JIT.
77 JITCallbackAsm << " movq " << ReturnAddrOffset << "(%rsp), %rax\n"
78 << " leaq (jit_indices_start+5)(%rip), %rbx\n"
79 << " subq %rbx, %rax\n"
80 << " xorq %rdx, %rdx\n"
81 << " movq $5, %rbx\n"
82 << " divq %rbx\n"
83 << " movq %rax, %rsi\n"
84 << " leaq jit_object_addr(%rip), %rdi\n"
85 << " movq (%rdi), %rdi\n"
86 << " movabsq $" << CallbackAddr << ", %rax\n"
87 << " callq *%rax\n"
88 << " movq %rax, " << ReturnAddrOffset << "(%rsp)\n";
89
90 restoreX86Regs(JITCallbackAsm);
91
92 JITCallbackAsm << " retq\n"
93 << "jit_indices_start:\n";
94
95 for (JITResolveCallbackHandler::StubIndex I = 0; I < J.getNumFuncs(); ++I)
96 JITCallbackAsm << getJITResolveCallbackIndexLabel(I) << ":\n"
97 << " callq " << JITCallbackFuncName << "\n";
98
99 M.appendModuleInlineAsm(JITCallbackAsm.str());
100 }
101 }
448448 StringRef Name;
449449 Check(Sym.getName(Name));
450450
451 assert((GlobalSymbolTable.find(Name) == GlobalSymbolTable.end()) &&
452 "Common symbol in global symbol table.");
453
454451 // Skip common symbols already elsewhere.
455 if (GlobalSymbolTable.count(Name)) {
452 if (GlobalSymbolTable.count(Name) ||
453 MemMgr->getSymbolAddressInLogicalDylib(Name)) {
456454 DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name
457455 << "'\n");
458456 continue;
99 MC
1010 MCJIT
1111 Object
12 OrcJIT
1213 SelectionDAG
1314 Support
1415 native
2424 #include "llvm/ExecutionEngine/JITEventListener.h"
2525 #include "llvm/ExecutionEngine/MCJIT.h"
2626 #include "llvm/ExecutionEngine/ObjectCache.h"
27 #include "llvm/ExecutionEngine/OrcMCJITReplacement.h"
2728 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
2829 #include "llvm/IR/IRBuilder.h"
2930 #include "llvm/IR/Module.h"
7374 cl::desc("Force interpretation: disable JIT"),
7475 cl::init(false));
7576
77 cl::opt UseOrcMCJITReplacement("use-orcmcjit",
78 cl::desc("Use the experimental "
79 "OrcMCJITReplacement as a "
80 "drop-in replacement for "
81 "MCJIT."),
82 cl::init(false));
83
7684 // The MCJIT supports building for a target address space separate from
7785 // the JIT compilation process. Use a forked process and a copying
7886 // memory manager with IPC to execute using this functionality.
420428 builder.setEngineKind(ForceInterpreter
421429 ? EngineKind::Interpreter
422430 : EngineKind::JIT);
431 builder.setUseOrcMCJITReplacement(UseOrcMCJITReplacement);
423432
424433 // If we are supposed to override the target triple, do so now.
425434 if (!TargetTriple.empty())