blob: b54c7d882e2476da5df2cf55cbe91b2d153e52e5 [file] [log] [blame]
Andrew Scullcdfcccc2018-10-05 20:58:37 +01001//===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +01006//
7//===----------------------------------------------------------------------===//
8//
9// An ORC-based JIT for compiling LLVM IR.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
14#define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
15
16#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
17#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
18#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
19#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
20#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
Andrew Scull0372a572018-11-16 15:47:06 +000021#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
Andrew Scullcdfcccc2018-10-05 20:58:37 +010022#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
Andrew Scull0372a572018-11-16 15:47:06 +000023#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
24#include "llvm/Support/ThreadPool.h"
Andrew Scullcdfcccc2018-10-05 20:58:37 +010025
26namespace llvm {
27namespace orc {
28
Andrew Walbran3d2c1972020-04-07 12:24:26 +010029class LLJITBuilderState;
30class LLLazyJITBuilderState;
31
Andrew Scullcdfcccc2018-10-05 20:58:37 +010032/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
Andrew Walbran3d2c1972020-04-07 12:24:26 +010033///
34/// Create instances using LLJITBuilder.
Andrew Scullcdfcccc2018-10-05 20:58:37 +010035class LLJIT {
Andrew Walbran3d2c1972020-04-07 12:24:26 +010036 template <typename, typename, typename> friend class LLJITBuilderSetters;
37
Andrew Scullcdfcccc2018-10-05 20:58:37 +010038public:
Andrew Walbran3d2c1972020-04-07 12:24:26 +010039 static Expected<std::unique_ptr<LLJIT>> Create(LLJITBuilderState &S);
Andrew Scullcdfcccc2018-10-05 20:58:37 +010040
Andrew Scull0372a572018-11-16 15:47:06 +000041 /// Destruct this instance. If a multi-threaded instance, waits for all
42 /// compile threads to complete.
43 ~LLJIT();
44
Andrew Scull0372a572018-11-16 15:47:06 +000045 /// Returns the ExecutionSession for this instance.
Andrew Scullcdfcccc2018-10-05 20:58:37 +010046 ExecutionSession &getExecutionSession() { return *ES; }
47
Andrew Walbran3d2c1972020-04-07 12:24:26 +010048 /// Returns a reference to the DataLayout for this instance.
49 const DataLayout &getDataLayout() const { return DL; }
50
Andrew Scull0372a572018-11-16 15:47:06 +000051 /// Returns a reference to the JITDylib representing the JIT'd main program.
52 JITDylib &getMainJITDylib() { return Main; }
Andrew Scullcdfcccc2018-10-05 20:58:37 +010053
Andrew Walbran3d2c1972020-04-07 12:24:26 +010054 /// Returns the JITDylib with the given name, or nullptr if no JITDylib with
55 /// that name exists.
56 JITDylib *getJITDylibByName(StringRef Name) {
57 return ES->getJITDylibByName(Name);
58 }
59
Andrew Walbran16937d02019-10-22 13:54:20 +010060 /// Create a new JITDylib with the given name and return a reference to it.
Andrew Walbran3d2c1972020-04-07 12:24:26 +010061 ///
62 /// JITDylib names must be unique. If the given name is derived from user
63 /// input or elsewhere in the environment then the client should check
64 /// (e.g. by calling getJITDylibByName) that the given name is not already in
65 /// use.
Andrew Walbran16937d02019-10-22 13:54:20 +010066 JITDylib &createJITDylib(std::string Name) {
67 return ES->createJITDylib(std::move(Name));
68 }
69
Andrew Scullcdfcccc2018-10-05 20:58:37 +010070 /// Convenience method for defining an absolute symbol.
71 Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
72
Andrew Scull0372a572018-11-16 15:47:06 +000073 /// Adds an IR module to the given JITDylib.
74 Error addIRModule(JITDylib &JD, ThreadSafeModule TSM);
75
76 /// Adds an IR module to the Main JITDylib.
77 Error addIRModule(ThreadSafeModule TSM) {
78 return addIRModule(Main, std::move(TSM));
Andrew Scullcdfcccc2018-10-05 20:58:37 +010079 }
80
Andrew Scull0372a572018-11-16 15:47:06 +000081 /// Adds an object file to the given JITDylib.
82 Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj);
Andrew Scullcdfcccc2018-10-05 20:58:37 +010083
Andrew Scull0372a572018-11-16 15:47:06 +000084 /// Adds an object file to the given JITDylib.
85 Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) {
86 return addObjectFile(Main, std::move(Obj));
87 }
88
89 /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
Andrew Scullcdfcccc2018-10-05 20:58:37 +010090 /// look up symbols based on their IR name use the lookup function instead).
Andrew Scull0372a572018-11-16 15:47:06 +000091 Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
92 StringRef Name);
93
94 /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name
95 /// (to look up symbols based on their IR name use the lookup function
96 /// instead).
Andrew Scullcdfcccc2018-10-05 20:58:37 +010097 Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
98 return lookupLinkerMangled(Main, Name);
99 }
100
Andrew Scull0372a572018-11-16 15:47:06 +0000101 /// Look up a symbol in JITDylib JD based on its IR symbol name.
102 Expected<JITEvaluatedSymbol> lookup(JITDylib &JD, StringRef UnmangledName) {
103 return lookupLinkerMangled(JD, mangle(UnmangledName));
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100104 }
105
Andrew Scull0372a572018-11-16 15:47:06 +0000106 /// Look up a symbol in the main JITDylib based on its IR symbol name.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100107 Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
108 return lookup(Main, UnmangledName);
109 }
110
111 /// Runs all not-yet-run static constructors.
112 Error runConstructors() { return CtorRunner.run(); }
113
114 /// Runs all not-yet-run static destructors.
115 Error runDestructors() { return DtorRunner.run(); }
116
Andrew Scull0372a572018-11-16 15:47:06 +0000117 /// Returns a reference to the ObjLinkingLayer
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100118 ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }
Andrew Scull0372a572018-11-16 15:47:06 +0000119
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100120protected:
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100121 static std::unique_ptr<ObjectLayer>
122 createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);
Andrew Scull0372a572018-11-16 15:47:06 +0000123
124 /// Create an LLJIT instance with a single compile thread.
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100125 LLJIT(LLJITBuilderState &S, Error &Err);
Andrew Scull0372a572018-11-16 15:47:06 +0000126
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100127 std::string mangle(StringRef UnmangledName);
128
129 Error applyDataLayout(Module &M);
130
131 void recordCtorDtors(Module &M);
132
133 std::unique_ptr<ExecutionSession> ES;
Andrew Scull0372a572018-11-16 15:47:06 +0000134 JITDylib &Main;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100135
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100136 DataLayout DL;
Andrew Scull0372a572018-11-16 15:47:06 +0000137 std::unique_ptr<ThreadPool> CompileThreads;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100138
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100139 std::unique_ptr<ObjectLayer> ObjLinkingLayer;
140 std::unique_ptr<IRCompileLayer> CompileLayer;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100141
Andrew Walbran16937d02019-10-22 13:54:20 +0100142 CtorDtorRunner CtorRunner, DtorRunner;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100143};
144
145/// An extended version of LLJIT that supports lazy function-at-a-time
146/// compilation of LLVM IR.
147class LLLazyJIT : public LLJIT {
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100148 template <typename, typename, typename> friend class LLJITBuilderSetters;
Andrew Scull0372a572018-11-16 15:47:06 +0000149
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100150public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100151
152 /// Set an IR transform (e.g. pass manager pipeline) to run on each function
153 /// when it is compiled.
Andrew Walbran16937d02019-10-22 13:54:20 +0100154 void setLazyCompileTransform(IRTransformLayer::TransformFunction Transform) {
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100155 TransformLayer->setTransform(std::move(Transform));
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100156 }
157
Andrew Scull0372a572018-11-16 15:47:06 +0000158 /// Sets the partition function.
159 void
Andrew Walbran16937d02019-10-22 13:54:20 +0100160 setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) {
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100161 CODLayer->setPartitionFunction(std::move(Partition));
Andrew Scull0372a572018-11-16 15:47:06 +0000162 }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100163
Andrew Scull0372a572018-11-16 15:47:06 +0000164 /// Add a module to be lazily compiled to JITDylib JD.
165 Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M);
166
167 /// Add a module to be lazily compiled to the main JITDylib.
168 Error addLazyIRModule(ThreadSafeModule M) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100169 return addLazyIRModule(Main, std::move(M));
170 }
171
172private:
Andrew Scull0372a572018-11-16 15:47:06 +0000173
174 // Create a single-threaded LLLazyJIT instance.
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100175 LLLazyJIT(LLLazyJITBuilderState &S, Error &Err);
Andrew Scull0372a572018-11-16 15:47:06 +0000176
177 std::unique_ptr<LazyCallThroughManager> LCTMgr;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100178 std::unique_ptr<IRTransformLayer> TransformLayer;
179 std::unique_ptr<CompileOnDemandLayer> CODLayer;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100180};
181
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100182class LLJITBuilderState {
183public:
184 using CreateObjectLinkingLayerFunction =
185 std::function<std::unique_ptr<ObjectLayer>(ExecutionSession &)>;
186
187 std::unique_ptr<ExecutionSession> ES;
188 Optional<JITTargetMachineBuilder> JTMB;
189 CreateObjectLinkingLayerFunction CreateObjectLinkingLayer;
190 unsigned NumCompileThreads = 0;
191
192 /// Called prior to JIT class construcion to fix up defaults.
193 Error prepareForConstruction();
194};
195
196template <typename JITType, typename SetterImpl, typename State>
197class LLJITBuilderSetters {
198public:
199 /// Set the JITTargetMachineBuilder for this instance.
200 ///
201 /// If this method is not called, JITTargetMachineBuilder::detectHost will be
202 /// used to construct a default target machine builder for the host platform.
203 SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) {
204 impl().JTMB = std::move(JTMB);
205 return impl();
206 }
207
208 /// Return a reference to the JITTargetMachineBuilder.
209 ///
210 Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() {
211 return impl().JTMB;
212 }
213
214 /// Set an ObjectLinkingLayer creation function.
215 ///
216 /// If this method is not called, a default creation function will be used
217 /// that will construct an RTDyldObjectLinkingLayer.
218 SetterImpl &setCreateObjectLinkingLayer(
219 LLJITBuilderState::CreateObjectLinkingLayerFunction
220 CreateObjectLinkingLayer) {
221 impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer);
222 return impl();
223 }
224
225 /// Set the number of compile threads to use.
226 ///
227 /// If set to zero, compilation will be performed on the execution thread when
228 /// JITing in-process. If set to any other number N, a thread pool of N
229 /// threads will be created for compilation.
230 ///
231 /// If this method is not called, behavior will be as if it were called with
232 /// a zero argument.
233 SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) {
234 impl().NumCompileThreads = NumCompileThreads;
235 return impl();
236 }
237
238 /// Create an instance of the JIT.
239 Expected<std::unique_ptr<JITType>> create() {
240 if (auto Err = impl().prepareForConstruction())
241 return std::move(Err);
242
243 Error Err = Error::success();
244 std::unique_ptr<JITType> J(new JITType(impl(), Err));
245 if (Err)
246 return std::move(Err);
247 return std::move(J);
248 }
249
250protected:
251 SetterImpl &impl() { return static_cast<SetterImpl &>(*this); }
252};
253
254/// Constructs LLJIT instances.
255class LLJITBuilder
256 : public LLJITBuilderState,
257 public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {};
258
259class LLLazyJITBuilderState : public LLJITBuilderState {
260 friend class LLLazyJIT;
261
262public:
263 using IndirectStubsManagerBuilderFunction =
264 std::function<std::unique_ptr<IndirectStubsManager>()>;
265
266 Triple TT;
267 JITTargetAddress LazyCompileFailureAddr = 0;
268 std::unique_ptr<LazyCallThroughManager> LCTMgr;
269 IndirectStubsManagerBuilderFunction ISMBuilder;
270
271 Error prepareForConstruction();
272};
273
274template <typename JITType, typename SetterImpl, typename State>
275class LLLazyJITBuilderSetters
276 : public LLJITBuilderSetters<JITType, SetterImpl, State> {
277public:
278 /// Set the address in the target address to call if a lazy compile fails.
279 ///
280 /// If this method is not called then the value will default to 0.
281 SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) {
282 this->impl().LazyCompileFailureAddr = Addr;
283 return this->impl();
284 }
285
286 /// Set the lazy-callthrough manager.
287 ///
288 /// If this method is not called then a default, in-process lazy callthrough
289 /// manager for the host platform will be used.
290 SetterImpl &
291 setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) {
292 this->impl().LCTMgr = std::move(LCTMgr);
293 return this->impl();
294 }
295
296 /// Set the IndirectStubsManager builder function.
297 ///
298 /// If this method is not called then a default, in-process
299 /// IndirectStubsManager builder for the host platform will be used.
300 SetterImpl &setIndirectStubsManagerBuilder(
301 LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) {
302 this->impl().ISMBuilder = std::move(ISMBuilder);
303 return this->impl();
304 }
305};
306
307/// Constructs LLLazyJIT instances.
308class LLLazyJITBuilder
309 : public LLLazyJITBuilderState,
310 public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,
311 LLLazyJITBuilderState> {};
312
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100313} // End namespace orc
314} // End namespace llvm
315
316#endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H