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:
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     // IRCompileLayer2::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 
33 LLJIT::~LLJIT() {
34   if (CompileThreads)
35     CompileThreads->wait();
36 }
37 
38 Expected<std::unique_ptr<LLJIT>>
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 
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 
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   auto K = ES->allocateVModule();
69   return CompileLayer.add(JD, K, std::move(TSM));
70 }
71 
72 Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
73   assert(Obj && "Can not add null object");
74 
75   auto K = ES->allocateVModule();
76   return ObjLinkingLayer.add(JD, K, std::move(Obj));
77 }
78 
79 Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
80                                                         StringRef Name) {
81   return ES->lookup({&JD}, ES->intern(Name));
82 }
83 
84 LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES,
85              std::unique_ptr<TargetMachine> TM, DataLayout DL)
86     : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
87       ObjLinkingLayer(*this->ES,
88                       [this](VModuleKey K) { return getMemoryManager(K); }),
89       CompileLayer(*this->ES, ObjLinkingLayer,
90                    TMOwningSimpleCompiler(std::move(TM))),
91       CtorRunner(Main), DtorRunner(Main) {}
92 
93 LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
94              DataLayout DL, unsigned NumCompileThreads)
95     : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
96       ObjLinkingLayer(*this->ES,
97                       [this](VModuleKey K) { return getMemoryManager(K); }),
98       CompileLayer(*this->ES, ObjLinkingLayer,
99                    MultiThreadedSimpleCompiler(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(
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 
120 std::unique_ptr<RuntimeDyld::MemoryManager>
121 LLJIT::getMemoryManager(VModuleKey K) {
122   return llvm::make_unique<SectionMemoryManager>();
123 }
124 
125 std::string LLJIT::mangle(StringRef UnmangledName) {
126   std::string MangledName;
127   {
128     raw_string_ostream MangledNameStream(MangledName);
129     Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
130   }
131   return MangledName;
132 }
133 
134 Error LLJIT::applyDataLayout(Module &M) {
135   if (M.getDataLayout().isDefault())
136     M.setDataLayout(DL);
137 
138   if (M.getDataLayout() != DL)
139     return make_error<StringError>(
140         "Added modules have incompatible data layouts",
141         inconvertibleErrorCode());
142 
143   return Error::success();
144 }
145 
146 void LLJIT::recordCtorDtors(Module &M) {
147   CtorRunner.add(getConstructors(M));
148   DtorRunner.add(getDestructors(M));
149 }
150 
151 Expected<std::unique_ptr<LLLazyJIT>>
152   LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
153                     unsigned NumCompileThreads) {
154   auto ES = llvm::make_unique<ExecutionSession>();
155 
156   const Triple &TT = JTMB.getTargetTriple();
157 
158   auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, 0);
159   if (!LCTMgr)
160     return LCTMgr.takeError();
161 
162   auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT);
163   if (!ISMBuilder)
164     return make_error<StringError>(
165         std::string("No indirect stubs manager builder for ") + TT.str(),
166         inconvertibleErrorCode());
167 
168   if (NumCompileThreads == 0) {
169     auto TM = JTMB.createTargetMachine();
170     if (!TM)
171       return TM.takeError();
172     return std::unique_ptr<LLLazyJIT>(
173         new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL),
174                       std::move(*LCTMgr), std::move(ISMBuilder)));
175   }
176 
177   return std::unique_ptr<LLLazyJIT>(new LLLazyJIT(
178       std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads,
179       std::move(*LCTMgr), std::move(ISMBuilder)));
180 }
181 
182 Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
183   assert(TSM && "Can not add null module");
184 
185   if (auto Err = applyDataLayout(*TSM.getModule()))
186     return Err;
187 
188   recordCtorDtors(*TSM.getModule());
189 
190   auto K = ES->allocateVModule();
191   return CODLayer.add(JD, K, std::move(TSM));
192 }
193 
194 LLLazyJIT::LLLazyJIT(
195     std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
196     DataLayout DL, std::unique_ptr<LazyCallThroughManager> LCTMgr,
197     std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
198     : LLJIT(std::move(ES), std::move(TM), std::move(DL)),
199       LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
200       CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
201                std::move(ISMBuilder)) {}
202 
203 LLLazyJIT::LLLazyJIT(
204     std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
205     DataLayout DL, unsigned NumCompileThreads,
206     std::unique_ptr<LazyCallThroughManager> LCTMgr,
207     std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
208     : LLJIT(std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads),
209       LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
210       CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
211                std::move(ISMBuilder)) {
212   CODLayer.setCloneToNewContextOnEmit(true);
213 }
214 
215 } // End namespace orc.
216 } // End namespace llvm.
217