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