1 //===--------- LLJIT.cpp - An ORC-based JIT for compiling LLVM IR ---------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
11 #include "llvm/ExecutionEngine/Orc/OrcError.h"
12 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
13 #include "llvm/IR/Mangler.h"
14
15 namespace {
16
17 // A SimpleCompiler that owns its TargetMachine.
18 class TMOwningSimpleCompiler : public llvm::orc::SimpleCompiler {
19 public:
TMOwningSimpleCompiler(std::unique_ptr<llvm::TargetMachine> TM)20 TMOwningSimpleCompiler(std::unique_ptr<llvm::TargetMachine> TM)
21 : llvm::orc::SimpleCompiler(*TM), TM(std::move(TM)) {}
22 private:
23 // FIXME: shared because std::functions (and thus
24 // IRCompileLayer::CompileFunction) are not moveable.
25 std::shared_ptr<llvm::TargetMachine> TM;
26 };
27
28 } // end anonymous namespace
29
30 namespace llvm {
31 namespace orc {
32
~LLJIT()33 LLJIT::~LLJIT() {
34 if (CompileThreads)
35 CompileThreads->wait();
36 }
37
38 Expected<std::unique_ptr<LLJIT>>
Create(JITTargetMachineBuilder JTMB,DataLayout DL,unsigned NumCompileThreads)39 LLJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
40 unsigned NumCompileThreads) {
41
42 if (NumCompileThreads == 0) {
43 // If NumCompileThreads == 0 then create a single-threaded LLJIT instance.
44 auto TM = JTMB.createTargetMachine();
45 if (!TM)
46 return TM.takeError();
47 return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
48 std::move(*TM), std::move(DL)));
49 }
50
51 return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
52 std::move(JTMB), std::move(DL),
53 NumCompileThreads));
54 }
55
defineAbsolute(StringRef Name,JITEvaluatedSymbol Sym)56 Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {
57 auto InternedName = ES->intern(Name);
58 SymbolMap Symbols({{InternedName, Sym}});
59 return Main.define(absoluteSymbols(std::move(Symbols)));
60 }
61
addIRModule(JITDylib & JD,ThreadSafeModule TSM)62 Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
63 assert(TSM && "Can not add null module");
64
65 if (auto Err = applyDataLayout(*TSM.getModule()))
66 return Err;
67
68 return CompileLayer.add(JD, std::move(TSM), ES->allocateVModule());
69 }
70
addObjectFile(JITDylib & JD,std::unique_ptr<MemoryBuffer> Obj)71 Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
72 assert(Obj && "Can not add null object");
73
74 return ObjLinkingLayer.add(JD, std::move(Obj), ES->allocateVModule());
75 }
76
lookupLinkerMangled(JITDylib & JD,StringRef Name)77 Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
78 StringRef Name) {
79 return ES->lookup(JITDylibSearchList({{&JD, true}}), ES->intern(Name));
80 }
81
LLJIT(std::unique_ptr<ExecutionSession> ES,std::unique_ptr<TargetMachine> TM,DataLayout DL)82 LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES,
83 std::unique_ptr<TargetMachine> TM, DataLayout DL)
84 : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
85 ObjLinkingLayer(
86 *this->ES,
87 []() { return llvm::make_unique<SectionMemoryManager>(); }),
88 CompileLayer(*this->ES, ObjLinkingLayer,
89 TMOwningSimpleCompiler(std::move(TM))),
90 CtorRunner(Main), DtorRunner(Main) {}
91
LLJIT(std::unique_ptr<ExecutionSession> ES,JITTargetMachineBuilder JTMB,DataLayout DL,unsigned NumCompileThreads)92 LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
93 DataLayout DL, unsigned NumCompileThreads)
94 : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
95 ObjLinkingLayer(
96 *this->ES,
97 []() { return llvm::make_unique<SectionMemoryManager>(); }),
98 CompileLayer(*this->ES, ObjLinkingLayer,
99 ConcurrentIRCompiler(std::move(JTMB))),
100 CtorRunner(Main), DtorRunner(Main) {
101 assert(NumCompileThreads != 0 &&
102 "Multithreaded LLJIT instance can not be created with 0 threads");
103
104 // Move modules to new contexts when they're emitted so that we can compile
105 // them in parallel.
106 CompileLayer.setCloneToNewContextOnEmit(true);
107
108 // Create a thread pool to compile on and set the execution session
109 // dispatcher to use the thread pool.
110 CompileThreads = llvm::make_unique<ThreadPool>(NumCompileThreads);
111 this->ES->setDispatchMaterialization(
__anonb1c15e800402(JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) 112 [this](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) {
113 // FIXME: Switch to move capture once we have c++14.
114 auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU));
115 auto Work = [SharedMU, &JD]() { SharedMU->doMaterialize(JD); };
116 CompileThreads->async(std::move(Work));
117 });
118 }
119
mangle(StringRef UnmangledName)120 std::string LLJIT::mangle(StringRef UnmangledName) {
121 std::string MangledName;
122 {
123 raw_string_ostream MangledNameStream(MangledName);
124 Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
125 }
126 return MangledName;
127 }
128
applyDataLayout(Module & M)129 Error LLJIT::applyDataLayout(Module &M) {
130 if (M.getDataLayout().isDefault())
131 M.setDataLayout(DL);
132
133 if (M.getDataLayout() != DL)
134 return make_error<StringError>(
135 "Added modules have incompatible data layouts",
136 inconvertibleErrorCode());
137
138 return Error::success();
139 }
140
recordCtorDtors(Module & M)141 void LLJIT::recordCtorDtors(Module &M) {
142 CtorRunner.add(getConstructors(M));
143 DtorRunner.add(getDestructors(M));
144 }
145
146 Expected<std::unique_ptr<LLLazyJIT>>
Create(JITTargetMachineBuilder JTMB,DataLayout DL,JITTargetAddress ErrorAddr,unsigned NumCompileThreads)147 LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
148 JITTargetAddress ErrorAddr, unsigned NumCompileThreads) {
149 auto ES = llvm::make_unique<ExecutionSession>();
150
151 const Triple &TT = JTMB.getTargetTriple();
152
153 auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, ErrorAddr);
154 if (!LCTMgr)
155 return LCTMgr.takeError();
156
157 auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT);
158 if (!ISMBuilder)
159 return make_error<StringError>(
160 std::string("No indirect stubs manager builder for ") + TT.str(),
161 inconvertibleErrorCode());
162
163 if (NumCompileThreads == 0) {
164 auto TM = JTMB.createTargetMachine();
165 if (!TM)
166 return TM.takeError();
167 return std::unique_ptr<LLLazyJIT>(
168 new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL),
169 std::move(*LCTMgr), std::move(ISMBuilder)));
170 }
171
172 return std::unique_ptr<LLLazyJIT>(new LLLazyJIT(
173 std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads,
174 std::move(*LCTMgr), std::move(ISMBuilder)));
175 }
176
addLazyIRModule(JITDylib & JD,ThreadSafeModule TSM)177 Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
178 assert(TSM && "Can not add null module");
179
180 if (auto Err = applyDataLayout(*TSM.getModule()))
181 return Err;
182
183 recordCtorDtors(*TSM.getModule());
184
185 return CODLayer.add(JD, std::move(TSM), ES->allocateVModule());
186 }
187
LLLazyJIT(std::unique_ptr<ExecutionSession> ES,std::unique_ptr<TargetMachine> TM,DataLayout DL,std::unique_ptr<LazyCallThroughManager> LCTMgr,std::function<std::unique_ptr<IndirectStubsManager> ()> ISMBuilder)188 LLLazyJIT::LLLazyJIT(
189 std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
190 DataLayout DL, std::unique_ptr<LazyCallThroughManager> LCTMgr,
191 std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
192 : LLJIT(std::move(ES), std::move(TM), std::move(DL)),
193 LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
194 CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
195 std::move(ISMBuilder)) {}
196
LLLazyJIT(std::unique_ptr<ExecutionSession> ES,JITTargetMachineBuilder JTMB,DataLayout DL,unsigned NumCompileThreads,std::unique_ptr<LazyCallThroughManager> LCTMgr,std::function<std::unique_ptr<IndirectStubsManager> ()> ISMBuilder)197 LLLazyJIT::LLLazyJIT(
198 std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
199 DataLayout DL, unsigned NumCompileThreads,
200 std::unique_ptr<LazyCallThroughManager> LCTMgr,
201 std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
202 : LLJIT(std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads),
203 LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
204 CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
205 std::move(ISMBuilder)) {
206 CODLayer.setCloneToNewContextOnEmit(true);
207 }
208
209 } // End namespace orc.
210 } // End namespace llvm.
211