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/Orc/RTDyldObjectLinkingLayer.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     // 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 
33 Error LLJITBuilderState::prepareForConstruction() {
34 
35   if (!JTMB) {
36     if (auto JTMBOrErr = JITTargetMachineBuilder::detectHost())
37       JTMB = std::move(*JTMBOrErr);
38     else
39       return JTMBOrErr.takeError();
40   }
41 
42   return Error::success();
43 }
44 
45 LLJIT::~LLJIT() {
46   if (CompileThreads)
47     CompileThreads->wait();
48 }
49 
50 Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {
51   auto InternedName = ES->intern(Name);
52   SymbolMap Symbols({{InternedName, Sym}});
53   return Main.define(absoluteSymbols(std::move(Symbols)));
54 }
55 
56 Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
57   assert(TSM && "Can not add null module");
58 
59   if (auto Err = applyDataLayout(*TSM.getModule()))
60     return Err;
61 
62   return CompileLayer->add(JD, std::move(TSM), ES->allocateVModule());
63 }
64 
65 Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
66   assert(Obj && "Can not add null object");
67 
68   return ObjLinkingLayer->add(JD, std::move(Obj), ES->allocateVModule());
69 }
70 
71 Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
72                                                         StringRef Name) {
73   return ES->lookup(JITDylibSearchList({{&JD, true}}), ES->intern(Name));
74 }
75 
76 std::unique_ptr<ObjectLayer>
77 LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) {
78 
79   // If the config state provided an ObjectLinkingLayer factory then use it.
80   if (S.CreateObjectLinkingLayer)
81     return S.CreateObjectLinkingLayer(ES);
82 
83   // Otherwise default to creating an RTDyldObjectLinkingLayer that constructs
84   // a new SectionMemoryManager for each object.
85   auto GetMemMgr = []() { return llvm::make_unique<SectionMemoryManager>(); };
86   return llvm::make_unique<RTDyldObjectLinkingLayer>(ES, std::move(GetMemMgr));
87 }
88 
89 LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
90     : ES(S.ES ? std::move(S.ES) : llvm::make_unique<ExecutionSession>()),
91       Main(this->ES->getMainJITDylib()), DL(""), CtorRunner(Main),
92       DtorRunner(Main) {
93 
94   ErrorAsOutParameter _(&Err);
95 
96   ObjLinkingLayer = createObjectLinkingLayer(S, *ES);
97 
98   if (S.NumCompileThreads > 0) {
99 
100     // Configure multi-threaded.
101 
102     if (auto DLOrErr = S.JTMB->getDefaultDataLayoutForTarget())
103       DL = std::move(*DLOrErr);
104     else {
105       Err = DLOrErr.takeError();
106       return;
107     }
108 
109     {
110       auto TmpCompileLayer = llvm::make_unique<IRCompileLayer>(
111           *ES, *ObjLinkingLayer, ConcurrentIRCompiler(std::move(*S.JTMB)));
112 
113       TmpCompileLayer->setCloneToNewContextOnEmit(true);
114       CompileLayer = std::move(TmpCompileLayer);
115     }
116 
117     CompileThreads = llvm::make_unique<ThreadPool>(S.NumCompileThreads);
118     ES->setDispatchMaterialization(
119         [this](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) {
120           // FIXME: Switch to move capture once we have c++14.
121           auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU));
122           auto Work = [SharedMU, &JD]() { SharedMU->doMaterialize(JD); };
123           CompileThreads->async(std::move(Work));
124         });
125   } else {
126 
127     // Configure single-threaded.
128 
129     auto TM = S.JTMB->createTargetMachine();
130     if (!TM) {
131       Err = TM.takeError();
132       return;
133     }
134 
135     DL = (*TM)->createDataLayout();
136 
137     CompileLayer = llvm::make_unique<IRCompileLayer>(
138         *ES, *ObjLinkingLayer, TMOwningSimpleCompiler(std::move(*TM)));
139   }
140 }
141 
142 std::string LLJIT::mangle(StringRef UnmangledName) {
143   std::string MangledName;
144   {
145     raw_string_ostream MangledNameStream(MangledName);
146     Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
147   }
148   return MangledName;
149 }
150 
151 Error LLJIT::applyDataLayout(Module &M) {
152   if (M.getDataLayout().isDefault())
153     M.setDataLayout(DL);
154 
155   if (M.getDataLayout() != DL)
156     return make_error<StringError>(
157         "Added modules have incompatible data layouts",
158         inconvertibleErrorCode());
159 
160   return Error::success();
161 }
162 
163 void LLJIT::recordCtorDtors(Module &M) {
164   CtorRunner.add(getConstructors(M));
165   DtorRunner.add(getDestructors(M));
166 }
167 
168 Error LLLazyJITBuilderState::prepareForConstruction() {
169   if (auto Err = LLJITBuilderState::prepareForConstruction())
170     return Err;
171   TT = JTMB->getTargetTriple();
172   return Error::success();
173 }
174 
175 Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
176   assert(TSM && "Can not add null module");
177 
178   if (auto Err = applyDataLayout(*TSM.getModule()))
179     return Err;
180 
181   recordCtorDtors(*TSM.getModule());
182 
183   return CODLayer->add(JD, std::move(TSM), ES->allocateVModule());
184 }
185 
186 LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) {
187 
188   // If LLJIT construction failed then bail out.
189   if (Err)
190     return;
191 
192   ErrorAsOutParameter _(&Err);
193 
194   /// Take/Create the lazy-compile callthrough manager.
195   if (S.LCTMgr)
196     LCTMgr = std::move(S.LCTMgr);
197   else {
198     if (auto LCTMgrOrErr = createLocalLazyCallThroughManager(
199             S.TT, *ES, S.LazyCompileFailureAddr))
200       LCTMgr = std::move(*LCTMgrOrErr);
201     else {
202       Err = LCTMgrOrErr.takeError();
203       return;
204     }
205   }
206 
207   // Take/Create the indirect stubs manager builder.
208   auto ISMBuilder = std::move(S.ISMBuilder);
209 
210   // If none was provided, try to build one.
211   if (!ISMBuilder)
212     ISMBuilder = createLocalIndirectStubsManagerBuilder(S.TT);
213 
214   // No luck. Bail out.
215   if (!ISMBuilder) {
216     Err = make_error<StringError>("Could not construct "
217                                   "IndirectStubsManagerBuilder for target " +
218                                       S.TT.str(),
219                                   inconvertibleErrorCode());
220     return;
221   }
222 
223   // Create the transform layer.
224   TransformLayer = llvm::make_unique<IRTransformLayer>(*ES, *CompileLayer);
225 
226   // Create the COD layer.
227   CODLayer = llvm::make_unique<CompileOnDemandLayer>(
228       *ES, *TransformLayer, *LCTMgr, std::move(ISMBuilder));
229 
230   if (S.NumCompileThreads > 0)
231     CODLayer->setCloneToNewContextOnEmit(true);
232 }
233 
234 } // End namespace orc.
235 } // End namespace llvm.
236