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