]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / include / llvm / ExecutionEngine / Orc / LLJIT.h
1 //===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===//
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 // 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"
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"
25
26 namespace llvm {
27 namespace orc {
28
29 class LLJITBuilderState;
30 class LLLazyJITBuilderState;
31
32 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
33 ///
34 /// Create instances using LLJITBuilder.
35 class LLJIT {
36   template <typename, typename, typename> friend class LLJITBuilderSetters;
37
38 public:
39   static Expected<std::unique_ptr<LLJIT>> Create(LLJITBuilderState &S);
40
41   /// Destruct this instance. If a multi-threaded instance, waits for all
42   /// compile threads to complete.
43   ~LLJIT();
44
45   /// Returns the ExecutionSession for this instance.
46   ExecutionSession &getExecutionSession() { return *ES; }
47
48   /// Returns a reference to the DataLayout for this instance.
49   const DataLayout &getDataLayout() const { return DL; }
50
51   /// Returns a reference to the JITDylib representing the JIT'd main program.
52   JITDylib &getMainJITDylib() { return Main; }
53
54   /// 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
60   /// Create a new JITDylib with the given name and return a reference to it.
61   ///
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.
66   JITDylib &createJITDylib(std::string Name) {
67     return ES->createJITDylib(std::move(Name));
68   }
69
70   /// Convenience method for defining an absolute symbol.
71   Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
72
73   /// 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));
79   }
80
81   /// Adds an object file to the given JITDylib.
82   Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj);
83
84   /// 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
90   /// look up symbols based on their IR name use the lookup function instead).
91   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).
97   Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
98     return lookupLinkerMangled(Main, Name);
99   }
100
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));
104   }
105
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);
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
117   /// Returns a reference to the ObjLinkingLayer
118   ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }
119
120 protected:
121   static std::unique_ptr<ObjectLayer>
122   createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);
123
124   static Expected<IRCompileLayer::CompileFunction>
125   createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB);
126
127   /// Create an LLJIT instance with a single compile thread.
128   LLJIT(LLJITBuilderState &S, Error &Err);
129
130   std::string mangle(StringRef UnmangledName);
131
132   Error applyDataLayout(Module &M);
133
134   void recordCtorDtors(Module &M);
135
136   std::unique_ptr<ExecutionSession> ES;
137   JITDylib &Main;
138
139   DataLayout DL;
140   std::unique_ptr<ThreadPool> CompileThreads;
141
142   std::unique_ptr<ObjectLayer> ObjLinkingLayer;
143   std::unique_ptr<IRCompileLayer> CompileLayer;
144
145   CtorDtorRunner CtorRunner, DtorRunner;
146 };
147
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;
152
153 public:
154
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));
159   }
160
161   /// Sets the partition function.
162   void
163   setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) {
164     CODLayer->setPartitionFunction(std::move(Partition));
165   }
166
167   /// Add a module to be lazily compiled to JITDylib JD.
168   Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M);
169
170   /// Add a module to be lazily compiled to the main JITDylib.
171   Error addLazyIRModule(ThreadSafeModule M) {
172     return addLazyIRModule(Main, std::move(M));
173   }
174
175 private:
176
177   // Create a single-threaded LLLazyJIT instance.
178   LLLazyJIT(LLLazyJITBuilderState &S, Error &Err);
179
180   std::unique_ptr<LazyCallThroughManager> LCTMgr;
181   std::unique_ptr<IRTransformLayer> TransformLayer;
182   std::unique_ptr<CompileOnDemandLayer> CODLayer;
183 };
184
185 class LLJITBuilderState {
186 public:
187   using ObjectLinkingLayerCreator =
188       std::function<std::unique_ptr<ObjectLayer>(ExecutionSession &)>;
189
190   using CompileFunctionCreator =
191       std::function<Expected<IRCompileLayer::CompileFunction>(
192           JITTargetMachineBuilder JTMB)>;
193
194   std::unique_ptr<ExecutionSession> ES;
195   Optional<JITTargetMachineBuilder> JTMB;
196   ObjectLinkingLayerCreator CreateObjectLinkingLayer;
197   CompileFunctionCreator CreateCompileFunction;
198   unsigned NumCompileThreads = 0;
199
200   /// Called prior to JIT class construcion to fix up defaults.
201   Error prepareForConstruction();
202 };
203
204 template <typename JITType, typename SetterImpl, typename State>
205 class LLJITBuilderSetters {
206 public:
207   /// Set the JITTargetMachineBuilder for this instance.
208   ///
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);
213     return impl();
214   }
215
216   /// Return a reference to the JITTargetMachineBuilder.
217   ///
218   Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() {
219     return impl().JTMB;
220   }
221
222   /// Set an ObjectLinkingLayer creation function.
223   ///
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);
229     return impl();
230   }
231
232   /// Set a CompileFunctionCreator.
233   ///
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);
241     return impl();
242   }
243
244   /// Set the number of compile threads to use.
245   ///
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.
249   ///
250   /// If this method is not called, behavior will be as if it were called with
251   /// a zero argument.
252   SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) {
253     impl().NumCompileThreads = NumCompileThreads;
254     return impl();
255   }
256
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);
261
262     Error Err = Error::success();
263     std::unique_ptr<JITType> J(new JITType(impl(), Err));
264     if (Err)
265       return std::move(Err);
266     return std::move(J);
267   }
268
269 protected:
270   SetterImpl &impl() { return static_cast<SetterImpl &>(*this); }
271 };
272
273 /// Constructs LLJIT instances.
274 class LLJITBuilder
275     : public LLJITBuilderState,
276       public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {};
277
278 class LLLazyJITBuilderState : public LLJITBuilderState {
279   friend class LLLazyJIT;
280
281 public:
282   using IndirectStubsManagerBuilderFunction =
283       std::function<std::unique_ptr<IndirectStubsManager>()>;
284
285   Triple TT;
286   JITTargetAddress LazyCompileFailureAddr = 0;
287   std::unique_ptr<LazyCallThroughManager> LCTMgr;
288   IndirectStubsManagerBuilderFunction ISMBuilder;
289
290   Error prepareForConstruction();
291 };
292
293 template <typename JITType, typename SetterImpl, typename State>
294 class LLLazyJITBuilderSetters
295     : public LLJITBuilderSetters<JITType, SetterImpl, State> {
296 public:
297   /// Set the address in the target address to call if a lazy compile fails.
298   ///
299   /// If this method is not called then the value will default to 0.
300   SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) {
301     this->impl().LazyCompileFailureAddr = Addr;
302     return this->impl();
303   }
304
305   /// Set the lazy-callthrough manager.
306   ///
307   /// If this method is not called then a default, in-process lazy callthrough
308   /// manager for the host platform will be used.
309   SetterImpl &
310   setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) {
311     this->impl().LCTMgr = std::move(LCTMgr);
312     return this->impl();
313   }
314
315   /// Set the IndirectStubsManager builder function.
316   ///
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);
322     return this->impl();
323   }
324 };
325
326 /// Constructs LLLazyJIT instances.
327 class LLLazyJITBuilder
328     : public LLLazyJITBuilderState,
329       public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,
330                                      LLLazyJITBuilderState> {};
331
332 } // End namespace orc
333 } // End namespace llvm
334
335 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H