llvm.org GIT mirror llvm / 9f1c239
[ORC] Add LLJIT and LLLazyJIT, and replace OrcLazyJIT in LLI with LLLazyJIT. LLJIT is a prefabricated ORC based JIT class that is meant to be the go-to replacement for MCJIT. Unlike OrcMCJITReplacement (which will continue to be supported) it is not API or bug-for-bug compatible, but targets the same use cases: Simple, non-lazy compilation and execution of LLVM IR. LLLazyJIT extends LLJIT with support for function-at-a-time lazy compilation, similar to what was provided by LLVM's original (now long deprecated) JIT APIs. This commit also contains some simple utility classes (CtorDtorRunner2, LocalCXXRuntimeOverrides2, JITTargetMachineBuilder) to support LLJIT and LLLazyJIT. Both of these classes are works in progress. Feedback from JIT clients is very welcome! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335670 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 2 years ago
15 changed file(s) with 835 addition(s) and 480 deletion(s). Raw diff Collapse all Expand all
621621 VSO(ExecutionSessionBase &ES, std::string Name)
622622 : ES(ES), VSOName(std::move(Name)) {}
623623
624 Error defineImpl(MaterializationUnit &MU);
625
626 SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
627 const SymbolNameSet &Names);
628
629 LookupImplActionFlags
630 lookupImpl(std::shared_ptr &Q,
631 std::vector> &MUs,
632 SymbolNameSet &Unresolved);
633
634 void detachQueryHelper(AsynchronousSymbolQuery &Q,
635 const SymbolNameSet &QuerySymbols);
636
637 void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI,
638 const SymbolStringPtr &DependantName,
639 MaterializingInfo &FinalizedMI);
640
641 Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
642
643 void replace(std::unique_ptr MU);
644
645 SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
646
647 void addDependencies(const SymbolFlagsMap &Dependents,
648 const SymbolDependenceMap &Dependencies);
649
650 void resolve(const SymbolMap &Resolved);
651
652 void finalize(const SymbolFlagsMap &Finalized);
653
654 void notifyFailed(const SymbolNameSet &FailedSymbols);
655
656 void runOutstandingMUs();
657
624658 ExecutionSessionBase &ES;
625659 std::string VSOName;
626660 SymbolMap Symbols;
628662 MaterializingInfosMap MaterializingInfos;
629663 FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator;
630664
631 Error defineImpl(MaterializationUnit &MU);
632
633 SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
634 const SymbolNameSet &Names);
635
636 LookupImplActionFlags
637 lookupImpl(std::shared_ptr &Q,
638 std::vector> &MUs,
639 SymbolNameSet &Unresolved);
640
641 void detachQueryHelper(AsynchronousSymbolQuery &Q,
642 const SymbolNameSet &QuerySymbols);
643
644 void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI,
645 const SymbolStringPtr &DependantName,
646 MaterializingInfo &FinalizedMI);
647
648 Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
649
650 void replace(std::unique_ptr MU);
651
652 SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
653
654 void addDependencies(const SymbolFlagsMap &Dependents,
655 const SymbolDependenceMap &Dependencies);
656
657 void resolve(const SymbolMap &Resolved);
658
659 void finalize(const SymbolFlagsMap &Finalized);
660
661 void notifyFailed(const SymbolNameSet &FailedSymbols);
665 // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
666 // with callbacks from asynchronous queries.
667 mutable std::recursive_mutex OutstandingMUsMutex;
668 std::vector> OutstandingMUs;
662669 };
663670
664671 /// An ExecutionSession represents a running JIT program.
1919 #include "llvm/ExecutionEngine/Orc/Core.h"
2020 #include "llvm/ExecutionEngine/Orc/OrcError.h"
2121 #include "llvm/ExecutionEngine/RuntimeDyld.h"
22 #include "llvm/Support/DynamicLibrary.h"
23 #include "llvm/Target/TargetOptions.h"
2224 #include
2325 #include
2426 #include
3133 class GlobalVariable;
3234 class Function;
3335 class Module;
36 class TargetMachine;
3437 class Value;
3538
3639 namespace orc {
40
41 /// A utility class for building TargetMachines for JITs.
42 class JITTargetMachineBuilder {
43 public:
44 JITTargetMachineBuilder(Triple TT);
45 static Expected detectHost();
46 Expected> createTargetMachine();
47
48 JITTargetMachineBuilder &setArch(std::string Arch) {
49 this->Arch = std::move(Arch);
50 return *this;
51 }
52 JITTargetMachineBuilder &setCPU(std::string CPU) {
53 this->CPU = std::move(CPU);
54 return *this;
55 }
56 JITTargetMachineBuilder &setRelocationModel(Optional RM) {
57 this->RM = std::move(RM);
58 return *this;
59 }
60 JITTargetMachineBuilder &setCodeModel(Optional CM) {
61 this->CM = std::move(CM);
62 return *this;
63 }
64 JITTargetMachineBuilder &
65 addFeatures(const std::vector &FeatureVec);
66 SubtargetFeatures &getFeatures() { return Features; }
67 TargetOptions &getOptions() { return Options; }
68
69 private:
70 Triple TT;
71 std::string Arch;
72 std::string CPU;
73 SubtargetFeatures Features;
74 TargetOptions Options;
75 Optional RM;
76 Optional CM;
77 CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
78 };
3779
3880 /// This iterator provides a convenient way to iterate over the elements
3981 /// of an llvm.global_ctors/llvm.global_dtors instance.
126168 orc::VModuleKey K;
127169 };
128170
171 class CtorDtorRunner2 {
172 public:
173 CtorDtorRunner2(VSO &V) : V(V) {}
174 void add(iterator_range CtorDtors);
175 Error run();
176
177 private:
178 using CtorDtorList = std::vector;
179 using CtorDtorPriorityMap = std::map;
180
181 VSO &V;
182 CtorDtorPriorityMap CtorDtorsByPriority;
183 };
184
129185 /// Support class for static dtor execution. For hosted (in-process) JITs
130186 /// only!
131187 ///
141197 /// the client determines that destructors should be run (generally at JIT
142198 /// teardown or after a return from main), the runDestructors method should be
143199 /// called.
144 class LocalCXXRuntimeOverrides {
200 class LocalCXXRuntimeOverridesBase {
201 public:
202 /// Run any destructors recorded by the overriden __cxa_atexit function
203 /// (CXAAtExitOverride).
204 void runDestructors();
205
206 protected:
207 template JITTargetAddress toTargetAddress(PtrTy *P) {
208 return static_cast(reinterpret_cast(P));
209 }
210
211 using DestructorPtr = void (*)(void *);
212 using CXXDestructorDataPair = std::pair;
213 using CXXDestructorDataPairList = std::vector;
214 CXXDestructorDataPairList DSOHandleOverride;
215 static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
216 void *DSOHandle);
217 };
218
219 class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
145220 public:
146221 /// Create a runtime-overrides class.
147222 template
158233 return nullptr;
159234 }
160235
161 /// Run any destructors recorded by the overriden __cxa_atexit function
162 /// (CXAAtExitOverride).
163 void runDestructors();
164
165 private:
166 template
167 JITTargetAddress toTargetAddress(PtrTy* P) {
168 return static_cast(reinterpret_cast(P));
169 }
170
236 private:
171237 void addOverride(const std::string &Name, JITTargetAddress Addr) {
172238 CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
173239 }
174240
175241 StringMap CXXRuntimeOverrides;
176
177 using DestructorPtr = void (*)(void *);
178 using CXXDestructorDataPair = std::pair;
179 using CXXDestructorDataPairList = std::vector;
180 CXXDestructorDataPairList DSOHandleOverride;
181 static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
182 void *DSOHandle);
242 };
243
244 class LocalCXXRuntimeOverrides2 : public LocalCXXRuntimeOverridesBase {
245 public:
246 Error enable(VSO &V, MangleAndInterner &Mangler);
247 };
248
249 /// A utility class to expose symbols found via dlsym to the JIT.
250 ///
251 /// If an instance of this class is attached to a VSO as a fallback definition
252 /// generator, then any symbol found in the given DynamicLibrary that passes
253 /// the 'Allow' predicate will be added to the VSO.
254 class DynamicLibraryFallbackGenerator {
255 public:
256 using SymbolPredicate = std::function;
257 DynamicLibraryFallbackGenerator(sys::DynamicLibrary Dylib,
258 const DataLayout &DL, SymbolPredicate Allow);
259 SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names);
260
261 private:
262 sys::DynamicLibrary Dylib;
263 SymbolPredicate Allow;
264 char GlobalPrefix;
183265 };
184266
185267 } // end namespace orc
186
187268 } // end namespace llvm
188269
189270 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
0 //===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- 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 3Bdetails.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // An ORC-based JIT for compiling LLVM IR.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
14 #define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
15
16 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
17 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
18 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
19 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
20 #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
21 #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
22 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
23 #include "llvm/Target/TargetMachine.h"
24
25 namespace llvm {
26 namespace orc {
27
28 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
29 class LLJIT {
30 public:
31 /// Create an LLJIT instance.
32 static Expected>
33 Create(std::unique_ptr ES,
34 std::unique_ptr TM, DataLayout DL);
35
36 /// Returns a reference to the ExecutionSession for this JIT instance.
37 ExecutionSession &getExecutionSession() { return *ES; }
38
39 /// Returns a reference to the VSO representing the JIT'd main program.
40 VSO &getMainVSO() { return Main; }
41
42 /// Convenience method for defining an absolute symbol.
43 Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
44
45 /// Adds an IR module to the given VSO.
46 Error addIRModule(VSO &V, std::unique_ptr M);
47
48 /// Adds an IR module to the Main VSO.
49 Error addIRModule(std::unique_ptr M) {
50 return addIRModule(Main, std::move(M));
51 }
52
53 /// Look up a symbol in VSO V by the symbol's linker-mangled name (to look up
54 /// symbols based on their IR name use the lookup function instead).
55 Expected lookupLinkerMangled(VSO &V, StringRef Name);
56
57 /// Look up a symbol in the main VSO by the symbol's linker-mangled name (to
58 /// look up symbols based on their IR name use the lookup function instead).
59 Expected lookupLinkerMangled(StringRef Name) {
60 return lookupLinkerMangled(Main, Name);
61 }
62
63 /// Look up a symbol in VSO V based on its IR symbol name.
64 Expected lookup(VSO &V, StringRef UnmangledName) {
65 return lookupLinkerMangled(V, mangle(UnmangledName));
66 }
67
68 /// Look up a symbol in the main VSO based on its IR symbol name.
69 Expected lookup(StringRef UnmangledName) {
70 return lookup(Main, UnmangledName);
71 }
72
73 /// Runs all not-yet-run static constructors.
74 Error runConstructors() { return CtorRunner.run(); }
75
76 /// Runs all not-yet-run static destructors.
77 Error runDestructors() { return DtorRunner.run(); }
78
79 protected:
80 LLJIT(std::unique_ptr ES, std::unique_ptr TM,
81 DataLayout DL);
82
83 std::shared_ptr takeSymbolResolver(VModuleKey K);
84 RTDyldObjectLinkingLayer2::Resources getRTDyldResources(VModuleKey K);
85
86 std::string mangle(StringRef UnmangledName);
87
88 std::unique_ptr createResolverFor(VSO &V);
89
90 Error applyDataLayout(Module &M);
91
92 void recordCtorDtors(Module &M);
93
94 std::unique_ptr ES;
95 VSO &Main;
96
97 std::unique_ptr TM;
98 DataLayout DL;
99
100 std::map VSOLookupOrder;
101
102 RTDyldObjectLinkingLayer2 ObjLinkingLayer;
103 IRCompileLayer2 CompileLayer;
104
105 std::map> Resolvers;
106 CtorDtorRunner2 CtorRunner, DtorRunner;
107 };
108
109 /// An extended version of LLJIT that supports lazy function-at-a-time
110 /// compilation of LLVM IR.
111 class LLLazyJIT : public LLJIT {
112 public:
113 /// Create an LLLazyJIT instance.
114 static Expected>
115 Create(std::unique_ptr ES,
116 std::unique_ptr TM, DataLayout DL, LLVMContext &Ctx);
117
118 /// Set an IR transform (e.g. pass manager pipeline) to run on each function
119 /// when it is compiled.
120 void setLazyCompileTransform(IRTransformLayer2::TransformFunction Transform) {
121 TransformLayer.setTransform(std::move(Transform));
122 }
123
124 /// Add a module to be lazily compiled to VSO V.
125 Error addLazyIRModule(VSO &V, std::unique_ptr M);
126
127 /// Add a module to be lazily compiled to the main VSO.
128 Error addLazyIRModule(std::unique_ptr M) {
129 return addLazyIRModule(Main, std::move(M));
130 }
131
132 private:
133 LLLazyJIT(std::unique_ptr ES,
134 std::unique_ptr TM, DataLayout DL, LLVMContext &Ctx,
135 std::unique_ptr CCMgr,
136 std::function()> ISMBuilder);
137
138 std::shared_ptr getSymbolResolver(VModuleKey K);
139
140 void setSymbolResolver(VModuleKey K, std::shared_ptr R);
141
142 std::unique_ptr CCMgr;
143 std::function()> ISMBuilder;
144
145 IRTransformLayer2 TransformLayer;
146 CompileOnDemandLayer2 CODLayer;
147 };
148
149 } // End namespace orc
150 } // End namespace llvm
151
152 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H
66 IRTransformLayer.cpp
77 Legacy.cpp
88 Layer.cpp
9 LLJIT.cpp
910 NullResolver.cpp
1011 ObjectTransformLayer.cpp
1112 OrcABISupport.cpp
3434 }
3535 } // namespace
3636
37 static void extractAliases(MaterializationResponsibility &R, Module &M,
38 MangleAndInterner &Mangle) {
39 SymbolAliasMap Aliases;
40
41 std::vector ModAliases;
42 for (auto &A : M.aliases())
43 ModAliases.push_back(&A);
44
45 for (auto *A : ModAliases) {
46 Constant *Aliasee = A->getAliasee();
47 assert(A->hasName() && "Anonymous alias?");
48 assert(Aliasee->hasName() && "Anonymous aliasee");
49 std::string AliasName = A->getName();
50
51 Aliases[Mangle(AliasName)] = SymbolAliasMapEntry(
52 {Mangle(Aliasee->getName()), JITSymbolFlags::fromGlobalValue(*A)});
53
54 if (isa(Aliasee)) {
55 auto *F = cloneFunctionDecl(M, *cast(Aliasee));
56 A->replaceAllUsesWith(F);
57 A->eraseFromParent();
58 F->setName(AliasName);
59 } else if (isa(Aliasee)) {
60 auto *G = cloneGlobalVariableDecl(M, *cast(Aliasee));
61 A->replaceAllUsesWith(G);
62 A->eraseFromParent();
63 G->setName(AliasName);
64 }
65 }
66
67 R.delegate(symbolAliases(std::move(Aliases)));
68 }
69
3770 static std::unique_ptr extractGlobals(Module &M) {
3871 // FIXME: Add alias support.
39
40 if (M.global_empty() && M.alias_empty() && !M.getModuleFlagsMetadata())
41 return nullptr;
4272
4373 auto GlobalsModule = llvm::make_unique(
4474 (M.getName() + ".globals").str(), M.getContext());
160190
161191 Error CompileOnDemandLayer2::add(VSO &V, VModuleKey K,
162192 std::unique_ptr M) {
163 makeAllSymbolsExternallyAccessible(*M);
164193 return IRLayer::add(V, K, std::move(M));
165194 }
166195
173202 if (GV.hasWeakLinkage())
174203 GV.setLinkage(GlobalValue::ExternalLinkage);
175204
205 MangleAndInterner Mangle(ES, M->getDataLayout());
206
207 extractAliases(R, *M, Mangle);
208
176209 auto GlobalsModule = extractGlobals(*M);
177
178 MangleAndInterner Mangle(ES, M->getDataLayout());
179210
180211 // Delete the bodies of any available externally functions, rename the
181212 // rest, and build the compile callbacks.
193224 }
194225
195226 assert(F.hasName() && "Function should have a name");
196 auto StubName = Mangle(F.getName());
227 std::string StubUnmangledName = F.getName();
197228 F.setName(F.getName() + "$body");
229 auto StubDecl = cloneFunctionDecl(*M, F);
230 StubDecl->setName(StubUnmangledName);
231 F.replaceAllUsesWith(StubDecl);
232 auto StubName = Mangle(StubUnmangledName);
198233 auto BodyName = Mangle(F.getName());
199234 if (auto CallbackAddr = CCMgr.getCompileCallback(
200235 [BodyName, &TargetVSO, &ES]() -> JITTargetAddress {
222257 StubInits[*KV.first] = KV.second;
223258
224259 // Build the function-body-extracting materialization unit.
260 auto SR = GetSymbolResolver(K);
225261 if (auto Err = R.getTargetVSO().define(
226262 llvm::make_unique(
227 ES, *this, std::move(M), GetSymbolResolver(K)))) {
263 ES, *this, std::move(M), SR))) {
228264 ES.reportError(std::move(Err));
229265 R.failMaterialization();
230266 return;
231267 }
268
269 // Replace the fallback symbol resolver: We will re-use M's VModuleKey for
270 // the GlobalsModule.
271 SetSymbolResolver(K, SR);
232272
233273 // Build the stubs.
234274 // FIXME: Remove function bodies materialization unit if stub creation fails.
722722
723723 for (auto &Q : FailedQueriesToNotify)
724724 Q->handleFailed(make_error(FailedSymbols));
725 }
726
727 void VSO::runOutstandingMUs() {
728 while (1) {
729 std::unique_ptr MU;
730
731 {
732 std::lock_guard Lock(OutstandingMUsMutex);
733 if (!OutstandingMUs.empty()) {
734 MU = std::move(OutstandingMUs.back());
735 OutstandingMUs.pop_back();
736 }
737 }
738
739 if (MU)
740 ES.dispatchMaterialization(*this, std::move(MU));
741 else
742 break;
743 }
725744 }
726745
727746 SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags,
766785 SymbolNameSet Names) {
767786 assert(Q && "Query can not be null");
768787
788 runOutstandingMUs();
789
769790 LookupImplActionFlags ActionFlags = None;
770791 std::vector> MUs;
771792
795816 if (ActionFlags & NotifyFullyReady)
796817 Q->handleFullyReady();
797818
819 // FIXME: Swap back to the old code below once RuntimeDyld works with
820 // callbacks from asynchronous queries.
821 // Add MUs to the OutstandingMUs list.
822 {
823 std::lock_guard Lock(OutstandingMUsMutex);
824 for (auto &MU : MUs)
825 OutstandingMUs.push_back(std::move(MU));
826 }
827 runOutstandingMUs();
828
798829 // Dispatch any required MaterializationUnits for materialization.
799 for (auto &MU : MUs)
800 ES.dispatchMaterialization(*this, std::move(MU));
830 // for (auto &MU : MUs)
831 // ES.dispatchMaterialization(*this, std::move(MU));
801832
802833 return Unresolved;
803834 }
1212 #include "llvm/IR/Function.h"
1313 #include "llvm/IR/GlobalVariable.h"
1414 #include "llvm/IR/Module.h"
15 #include "llvm/Support/TargetRegistry.h"
16 #include "llvm/Target/TargetMachine.h"
1517
1618 namespace llvm {
1719 namespace orc {
20
21 JITTargetMachineBuilder::JITTargetMachineBuilder(Triple TT)
22 : TT(std::move(TT)) {}
23
24 Expected JITTargetMachineBuilder::detectHost() {
25 return JITTargetMachineBuilder(Triple(sys::getProcessTriple()));
26 }
27
28 Expected>
29 JITTargetMachineBuilder::createTargetMachine() {
30 if (!Arch.empty()) {
31 Triple::ArchType Type = Triple::getArchTypeForLLVMName(Arch);
32
33 if (Type == Triple::UnknownArch)
34 return make_error(std::string("Unknown arch: ") + Arch,
35 inconvertibleErrorCode());
36 }
37
38 std::string ErrMsg;
39 auto *TheTarget = TargetRegistry::lookupTarget(TT.getTriple(), ErrMsg);
40 if (!TheTarget)
41 return make_error(std::move(ErrMsg), inconvertibleErrorCode());
42
43 auto *TM =
44 TheTarget->createTargetMachine(TT.getTriple(), CPU, Features.getString(),
45 Options, RM, CM, OptLevel, /*JIT*/ true);
46 if (!TM)
47 return make_error("Could not allocate target machine",
48 inconvertibleErrorCode());
49
50 return std::unique_ptr(TM);
51 }
52
53 JITTargetMachineBuilder &JITTargetMachineBuilder::addFeatures(
54 const std::vector &FeatureVec) {
55 for (const auto &F : FeatureVec)
56 Features.AddFeature(F);
57 return *this;
58 }
1859
1960 CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
2061 : InitList(
67108
68109 ConstantInt *Priority = dyn_cast(CS->getOperand(0));
69110 Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
111 if (!isa(Data))
112 Data = nullptr;
70113 return Element(Priority->getZExtValue(), Func, Data);
71114 }
72115
82125 CtorDtorIterator(DtorsList, true));
83126 }
84127
85 void LocalCXXRuntimeOverrides::runDestructors() {
128 void CtorDtorRunner2::add(iterator_range CtorDtors) {
129 if (CtorDtors.begin() == CtorDtors.end())
130 return;
131
132 MangleAndInterner Mangle(
133 V.getExecutionSession(),
134 (*CtorDtors.begin()).Func->getParent()->getDataLayout());
135
136 for (const auto &CtorDtor : CtorDtors) {
137 assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
138 "Ctor/Dtor function must be named to be runnable under the JIT");
139
140 if (CtorDtor.Data && cast(CtorDtor.Data)->isDeclaration()) {
141 dbgs() << " Skipping because why now?\n";
142 continue;
143 }
144
145 CtorDtorsByPriority[CtorDtor.Priority].push_back(
146 Mangle(CtorDtor.Func->getName()));
147 }
148 }
149
150 Error CtorDtorRunner2::run() {
151 using CtorDtorTy = void (*)();
152
153 SymbolNameSet Names;
154
155 for (auto &KV : CtorDtorsByPriority) {
156 for (auto &Name : KV.second) {
157 auto Added = Names.insert(Name).second;
158 (void)Added;
159 assert(Added && "Ctor/Dtor names clashed");
160 }
161 }
162
163 if (auto CtorDtorMap = lookup({&V}, std::move(Names))) {
164 for (auto &KV : CtorDtorsByPriority) {
165 for (auto &Name : KV.second) {
166 assert(CtorDtorMap->count(Name) && "No entry for Name");
167 auto CtorDtor = reinterpret_cast(
168 static_cast((*CtorDtorMap)[Name].getAddress()));
169 CtorDtor();
170 }
171 }
172 return Error::success();
173 } else
174 return CtorDtorMap.takeError();
175
176 CtorDtorsByPriority.clear();
177 }
178
179 void LocalCXXRuntimeOverridesBase::runDestructors() {
86180 auto& CXXDestructorDataPairs = DSOHandleOverride;
87181 for (auto &P : CXXDestructorDataPairs)
88182 P.first(P.second);
89183 CXXDestructorDataPairs.clear();
90184 }
91185
92 int LocalCXXRuntimeOverrides::CXAAtExitOverride(DestructorPtr Destructor,
93 void *Arg, void *DSOHandle) {
186 int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
187 void *Arg,
188 void *DSOHandle) {
94189 auto& CXXDestructorDataPairs =
95190 *reinterpret_cast(DSOHandle);
96191 CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
97192 return 0;
98193 }
99194
195 Error LocalCXXRuntimeOverrides2::enable(VSO &V, MangleAndInterner &Mangle) {
196 SymbolMap RuntimeInterposes(
197 {{Mangle("__dso_handle"),
198 JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride),
199 JITSymbolFlags::Exported)},
200 {Mangle("__cxa_atexit"),
201 JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride),
202 JITSymbolFlags::Exported)}});
203
204 return V.define(absoluteSymbols(std::move(RuntimeInterposes)));
205 }
206
207 DynamicLibraryFallbackGenerator::DynamicLibraryFallbackGenerator(
208 sys::DynamicLibrary Dylib, const DataLayout &DL, SymbolPredicate Allow)
209 : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
210 GlobalPrefix(DL.getGlobalPrefix()) {}
211
212 SymbolNameSet DynamicLibraryFallbackGenerator::
213 operator()(VSO &V, const SymbolNameSet &Names) {
214 orc::SymbolNameSet Added;
215 orc::SymbolMap NewSymbols;
216
217 bool HasGlobalPrefix = (GlobalPrefix != '\0');
218
219 for (auto &Name : Names) {
220 if (!Allow(Name) || (*Name).empty())
221 continue;
222
223 if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
224 continue;
225
226 std::string Tmp((*Name).data() + (HasGlobalPrefix ? 1 : 0), (*Name).size());
227 if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) {
228 Added.insert(Name);
229 NewSymbols[Name] = JITEvaluatedSymbol(
230 static_cast(reinterpret_cast(Addr)),
231 JITSymbolFlags::Exported);
232 }
233 }
234
235 // Add any new symbols to V. Since the fallback generator is only called for
236 // symbols that are not already defined, this will never trigger a duplicate
237 // definition error, so we can wrap this call in a 'cantFail'.
238 if (!NewSymbols.empty())
239 cantFail(V.define(absoluteSymbols(std::move(NewSymbols))));
240
241 return Added;
242 }
243
100244 } // End namespace orc.
101245 } // End namespace llvm.
264264
265265 Function* cloneFunctionDecl(Module &Dst, const Function &F,
266266 ValueToValueMapTy *VMap) {
267 assert(F.getParent() != &Dst && "Can't copy decl over existing function.");
268267 Function *NewF =
269268 Function::Create(cast(F.getValueType()),
270269 F.getLinkage(), F.getName(), &Dst);
302301
303302 GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
304303 ValueToValueMapTy *VMap) {
305 assert(GV.getParent() != &Dst && "Can't copy decl over existing global var.");
306304 GlobalVariable *NewGV = new GlobalVariable(
307305 Dst, GV.getValueType(), GV.isConstant(),
308306 GV.getLinkage(), nullptr, GV.getName(), nullptr,
0 //===--------- LLJIT.cpp - An ORC-based JIT for compiling LLVM IR ---------===//
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 "llvm/ExecutionEngine/Orc/LLJIT.h"
10 #include "llvm/ExecutionEngine/Orc/OrcError.h"
11 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
12 #include "llvm/IR/Mangler.h"
13
14 namespace llvm {
15 namespace orc {
16
17 Expected>
18 LLJIT::Create(std::unique_ptr ES,
19 std::unique_ptr TM, DataLayout DL) {
20 return std::unique_ptr(
21 new LLJIT(std::move(ES), std::move(TM), std::move(DL)));
22 }
23
24 Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {
25 auto InternedName = ES->getSymbolStringPool().intern(Name);
26 SymbolMap Symbols({{InternedName, Sym}});
27 return Main.define(absoluteSymbols(std::move(Symbols)));
28 }
29
30 Error LLJIT::addIRModule(VSO &V, std::unique_ptr M) {
31 assert(M && "Can not add null module");
32
33 if (auto Err = applyDataLayout(*M))
34 return Err;
35
36 auto K = ES->allocateVModule();
37 Resolvers[K] = createResolverFor(V);
38 return CompileLayer.add(V, K, std::move(M));
39 }
40
41 Expected LLJIT::lookupLinkerMangled(VSO &V,
42 StringRef Name) {
43 return llvm::orc::lookup({&V}, ES->getSymbolStringPool().intern(Name));
44 }
45
46 LLJIT::LLJIT(std::unique_ptr ES,
47 std::unique_ptr TM, DataLayout DL)
48 : ES(std::move(ES)), Main(this->ES->createVSO("main")), TM(std::move(TM)),
49 DL(std::move(DL)),
50 ObjLinkingLayer(*this->ES,
51 [this](VModuleKey K) { return getRTDyldResources(K); }),
52 CompileLayer(*this->ES, ObjLinkingLayer, SimpleCompiler(*this->TM)),
53 CtorRunner(Main), DtorRunner(Main) {
54 VSOLookupOrder[&Main] = VSOList({&Main});
55 }
56
57 std::shared_ptr LLJIT::takeSymbolResolver(VModuleKey K) {
58 auto ResolverI = Resolvers.find(K);
59 assert(ResolverI != Resolvers.end() && "Missing resolver");
60 auto Resolver = std::move(ResolverI->second);
61 Resolvers.erase(ResolverI);
62 return Resolver;
63 }
64
65 RTDyldObjectLinkingLayer2::Resources LLJIT::getRTDyldResources(VModuleKey K) {
66 return orc::RTDyldObjectLinkingLayer2::Resources(
67 {llvm::make_unique(), takeSymbolResolver(K)});
68 }
69
70 std::string LLJIT::mangle(StringRef UnmangledName) {
71 std::string MangledName;
72 {
73 raw_string_ostream MangledNameStream(MangledName);
74 Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
75 }
76 return MangledName;
77 }
78
79 std::unique_ptr LLJIT::createResolverFor(VSO &V) {
80 return createSymbolResolver(
81 [&](SymbolFlagsMap &Flags, const SymbolNameSet &Symbols) {
82 return V.lookupFlags(Flags, Symbols);
83 },
84 [&, this](std::shared_ptr Q,
85 SymbolNameSet Symbols) {
86 assert(VSOLookupOrder.count(&V) && "No VSO lookup order for V");
87 SymbolNameSet Unresolved = std::move(Symbols);
88 for (auto *LV : VSOLookupOrder[&V])
89 Unresolved = LV->lookup(Q, std::move(Unresolved));
90 return Unresolved;
91 });
92 }
93
94 Error LLJIT::applyDataLayout(Module &M) {
95 if (M.getDataLayout().isDefault())
96 M.setDataLayout(DL);
97
98 if (M.getDataLayout() != DL)
99 return make_error(
100 "Added modules have incompatible data layouts",
101 inconvertibleErrorCode());
102
103 return Error::success();
104 }
105
106 void LLJIT::recordCtorDtors(Module &M) {
107 CtorRunner.add(getConstructors(M));
108 DtorRunner.add(getDestructors(M));
109 }
110
111 Expected>
112 LLLazyJIT::Create(std::unique_ptr ES,
113 std::unique_ptr TM, DataLayout DL,
114 LLVMContext &Ctx) {
115 const Triple &TT = TM->getTargetTriple();
116
117 auto CCMgr = createLocalCompileCallbackManager(TT, *ES, 0);
118 if (!CCMgr)
119 return make_error(
120 std::string("No callback manager available for ") + TT.str(),
121 inconvertibleErrorCode());
122
123 auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT);
124 if (!ISMBuilder)
125 return make_error(
126 std::string("No indirect stubs manager builder for ") + TT.str(),
127 inconvertibleErrorCode());
128
129 return std::unique_ptr(
130 new LLLazyJIT(std::move(ES), std::move(TM), std::move(DL), Ctx,
131 std::move(CCMgr), std::move(ISMBuilder)));
132 }
133
134 Error LLLazyJIT::addLazyIRModule(VSO &V, std::unique_ptr M) {
135 assert(M && "Can not add null module");
136
137 if (auto Err = applyDataLayout(*M))
138 return Err;
139
140 makeAllSymbolsExternallyAccessible(*M);
141
142 recordCtorDtors(*M);
143
144 auto K = ES->allocateVModule();
145 setSymbolResolver(K, createResolverFor(V));
146 return CODLayer.add(V, K, std::move(M));
147 }
148
149 LLLazyJIT::LLLazyJIT(
150 std::unique_ptr ES, std::unique_ptr TM,
151 DataLayout DL, LLVMContext &Ctx,
152 std::unique_ptr CCMgr,
153 std::function()> ISMBuilder)
154 : LLJIT(std::move(ES), std::move(TM), std::move(DL)),
155 CCMgr(std::move(CCMgr)), TransformLayer(*this->ES, CompileLayer),
156 CODLayer(*this->ES, TransformLayer, *this->CCMgr, std::move(ISMBuilder),
157 [this](VModuleKey K) { return takeSymbolResolver(K); },
158 [this](VModuleKey K, std::shared_ptr R) {
159 setSymbolResolver(K, std::move(R));
160 },
161 [&]() -> LLVMContext & { return Ctx; }) {}
162
163 void LLLazyJIT::setSymbolResolver(VModuleKey K,
164 std::shared_ptr R) {
165 assert(!Resolvers.count(K) && "Resolver already present for VModule K");
166 Resolvers[K] = std::move(R);
167 }
168
169 } // End namespace orc.
170 } // End namespace llvm.
77 //===----------------------------------------------------------------------===//
88
99 #include "llvm/ExecutionEngine/Orc/Layer.h"
10 #include "llvm/IR/Mangler.h"
1110 #include "llvm/Object/ObjectFile.h"
1211 #include "llvm/Support/MemoryBuffer.h"
1312
2827
2928 MangleAndInterner Mangle(ES, this->M->getDataLayout());
3029 for (auto &G : this->M->global_values()) {
31 if (G.hasName() && !G.isDeclaration() &&
32 !G.hasLocalLinkage() &&
33 !G.hasAvailableExternallyLinkage()) {
30 if (G.hasName() && !G.isDeclaration() && !G.hasLocalLinkage() &&
31 !G.hasAvailableExternallyLinkage() && !G.hasAppendingLinkage()) {
3432 auto MangledName = Mangle(G.getName());
3533 SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
3634 SymbolToDefinition[MangledName] = &G;
0 ; RUN: lli -jit-kind=orc-lazy -orc-lazy-debug=funcs-to-stdout %s | FileCheck %s
11 ;
22 ; CHECK: Hello
3 ; CHECK: [ {{.*}}main ]
3 ; CHECK: [ {{.*}}main{{.*}} ]
44 ; CHECK: Goodbye
55
66 %class.Foo = type { i8 }
3737
3838 add_llvm_tool(lli
3939 lli.cpp
40 OrcLazyJIT.cpp
4140
4241 DEPENDS
4342 intrinsics_gen
+0
-155
tools/lli/OrcLazyJIT.cpp less more
None //===- OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution ------------===//
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 "OrcLazyJIT.h"
10 #include "llvm/ADT/Triple.h"
11 #include "llvm/ExecutionEngine/ExecutionEngine.h"
12 #include "llvm/Support/CodeGen.h"
13 #include "llvm/Support/CommandLine.h"
14 #include "llvm/Support/DynamicLibrary.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/FileSystem.h"
17 #include
18 #include
19 #include
20 #include
21
22 using namespace llvm;
23
24 namespace {
25
26 enum class DumpKind {
27 NoDump,
28 DumpFuncsToStdOut,
29 DumpModsToStdOut,
30 DumpModsToDisk
31 };
32
33 } // end anonymous namespace
34
35 static cl::opt OrcDumpKind(
36 "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."),
37 cl::init(DumpKind::NoDump),
38 cl::values(clEnumValN(DumpKind::NoDump, "no-dump", "Don't dump anything."),
39 clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",
40 "Dump function names to stdout."),
41 clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",
42 "Dump modules to stdout."),
43 clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",
44 "Dump modules to the current "
45 "working directory. (WARNING: "
46 "will overwrite existing files).")),
47 cl::Hidden);
48
49 static cl::opt OrcInlineStubs("orc-lazy-inline-stubs",
50 cl::desc("Try to inline stubs"),
51 cl::init(true), cl::Hidden);
52
53 OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
54 switch (OrcDumpKind) {
55 case DumpKind::NoDump:
56 return [](std::unique_ptr M) { return M; };
57
58 case DumpKind::DumpFuncsToStdOut:
59 return [](std::unique_ptr M) {
60 printf("[ ");
61
62 for (const auto &F : *M) {
63 if (F.isDeclaration())
64 continue;
65
66 if (F.hasName()) {
67 std::string Name(F.getName());
68 printf("%s ", Name.c_str());
69 } else
70 printf(" ");
71 }
72
73 printf("]\n");
74 return M;
75 };
76
77 case DumpKind::DumpModsToStdOut:
78 return [](std::unique_ptr M) {
79 outs() << "----- Module Start -----\n"
80 << *M << "----- Module End -----\n";
81
82 return M;
83 };
84
85 case DumpKind::DumpModsToDisk:
86 return [](std::unique_ptr M) {
87 std::error_code EC;
88 raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC, sys::fs::F_Text);
89 if (EC) {
90 errs() << "Couldn't open " << M->getModuleIdentifier()
91 << " for dumping.\nError:" << EC.message() << "\n";
92 exit(1);
93 }
94 Out << *M;
95 return M;
96 };
97 }
98 llvm_unreachable("Unknown DumpKind");
99 }
100
101 // Defined in lli.cpp.
102 CodeGenOpt::Level getOptLevel();
103
104 template
105 static PtrTy fromTargetAddress(JITTargetAddress Addr) {
106 return reinterpret_cast(static_cast(Addr));
107 }
108
109 int llvm::runOrcLazyJIT(std::vector> Ms,
110 const std::vector &Args) {
111 // Add the program's symbols into the JIT's search space.
112 if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
113 errs() << "Error loading program symbols.\n";
114 return 1;
115 }
116
117 // Grab a target machine and try to build a factory function for the
118 // target-specific Orc callback manager.
119 EngineBuilder EB;
120 EB.setOptLevel(getOptLevel());
121 auto TM = std::unique_ptr(EB.selectTarget());
122 Triple T(TM->getTargetTriple());
123
124 auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T);
125
126 // If we couldn't build a stubs-manager-builder for this target then bail out.
127 if (!IndirectStubsMgrBuilder) {
128 errs() << "No indirect stubs manager available for target '"
129 << TM->getTargetTriple().str() << "'.\n";
130 return 1;
131 }
132
133 // Everything looks good. Build the JIT.
134 OrcLazyJIT J(std::move(TM), std::move(IndirectStubsMgrBuilder),
135 OrcInlineStubs);
136
137 // Add the module, look up main and run it.
138 for (auto &M : Ms)
139 cantFail(J.addModule(std::move(M)));
140
141 if (auto MainSym = J.findSymbol("main")) {
142 typedef int (*MainFnPtr)(int, const char*[]);
143 std::vector ArgV;
144 for (auto &Arg : Args)
145 ArgV.push_back(Arg.c_str());
146 auto Main = fromTargetAddress(cantFail(MainSym.getAddress()));
147 return Main(ArgV.size(), (const char**)ArgV.data());
148 } else if (auto Err = MainSym.takeError())
149 logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
150 else
151 errs() << "Could not find main function.\n";
152
153 return 1;
154 }
+0
-252
tools/lli/OrcLazyJIT.h less more
None //===- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution ----*- 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 // Simple Orc-based JIT. Uses the compile-on-demand layer to break up and
10 // lazily compile modules.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H
15 #define LLVM_TOOLS_LLI_ORCLAZYJIT_H
16
17 #include "llvm/ADT/Optional.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/ExecutionEngine/JITSymbol.h"
21 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
22 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
23 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
24 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
25 #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
26 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
27 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
28 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
29 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
30 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
31 #include "llvm/IR/DataLayout.h"
32 #include "llvm/IR/GlobalValue.h"
33 #include "llvm/IR/Mangler.h"
34 #include "llvm/IR/Module.h"
35 #include "llvm/Support/raw_ostream.h"
36 #include "llvm/Target/TargetMachine.h"
37 #include
38 #include
39 #include
40 #include
41 #include
42 #include
43
44 namespace llvm {
45
46 class OrcLazyJIT {
47 public:
48
49 using CompileCallbackMgr = orc::JITCompileCallbackManager;
50 using ObjLayerT = orc::RTDyldObjectLinkingLayer;
51 using CompileLayerT = orc::IRCompileLayer;
52 using TransformFtor =
53 std::function(std::unique_ptr)>;
54 using IRDumpLayerT = orc::IRTransformLayer;
55 using CODLayerT = orc::CompileOnDemandLayer;
56 using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
57
58 OrcLazyJIT(std::unique_ptr TM,
59 IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
60 bool InlineStubs)
61 : TM(std::move(TM)), DL(this->TM->createDataLayout()),
62 CCMgr(orc::createLocalCompileCallbackManager(
63 this->TM->getTargetTriple(), ES, 0)),
64 ObjectLayer(ES,
65 [this](orc::VModuleKey K) {
66 auto ResolverI = Resolvers.find(K);
67 assert(ResolverI != Resolvers.end() &&
68 "Missing resolver for module K");
69 auto Resolver = std::move(ResolverI->second);
70 Resolvers.erase(ResolverI);
71 return ObjLayerT::Resources{
72 std::make_shared(),
73 std::move(Resolver)};
74 }),
75 CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
76 IRDumpLayer(CompileLayer, createDebugDumper()),
77 CODLayer(
78 ES, IRDumpLayer,
79 [&](orc::VModuleKey K) {
80 auto ResolverI = Resolvers.find(K);
81 assert(ResolverI != Resolvers.end() &&
82 "Missing resolver for module K");
83 auto Resolver = std::move(ResolverI->second);
84 Resolvers.erase(ResolverI);
85 return Resolver;
86 },
87 [&](orc::VModuleKey K, std::shared_ptr R) {
88 assert(!Resolvers.count(K) && "Resolver already present");
89 Resolvers[K] = std::move(R);
90 },
91 extractSingleFunction, *this->CCMgr,
92 std::move(IndirectStubsMgrBuilder), InlineStubs),
93 CXXRuntimeOverrides(
94 [this](const std::string &S) { return mangle(S); }) {}
95
96 ~OrcLazyJIT() {
97 // Run any destructors registered with __cxa_atexit.
98 CXXRuntimeOverrides.runDestructors();
99 // Run any IR destructors.
100 for (auto &DtorRunner : IRStaticDestructorRunners)
101 if (auto Err = DtorRunner.runViaLayer(CODLayer)) {
102 // FIXME: OrcLazyJIT should probably take a "shutdownError" callback to
103 // report these errors on.
104 report_fatal_error(std::move(Err));
105 }
106 }
107
108 Error addModule(std::unique_ptr M) {
109 if (M->getDataLayout().isDefault())
110 M->setDataLayout(DL);
111
112 // Rename, bump linkage and record static constructors and destructors.
113 // We have to do this before we hand over ownership of the module to the
114 // JIT.
115 std::vector CtorNames, DtorNames;
116 {
117 unsigned CtorId = 0, DtorId = 0;
118 for (auto Ctor : orc::getConstructors(*M)) {
119 std::string NewCtorName = ("$static_ctor." + Twine(CtorId++)).str();
120 Ctor.Func->setName(NewCtorName);
121 Ctor.Func->setLinkage(GlobalValue::ExternalLinkage);
122 Ctor.Func->setVisibility(GlobalValue::HiddenVisibility);
123 CtorNames.push_back(mangle(NewCtorName));
124 }
125 for (auto Dtor : orc::getDestructors(*M)) {
126 std::string NewDtorName = ("$static_dtor." + Twine(DtorId++)).str();
127 Dtor.Func->setLinkage(GlobalValue::ExternalLinkage);
128 Dtor.Func->setVisibility(GlobalValue::HiddenVisibility);
129 DtorNames.push_back(mangle(Dtor.Func->getName()));
130 Dtor.Func->setName(NewDtorName);
131 }
132 }
133
134 // Symbol resolution order:
135 // 1) Search the JIT symbols.
136 // 2) Check for C++ runtime overrides.
137 // 3) Search the host process (LLI)'s symbol table.
138 if (!ModulesKey) {
139 auto LegacyLookupInDylib = [this](const std::string &Name) -> JITSymbol {
140 if (auto Sym = CODLayer.findSymbol(Name, true))
141 return Sym;
142 else if (auto Err = Sym.takeError())
143 return std::move(Err);
144 return CXXRuntimeOverrides.searchOverrides(Name);
145 };
146
147 auto LegacyLookup =
148 [LegacyLookupInDylib](const std::string &Name) -> JITSymbol {
149 if (auto Sym = LegacyLookupInDylib(Name))
150 return Sym;
151 else if (auto Err = Sym.takeError())
152 return std::move(Err);
153
154 if (auto Addr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
155 return JITSymbol(Addr, JITSymbolFlags::Exported);
156
157 return nullptr;
158 };
159
160 ModulesKey = ES.allocateVModule();
161 assert(!Resolvers.count(*ModulesKey) && "Resolver already present");
162 Resolvers[*ModulesKey] = orc::createSymbolResolver(
163 [LegacyLookupInDylib](orc::SymbolFlagsMap &SymbolFlags,
164 const orc::SymbolNameSet &Symbols) {
165 auto NotFoundViaLegacyLookup = lookupFlagsWithLegacyFn(
166 SymbolFlags, Symbols, LegacyLookupInDylib);
167 if (!NotFoundViaLegacyLookup) {
168 logAllUnhandledErrors(NotFoundViaLegacyLookup.takeError(), errs(),
169 "OrcLazyJIT lookupFlags error: ");
170 SymbolFlags.clear();
171 return orc::SymbolNameSet();
172 }
173 return std::move(*NotFoundViaLegacyLookup);
174 },
175 [this,
176 LegacyLookup](std::shared_ptr Query,
177 orc::SymbolNameSet Symbols) {
178 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
179 });
180
181 // Add the module to the JIT.
182 if (auto Err = CODLayer.addModule(*ModulesKey, std::move(M)))
183 return Err;
184
185 } else if (auto Err = CODLayer.addExtraModule(*ModulesKey, std::move(M)))
186 return Err;
187
188 // Run the static constructors, and save the static destructor runner for
189 // execution when the JIT is torn down.
190 orc::CtorDtorRunner CtorRunner(std::move(CtorNames),
191 *ModulesKey);
192 if (auto Err = CtorRunner.runViaLayer(CODLayer))
193 return Err;
194
195 IRStaticDestructorRunners.emplace_back(std::move(DtorNames), *ModulesKey);
196
197 return Error::success();
198 }
199
200 JITSymbol findSymbol(const std::string &Name) {
201 return CODLayer.findSymbol(mangle(Name), true);
202 }
203
204 JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name) {
205 return CODLayer.findSymbolIn(K, mangle(Name), true);
206 }
207
208 private:
209 std::string mangle(const std::string &Name) {
210 std::string MangledName;
211 {
212 raw_string_ostream MangledNameStream(MangledName);
213 Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
214 }
215 return MangledName;
216 }
217
218 static std::set extractSingleFunction(Function &F) {
219 std::set Partition;
220 Partition.insert(&F);
221 return Partition;
222 }
223
224 static TransformFtor createDebugDumper();
225
226 orc::SymbolStringPool SSP;
227 orc::ExecutionSession ES;
228
229 std::map> Resolvers;
230
231 std::unique_ptr TM;
232 DataLayout DL;
233 SectionMemoryManager CCMgrMemMgr;
234
235 std::unique_ptr CCMgr;
236 ObjLayerT ObjectLayer;
237 CompileLayerT CompileLayer;
238 IRDumpLayerT IRDumpLayer;
239 CODLayerT CODLayer;
240
241 orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
242 std::vector> IRStaticDestructorRunners;
243 llvm::Optional ModulesKey;
244 };
245
246 int runOrcLazyJIT(std::vector> Ms,
247 const std::vector &Args);
248
249 } // end namespace llvm
250
251 #endif // LLVM_TOOLS_LLI_ORCLAZYJIT_H
1212 //
1313 //===----------------------------------------------------------------------===//
1414
15 #include "OrcLazyJIT.h"
1615 #include "RemoteJITUtils.h"
1716 #include "llvm/ADT/StringExtras.h"
1817 #include "llvm/ADT/Triple.h"
2524 #include "llvm/ExecutionEngine/JITEventListener.h"
2625 #include "llvm/ExecutionEngine/MCJIT.h"
2726 #include "llvm/ExecutionEngine/ObjectCache.h"
27 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
28 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
2829 #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h"
2930 #include "llvm/ExecutionEngine/OrcMCJITReplacement.h"
3031 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
176177 cl::desc("Generate software floating point library calls"),
177178 cl::init(false));
178179
180 enum class DumpKind {
181 NoDump,
182 DumpFuncsToStdOut,
183 DumpModsToStdOut,
184 DumpModsToDisk
185 };
186
187 cl::opt OrcDumpKind(
188 "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."),
189 cl::init(DumpKind::NoDump),
190 cl::values(clEnumValN(DumpKind::NoDump, "no-dump",
191 "Don't dump anything."),
192 clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",
193 "Dump function names to stdout."),
194 clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",
195 "Dump modules to stdout."),
196 clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",
197 "Dump modules to the current "
198 "working directory. (WARNING: "
199 "will overwrite existing files).")),
200 cl::Hidden);
201
179202 ExitOnError ExitOnErr;
180203 }
181204
312335 exit(1);
313336 }
314337
338 int runOrcLazyJIT(LLVMContext &Ctx, std::vector> Ms,
339 const std::vector &Args);
340
315341 //===----------------------------------------------------------------------===//
316342 // main Driver function
317343 //
355381 Args.push_back(InputFile);
356382 for (auto &Arg : InputArgv)
357383 Args.push_back(Arg);
358 return runOrcLazyJIT(std::move(Ms), Args);
384 return runOrcLazyJIT(Context, std::move(Ms), Args);
359385 }
360386
361387 if (EnableCacheManager) {
657683 return Result;
658684 }
659685
686 static orc::IRTransformLayer2::TransformFunction createDebugDumper() {
687 switch (OrcDumpKind) {
688 case DumpKind::NoDump:
689 return [](std::unique_ptr M) { return M; };
690
691 case DumpKind::DumpFuncsToStdOut:
692 return [](std::unique_ptr M) {
693 printf("[ ");
694
695 for (const auto &F : *M) {
696 if (F.isDeclaration())
697 continue;
698
699 if (F.hasName()) {
700 std::string Name(F.getName());
701 printf("%s ", Name.c_str());
702 } else
703 printf(" ");
704 }
705
706 printf("]\n");
707 return M;
708 };
709
710 case DumpKind::DumpModsToStdOut:
711 return [](std::unique_ptr M) {
712 outs() << "----- Module Start -----\n"
713 << *M << "----- Module End -----\n";
714
715 return M;
716 };
717
718 case DumpKind::DumpModsToDisk:
719 return [](std::unique_ptr M) {
720 std::error_code EC;
721 raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC, sys::fs::F_Text);
722 if (EC) {
723 errs() << "Couldn't open " << M->getModuleIdentifier()
724 << " for dumping.\nError:" << EC.message() << "\n";
725 exit(1);
726 }
727 Out << *M;
728 return M;
729 };
730 }
731 llvm_unreachable("Unknown DumpKind");
732 }
733
734 int runOrcLazyJIT(LLVMContext &Ctx, std::vector> Ms,
735 const std::vector &Args) {
736 // Bail out early if no modules loaded.
737 if (Ms.empty())
738 return 0;
739
740 // Add lli's symbols into the JIT's search space.
741 std::string ErrMsg;
742 sys::DynamicLibrary LibLLI =
743 sys::DynamicLibrary::getPermanentLibrary(nullptr, &ErrMsg);
744 if (!LibLLI.isValid()) {
745 errs() << "Error loading lli symbols: " << ErrMsg << ".\n";
746 return 1;
747 }
748
749 const auto &TT = Ms.front()->getTargetTriple();
750 orc::JITTargetMachineBuilder TMD =
751 TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost())
752 : orc::JITTargetMachineBuilder(Triple(TT));
753
754 TMD.setArch(MArch)
755 .setCPU(getCPUStr())
756 .addFeatures(getFeatureList())
757 .setRelocationModel(RelocModel.getNumOccurrences()
758 ? Optional(RelocModel)
759 : None)
760 .setCodeModel(CMModel.getNumOccurrences()
761 ? Optional(CMModel)
762 : None);
763 auto TM = ExitOnErr(TMD.createTargetMachine());
764 auto DL = TM->createDataLayout();
765 auto ES = llvm::make_unique();
766 auto J =
767 ExitOnErr(orc::LLLazyJIT::Create(std::move(ES), std::move(TM), DL, Ctx));
768
769 J->setLazyCompileTransform(createDebugDumper());
770 J->getMainVSO().setFallbackDefinitionGenerator(
771 orc::DynamicLibraryFallbackGenerator(
772 std::move(LibLLI), DL, [](orc::SymbolStringPtr) { return true; }));
773
774 orc::MangleAndInterner Mangle(J->getExecutionSession(), DL);
775 orc::LocalCXXRuntimeOverrides2 CXXRuntimeOverrides;
776 ExitOnErr(CXXRuntimeOverrides.enable(J->getMainVSO(), Mangle));
777
778 for (auto &M : Ms)
779 ExitOnErr(J->addLazyIRModule(std::move(M)));
780
781 ExitOnErr(J->runConstructors());
782
783 auto MainSym = ExitOnErr(J->lookup("main"));
784 typedef int (*MainFnPtr)(int, const char *[]);
785 std::vector ArgV;
786 for (auto &Arg : Args)
787 ArgV.push_back(Arg.c_str());
788 auto Main =
789 reinterpret_cast(static_cast(MainSym.getAddress()));
790 auto Result = Main(ArgV.size(), (const char **)ArgV.data());
791
792 ExitOnErr(J->runDestructors());
793
794 CXXRuntimeOverrides.runDestructors();
795
796 return Result;
797 }
798
660799 std::unique_ptr launchRemote() {
661800 #ifndef LLVM_ON_UNIX
662801 llvm_unreachable("launchRemote not supported on non-Unix platforms");