Line data Source code
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 0 : 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 24 : LLJIT::~LLJIT() {
34 12 : if (CompileThreads)
35 1 : CompileThreads->wait();
36 12 : }
37 :
38 : Expected<std::unique_ptr<LLJIT>>
39 0 : LLJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
40 : unsigned NumCompileThreads) {
41 :
42 0 : if (NumCompileThreads == 0) {
43 : // If NumCompileThreads == 0 then create a single-threaded LLJIT instance.
44 0 : auto TM = JTMB.createTargetMachine();
45 0 : if (!TM)
46 : return TM.takeError();
47 0 : return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
48 0 : std::move(*TM), std::move(DL)));
49 : }
50 :
51 0 : return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
52 : std::move(JTMB), std::move(DL),
53 0 : NumCompileThreads));
54 : }
55 :
56 0 : Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {
57 0 : auto InternedName = ES->intern(Name);
58 0 : SymbolMap Symbols({{InternedName, Sym}});
59 0 : return Main.define(absoluteSymbols(std::move(Symbols)));
60 : }
61 :
62 0 : Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
63 : assert(TSM && "Can not add null module");
64 :
65 0 : if (auto Err = applyDataLayout(*TSM.getModule()))
66 : return Err;
67 :
68 0 : return CompileLayer.add(JD, std::move(TSM), ES->allocateVModule());
69 : }
70 :
71 4 : Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
72 : assert(Obj && "Can not add null object");
73 :
74 8 : return ObjLinkingLayer.add(JD, std::move(Obj), ES->allocateVModule());
75 : }
76 :
77 13 : Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
78 : StringRef Name) {
79 26 : return ES->lookup({&JD}, ES->intern(Name));
80 : }
81 :
82 12 : LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES,
83 12 : std::unique_ptr<TargetMachine> TM, DataLayout DL)
84 12 : : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
85 : ObjLinkingLayer(
86 : *this->ES,
87 24 : []() { return llvm::make_unique<SectionMemoryManager>(); }),
88 : CompileLayer(*this->ES, ObjLinkingLayer,
89 12 : TMOwningSimpleCompiler(std::move(TM))),
90 36 : CtorRunner(Main), DtorRunner(Main) {}
91 :
92 1 : LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
93 1 : DataLayout DL, unsigned NumCompileThreads)
94 1 : : ES(std::move(ES)), Main(this->ES->getMainJITDylib()), DL(std::move(DL)),
95 : ObjLinkingLayer(
96 : *this->ES,
97 3 : []() { return llvm::make_unique<SectionMemoryManager>(); }),
98 : CompileLayer(*this->ES, ObjLinkingLayer,
99 1 : ConcurrentIRCompiler(std::move(JTMB))),
100 6 : 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 1 : 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 21 : auto Work = [SharedMU, &JD]() { SharedMU->doMaterialize(JD); };
116 : CompileThreads->async(std::move(Work));
117 1 : });
118 1 : }
119 :
120 13 : std::string LLJIT::mangle(StringRef UnmangledName) {
121 : std::string MangledName;
122 : {
123 13 : raw_string_ostream MangledNameStream(MangledName);
124 26 : Mangler::getNameWithPrefix(MangledNameStream, UnmangledName, DL);
125 : }
126 13 : return MangledName;
127 : }
128 :
129 14 : Error LLJIT::applyDataLayout(Module &M) {
130 14 : if (M.getDataLayout().isDefault())
131 14 : M.setDataLayout(DL);
132 :
133 28 : if (M.getDataLayout() != DL)
134 : return make_error<StringError>(
135 : "Added modules have incompatible data layouts",
136 0 : inconvertibleErrorCode());
137 :
138 : return Error::success();
139 : }
140 :
141 14 : void LLJIT::recordCtorDtors(Module &M) {
142 14 : CtorRunner.add(getConstructors(M));
143 14 : DtorRunner.add(getDestructors(M));
144 14 : }
145 :
146 : Expected<std::unique_ptr<LLLazyJIT>>
147 13 : LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
148 : unsigned NumCompileThreads) {
149 26 : auto ES = llvm::make_unique<ExecutionSession>();
150 :
151 : const Triple &TT = JTMB.getTargetTriple();
152 :
153 26 : auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, 0);
154 13 : if (!LCTMgr)
155 : return LCTMgr.takeError();
156 :
157 13 : auto ISMBuilder = createLocalIndirectStubsManagerBuilder(TT);
158 13 : if (!ISMBuilder)
159 0 : return make_error<StringError>(
160 0 : std::string("No indirect stubs manager builder for ") + TT.str(),
161 0 : inconvertibleErrorCode());
162 :
163 13 : if (NumCompileThreads == 0) {
164 24 : auto TM = JTMB.createTargetMachine();
165 12 : if (!TM)
166 : return TM.takeError();
167 24 : return std::unique_ptr<LLLazyJIT>(
168 : new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL),
169 12 : std::move(*LCTMgr), std::move(ISMBuilder)));
170 : }
171 :
172 2 : return std::unique_ptr<LLLazyJIT>(new LLLazyJIT(
173 : std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads,
174 1 : std::move(*LCTMgr), std::move(ISMBuilder)));
175 : }
176 :
177 14 : Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
178 : assert(TSM && "Can not add null module");
179 :
180 42 : if (auto Err = applyDataLayout(*TSM.getModule()))
181 : return Err;
182 :
183 14 : recordCtorDtors(*TSM.getModule());
184 :
185 28 : return CODLayer.add(JD, std::move(TSM), ES->allocateVModule());
186 : }
187 :
188 12 : LLLazyJIT::LLLazyJIT(
189 : std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
190 : DataLayout DL, std::unique_ptr<LazyCallThroughManager> LCTMgr,
191 12 : 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 48 : std::move(ISMBuilder)) {}
196 :
197 1 : LLLazyJIT::LLLazyJIT(
198 : std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
199 : DataLayout DL, unsigned NumCompileThreads,
200 : std::unique_ptr<LazyCallThroughManager> LCTMgr,
201 1 : 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 4 : std::move(ISMBuilder)) {
206 : CODLayer.setCloneToNewContextOnEmit(true);
207 1 : }
208 :
209 : } // End namespace orc.
210 : } // End namespace llvm.
|