1 //===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // An ORC-based JIT for compiling LLVM IR.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
14 #define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
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"
21 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
22 #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
23 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
24 #include "llvm/Support/ThreadPool.h"
29 class LLJITBuilderState
;
30 class LLLazyJITBuilderState
;
32 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
34 /// Create instances using LLJITBuilder.
36 template <typename
, typename
, typename
> friend class LLJITBuilderSetters
;
39 static Expected
<std::unique_ptr
<LLJIT
>> Create(LLJITBuilderState
&S
);
41 /// Destruct this instance. If a multi-threaded instance, waits for all
42 /// compile threads to complete.
45 /// Returns the ExecutionSession for this instance.
46 ExecutionSession
&getExecutionSession() { return *ES
; }
48 /// Returns a reference to the DataLayout for this instance.
49 const DataLayout
&getDataLayout() const { return DL
; }
51 /// Returns a reference to the JITDylib representing the JIT'd main program.
52 JITDylib
&getMainJITDylib() { return Main
; }
54 /// Returns the JITDylib with the given name, or nullptr if no JITDylib with
56 JITDylib
*getJITDylibByName(StringRef Name
) {
57 return ES
->getJITDylibByName(Name
);
60 /// Create a new JITDylib with the given name and return a reference to it.
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
66 JITDylib
&createJITDylib(std::string Name
) {
67 return ES
->createJITDylib(std::move(Name
));
70 /// Convenience method for defining an absolute symbol.
71 Error
defineAbsolute(StringRef Name
, JITEvaluatedSymbol Address
);
73 /// Adds an IR module to the given JITDylib.
74 Error
addIRModule(JITDylib
&JD
, ThreadSafeModule TSM
);
76 /// Adds an IR module to the Main JITDylib.
77 Error
addIRModule(ThreadSafeModule TSM
) {
78 return addIRModule(Main
, std::move(TSM
));
81 /// Adds an object file to the given JITDylib.
82 Error
addObjectFile(JITDylib
&JD
, std::unique_ptr
<MemoryBuffer
> Obj
);
84 /// Adds an object file to the given JITDylib.
85 Error
addObjectFile(std::unique_ptr
<MemoryBuffer
> Obj
) {
86 return addObjectFile(Main
, std::move(Obj
));
89 /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
90 /// look up symbols based on their IR name use the lookup function instead).
91 Expected
<JITEvaluatedSymbol
> lookupLinkerMangled(JITDylib
&JD
,
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
97 Expected
<JITEvaluatedSymbol
> lookupLinkerMangled(StringRef Name
) {
98 return lookupLinkerMangled(Main
, Name
);
101 /// 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
));
106 /// Look up a symbol in the main JITDylib based on its IR symbol name.
107 Expected
<JITEvaluatedSymbol
> lookup(StringRef UnmangledName
) {
108 return lookup(Main
, UnmangledName
);
111 /// Runs all not-yet-run static constructors.
112 Error
runConstructors() { return CtorRunner
.run(); }
114 /// Runs all not-yet-run static destructors.
115 Error
runDestructors() { return DtorRunner
.run(); }
117 /// Returns a reference to the ObjLinkingLayer
118 ObjectLayer
&getObjLinkingLayer() { return *ObjLinkingLayer
; }
121 static std::unique_ptr
<ObjectLayer
>
122 createObjectLinkingLayer(LLJITBuilderState
&S
, ExecutionSession
&ES
);
124 static Expected
<IRCompileLayer::CompileFunction
>
125 createCompileFunction(LLJITBuilderState
&S
, JITTargetMachineBuilder JTMB
);
127 /// Create an LLJIT instance with a single compile thread.
128 LLJIT(LLJITBuilderState
&S
, Error
&Err
);
130 std::string
mangle(StringRef UnmangledName
);
132 Error
applyDataLayout(Module
&M
);
134 void recordCtorDtors(Module
&M
);
136 std::unique_ptr
<ExecutionSession
> ES
;
140 std::unique_ptr
<ThreadPool
> CompileThreads
;
142 std::unique_ptr
<ObjectLayer
> ObjLinkingLayer
;
143 std::unique_ptr
<IRCompileLayer
> CompileLayer
;
145 CtorDtorRunner CtorRunner
, DtorRunner
;
148 /// An extended version of LLJIT that supports lazy function-at-a-time
149 /// compilation of LLVM IR.
150 class LLLazyJIT
: public LLJIT
{
151 template <typename
, typename
, typename
> friend class LLJITBuilderSetters
;
155 /// Set an IR transform (e.g. pass manager pipeline) to run on each function
156 /// when it is compiled.
157 void setLazyCompileTransform(IRTransformLayer::TransformFunction Transform
) {
158 TransformLayer
->setTransform(std::move(Transform
));
161 /// Sets the partition function.
163 setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition
) {
164 CODLayer
->setPartitionFunction(std::move(Partition
));
167 /// Add a module to be lazily compiled to JITDylib JD.
168 Error
addLazyIRModule(JITDylib
&JD
, ThreadSafeModule M
);
170 /// Add a module to be lazily compiled to the main JITDylib.
171 Error
addLazyIRModule(ThreadSafeModule M
) {
172 return addLazyIRModule(Main
, std::move(M
));
177 // Create a single-threaded LLLazyJIT instance.
178 LLLazyJIT(LLLazyJITBuilderState
&S
, Error
&Err
);
180 std::unique_ptr
<LazyCallThroughManager
> LCTMgr
;
181 std::unique_ptr
<IRTransformLayer
> TransformLayer
;
182 std::unique_ptr
<CompileOnDemandLayer
> CODLayer
;
185 class LLJITBuilderState
{
187 using ObjectLinkingLayerCreator
= std::function
<std::unique_ptr
<ObjectLayer
>(
188 ExecutionSession
&, const Triple
&TT
)>;
190 using CompileFunctionCreator
=
191 std::function
<Expected
<IRCompileLayer::CompileFunction
>(
192 JITTargetMachineBuilder JTMB
)>;
194 std::unique_ptr
<ExecutionSession
> ES
;
195 Optional
<JITTargetMachineBuilder
> JTMB
;
196 ObjectLinkingLayerCreator CreateObjectLinkingLayer
;
197 CompileFunctionCreator CreateCompileFunction
;
198 unsigned NumCompileThreads
= 0;
200 /// Called prior to JIT class construcion to fix up defaults.
201 Error
prepareForConstruction();
204 template <typename JITType
, typename SetterImpl
, typename State
>
205 class LLJITBuilderSetters
{
207 /// Set the JITTargetMachineBuilder for this instance.
209 /// If this method is not called, JITTargetMachineBuilder::detectHost will be
210 /// used to construct a default target machine builder for the host platform.
211 SetterImpl
&setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB
) {
212 impl().JTMB
= std::move(JTMB
);
216 /// Return a reference to the JITTargetMachineBuilder.
218 Optional
<JITTargetMachineBuilder
> &getJITTargetMachineBuilder() {
222 /// Set an ObjectLinkingLayer creation function.
224 /// If this method is not called, a default creation function will be used
225 /// that will construct an RTDyldObjectLinkingLayer.
226 SetterImpl
&setObjectLinkingLayerCreator(
227 LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer
) {
228 impl().CreateObjectLinkingLayer
= std::move(CreateObjectLinkingLayer
);
232 /// Set a CompileFunctionCreator.
234 /// If this method is not called, a default creation function wil be used
235 /// that will construct a basic IR compile function that is compatible with
236 /// the selected number of threads (SimpleCompiler for '0' compile threads,
237 /// ConcurrentIRCompiler otherwise).
238 SetterImpl
&setCompileFunctionCreator(
239 LLJITBuilderState::CompileFunctionCreator CreateCompileFunction
) {
240 impl().CreateCompileFunction
= std::move(CreateCompileFunction
);
244 /// Set the number of compile threads to use.
246 /// If set to zero, compilation will be performed on the execution thread when
247 /// JITing in-process. If set to any other number N, a thread pool of N
248 /// threads will be created for compilation.
250 /// If this method is not called, behavior will be as if it were called with
252 SetterImpl
&setNumCompileThreads(unsigned NumCompileThreads
) {
253 impl().NumCompileThreads
= NumCompileThreads
;
257 /// Create an instance of the JIT.
258 Expected
<std::unique_ptr
<JITType
>> create() {
259 if (auto Err
= impl().prepareForConstruction())
260 return std::move(Err
);
262 Error Err
= Error::success();
263 std::unique_ptr
<JITType
> J(new JITType(impl(), Err
));
265 return std::move(Err
);
270 SetterImpl
&impl() { return static_cast<SetterImpl
&>(*this); }
273 /// Constructs LLJIT instances.
275 : public LLJITBuilderState
,
276 public LLJITBuilderSetters
<LLJIT
, LLJITBuilder
, LLJITBuilderState
> {};
278 class LLLazyJITBuilderState
: public LLJITBuilderState
{
279 friend class LLLazyJIT
;
282 using IndirectStubsManagerBuilderFunction
=
283 std::function
<std::unique_ptr
<IndirectStubsManager
>()>;
286 JITTargetAddress LazyCompileFailureAddr
= 0;
287 std::unique_ptr
<LazyCallThroughManager
> LCTMgr
;
288 IndirectStubsManagerBuilderFunction ISMBuilder
;
290 Error
prepareForConstruction();
293 template <typename JITType
, typename SetterImpl
, typename State
>
294 class LLLazyJITBuilderSetters
295 : public LLJITBuilderSetters
<JITType
, SetterImpl
, State
> {
297 /// Set the address in the target address to call if a lazy compile fails.
299 /// If this method is not called then the value will default to 0.
300 SetterImpl
&setLazyCompileFailureAddr(JITTargetAddress Addr
) {
301 this->impl().LazyCompileFailureAddr
= Addr
;
305 /// Set the lazy-callthrough manager.
307 /// If this method is not called then a default, in-process lazy callthrough
308 /// manager for the host platform will be used.
310 setLazyCallthroughManager(std::unique_ptr
<LazyCallThroughManager
> LCTMgr
) {
311 this->impl().LCTMgr
= std::move(LCTMgr
);
315 /// Set the IndirectStubsManager builder function.
317 /// If this method is not called then a default, in-process
318 /// IndirectStubsManager builder for the host platform will be used.
319 SetterImpl
&setIndirectStubsManagerBuilder(
320 LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder
) {
321 this->impl().ISMBuilder
= std::move(ISMBuilder
);
326 /// Constructs LLLazyJIT instances.
327 class LLLazyJITBuilder
328 : public LLLazyJITBuilderState
,
329 public LLLazyJITBuilderSetters
<LLLazyJIT
, LLLazyJITBuilder
,
330 LLLazyJITBuilderState
> {};
332 } // End namespace orc
333 } // End namespace llvm
335 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H