xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
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/ThreadSafeModule.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/ThreadPool.h"
25 
26 namespace llvm {
27 namespace orc {
28 
29 class LLJITBuilderState;
30 class LLLazyJITBuilderState;
31 class ObjectTransformLayer;
32 class TargetProcessControl;
33 
34 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
35 ///
36 /// Create instances using LLJITBuilder.
37 class LLJIT {
38   template <typename, typename, typename> friend class LLJITBuilderSetters;
39 
40   friend void setUpGenericLLVMIRPlatform(LLJIT &J);
41 
42 public:
43   /// Initializer support for LLJIT.
44   class PlatformSupport {
45   public:
46     virtual ~PlatformSupport();
47 
48     virtual Error initialize(JITDylib &JD) = 0;
49 
50     virtual Error deinitialize(JITDylib &JD) = 0;
51 
52   protected:
53     static void setInitTransform(LLJIT &J,
54                                  IRTransformLayer::TransformFunction T);
55   };
56 
57   /// Destruct this instance. If a multi-threaded instance, waits for all
58   /// compile threads to complete.
59   ~LLJIT();
60 
61   /// Returns the ExecutionSession for this instance.
getExecutionSession()62   ExecutionSession &getExecutionSession() { return *ES; }
63 
64   /// Returns a reference to the triple for this instance.
getTargetTriple()65   const Triple &getTargetTriple() const { return TT; }
66 
67   /// Returns a reference to the DataLayout for this instance.
getDataLayout()68   const DataLayout &getDataLayout() const { return DL; }
69 
70   /// Returns a reference to the JITDylib representing the JIT'd main program.
getMainJITDylib()71   JITDylib &getMainJITDylib() { return *Main; }
72 
73   /// Returns the JITDylib with the given name, or nullptr if no JITDylib with
74   /// that name exists.
getJITDylibByName(StringRef Name)75   JITDylib *getJITDylibByName(StringRef Name) {
76     return ES->getJITDylibByName(Name);
77   }
78 
79   /// Create a new JITDylib with the given name and return a reference to it.
80   ///
81   /// JITDylib names must be unique. If the given name is derived from user
82   /// input or elsewhere in the environment then the client should check
83   /// (e.g. by calling getJITDylibByName) that the given name is not already in
84   /// use.
createJITDylib(std::string Name)85   Expected<JITDylib &> createJITDylib(std::string Name) {
86     return ES->createJITDylib(std::move(Name));
87   }
88 
89   /// Adds an IR module with the given ResourceTracker.
90   Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM);
91 
92   /// Adds an IR module to the given JITDylib.
93   Error addIRModule(JITDylib &JD, ThreadSafeModule TSM);
94 
95   /// Adds an IR module to the Main JITDylib.
addIRModule(ThreadSafeModule TSM)96   Error addIRModule(ThreadSafeModule TSM) {
97     return addIRModule(*Main, std::move(TSM));
98   }
99 
100   /// Adds an object file to the given JITDylib.
101   Error addObjectFile(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> Obj);
102 
103   /// Adds an object file to the given JITDylib.
104   Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj);
105 
106   /// Adds an object file to the given JITDylib.
addObjectFile(std::unique_ptr<MemoryBuffer> Obj)107   Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) {
108     return addObjectFile(*Main, std::move(Obj));
109   }
110 
111   /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
112   /// look up symbols based on their IR name use the lookup function instead).
113   Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
114                                                    SymbolStringPtr Name);
115 
116   /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
117   /// look up symbols based on their IR name use the lookup function instead).
lookupLinkerMangled(JITDylib & JD,StringRef Name)118   Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
119                                                    StringRef Name) {
120     return lookupLinkerMangled(JD, ES->intern(Name));
121   }
122 
123   /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name
124   /// (to look up symbols based on their IR name use the lookup function
125   /// instead).
lookupLinkerMangled(StringRef Name)126   Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
127     return lookupLinkerMangled(*Main, Name);
128   }
129 
130   /// Look up a symbol in JITDylib JD based on its IR symbol name.
lookup(JITDylib & JD,StringRef UnmangledName)131   Expected<JITEvaluatedSymbol> lookup(JITDylib &JD, StringRef UnmangledName) {
132     return lookupLinkerMangled(JD, mangle(UnmangledName));
133   }
134 
135   /// Look up a symbol in the main JITDylib based on its IR symbol name.
lookup(StringRef UnmangledName)136   Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
137     return lookup(*Main, UnmangledName);
138   }
139 
140   /// Set the PlatformSupport instance.
setPlatformSupport(std::unique_ptr<PlatformSupport> PS)141   void setPlatformSupport(std::unique_ptr<PlatformSupport> PS) {
142     this->PS = std::move(PS);
143   }
144 
145   /// Get the PlatformSupport instance.
getPlatformSupport()146   PlatformSupport *getPlatformSupport() { return PS.get(); }
147 
148   /// Run the initializers for the given JITDylib.
initialize(JITDylib & JD)149   Error initialize(JITDylib &JD) {
150     DEBUG_WITH_TYPE("orc", {
151       dbgs() << "LLJIT running initializers for JITDylib \"" << JD.getName()
152              << "\"\n";
153     });
154     assert(PS && "PlatformSupport must be set to run initializers.");
155     return PS->initialize(JD);
156   }
157 
158   /// Run the deinitializers for the given JITDylib.
deinitialize(JITDylib & JD)159   Error deinitialize(JITDylib &JD) {
160     DEBUG_WITH_TYPE("orc", {
161       dbgs() << "LLJIT running deinitializers for JITDylib \"" << JD.getName()
162              << "\"\n";
163     });
164     assert(PS && "PlatformSupport must be set to run initializers.");
165     return PS->deinitialize(JD);
166   }
167 
168   /// Returns a reference to the ObjLinkingLayer
getObjLinkingLayer()169   ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }
170 
171   /// Returns a reference to the object transform layer.
getObjTransformLayer()172   ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; }
173 
174   /// Returns a reference to the IR transform layer.
getIRTransformLayer()175   IRTransformLayer &getIRTransformLayer() { return *TransformLayer; }
176 
177   /// Returns a reference to the IR compile layer.
getIRCompileLayer()178   IRCompileLayer &getIRCompileLayer() { return *CompileLayer; }
179 
180   /// Returns a linker-mangled version of UnmangledName.
181   std::string mangle(StringRef UnmangledName) const;
182 
183   /// Returns an interned, linker-mangled version of UnmangledName.
mangleAndIntern(StringRef UnmangledName)184   SymbolStringPtr mangleAndIntern(StringRef UnmangledName) const {
185     return ES->intern(mangle(UnmangledName));
186   }
187 
188 protected:
189   static Expected<std::unique_ptr<ObjectLayer>>
190   createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);
191 
192   static Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>
193   createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB);
194 
195   /// Create an LLJIT instance with a single compile thread.
196   LLJIT(LLJITBuilderState &S, Error &Err);
197 
198   Error applyDataLayout(Module &M);
199 
200   void recordCtorDtors(Module &M);
201 
202   std::unique_ptr<ExecutionSession> ES;
203   std::unique_ptr<PlatformSupport> PS;
204 
205   JITDylib *Main = nullptr;
206 
207   DataLayout DL;
208   Triple TT;
209   std::unique_ptr<ThreadPool> CompileThreads;
210 
211   std::unique_ptr<ObjectLayer> ObjLinkingLayer;
212   std::unique_ptr<ObjectTransformLayer> ObjTransformLayer;
213   std::unique_ptr<IRCompileLayer> CompileLayer;
214   std::unique_ptr<IRTransformLayer> TransformLayer;
215   std::unique_ptr<IRTransformLayer> InitHelperTransformLayer;
216 };
217 
218 /// An extended version of LLJIT that supports lazy function-at-a-time
219 /// compilation of LLVM IR.
220 class LLLazyJIT : public LLJIT {
221   template <typename, typename, typename> friend class LLJITBuilderSetters;
222 
223 public:
224 
225   /// Sets the partition function.
226   void
setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition)227   setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) {
228     CODLayer->setPartitionFunction(std::move(Partition));
229   }
230 
231   /// Returns a reference to the on-demand layer.
getCompileOnDemandLayer()232   CompileOnDemandLayer &getCompileOnDemandLayer() { return *CODLayer; }
233 
234   /// Add a module to be lazily compiled to JITDylib JD.
235   Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M);
236 
237   /// Add a module to be lazily compiled to the main JITDylib.
addLazyIRModule(ThreadSafeModule M)238   Error addLazyIRModule(ThreadSafeModule M) {
239     return addLazyIRModule(*Main, std::move(M));
240   }
241 
242 private:
243 
244   // Create a single-threaded LLLazyJIT instance.
245   LLLazyJIT(LLLazyJITBuilderState &S, Error &Err);
246 
247   std::unique_ptr<LazyCallThroughManager> LCTMgr;
248   std::unique_ptr<CompileOnDemandLayer> CODLayer;
249 };
250 
251 class LLJITBuilderState {
252 public:
253   using ObjectLinkingLayerCreator =
254       std::function<Expected<std::unique_ptr<ObjectLayer>>(ExecutionSession &,
255                                                            const Triple &)>;
256 
257   using CompileFunctionCreator =
258       std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>(
259           JITTargetMachineBuilder JTMB)>;
260 
261   using PlatformSetupFunction = std::function<Error(LLJIT &J)>;
262 
263   std::unique_ptr<ExecutionSession> ES;
264   Optional<JITTargetMachineBuilder> JTMB;
265   Optional<DataLayout> DL;
266   ObjectLinkingLayerCreator CreateObjectLinkingLayer;
267   CompileFunctionCreator CreateCompileFunction;
268   PlatformSetupFunction SetUpPlatform;
269   unsigned NumCompileThreads = 0;
270   TargetProcessControl *TPC = nullptr;
271 
272   /// Called prior to JIT class construcion to fix up defaults.
273   Error prepareForConstruction();
274 };
275 
276 template <typename JITType, typename SetterImpl, typename State>
277 class LLJITBuilderSetters {
278 public:
279 
280   /// Set an ExecutionSession for this instance.
setExecutionSession(std::unique_ptr<ExecutionSession> ES)281   SetterImpl &setExecutionSession(std::unique_ptr<ExecutionSession> ES) {
282     impl().ES = std::move(ES);
283     return impl();
284   }
285 
286   /// Set the JITTargetMachineBuilder for this instance.
287   ///
288   /// If this method is not called, JITTargetMachineBuilder::detectHost will be
289   /// used to construct a default target machine builder for the host platform.
setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB)290   SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) {
291     impl().JTMB = std::move(JTMB);
292     return impl();
293   }
294 
295   /// Return a reference to the JITTargetMachineBuilder.
296   ///
getJITTargetMachineBuilder()297   Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() {
298     return impl().JTMB;
299   }
300 
301   /// Set a DataLayout for this instance. If no data layout is specified then
302   /// the target's default data layout will be used.
setDataLayout(Optional<DataLayout> DL)303   SetterImpl &setDataLayout(Optional<DataLayout> DL) {
304     impl().DL = std::move(DL);
305     return impl();
306   }
307 
308   /// Set an ObjectLinkingLayer creation function.
309   ///
310   /// If this method is not called, a default creation function will be used
311   /// that will construct an RTDyldObjectLinkingLayer.
setObjectLinkingLayerCreator(LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer)312   SetterImpl &setObjectLinkingLayerCreator(
313       LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) {
314     impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer);
315     return impl();
316   }
317 
318   /// Set a CompileFunctionCreator.
319   ///
320   /// If this method is not called, a default creation function wil be used
321   /// that will construct a basic IR compile function that is compatible with
322   /// the selected number of threads (SimpleCompiler for '0' compile threads,
323   /// ConcurrentIRCompiler otherwise).
setCompileFunctionCreator(LLJITBuilderState::CompileFunctionCreator CreateCompileFunction)324   SetterImpl &setCompileFunctionCreator(
325       LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) {
326     impl().CreateCompileFunction = std::move(CreateCompileFunction);
327     return impl();
328   }
329 
330   /// Set up an PlatformSetupFunction.
331   ///
332   /// If this method is not called then setUpGenericLLVMIRPlatform
333   /// will be used to configure the JIT's platform support.
334   SetterImpl &
setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform)335   setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform) {
336     impl().SetUpPlatform = std::move(SetUpPlatform);
337     return impl();
338   }
339 
340   /// Set the number of compile threads to use.
341   ///
342   /// If set to zero, compilation will be performed on the execution thread when
343   /// JITing in-process. If set to any other number N, a thread pool of N
344   /// threads will be created for compilation.
345   ///
346   /// If this method is not called, behavior will be as if it were called with
347   /// a zero argument.
setNumCompileThreads(unsigned NumCompileThreads)348   SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) {
349     impl().NumCompileThreads = NumCompileThreads;
350     return impl();
351   }
352 
353   /// Set a TargetProcessControl object.
354   ///
355   /// If the platform uses ObjectLinkingLayer by default and no
356   /// ObjectLinkingLayerCreator has been set then the TargetProcessControl
357   /// object will be used to supply the memory manager for the
358   /// ObjectLinkingLayer.
setTargetProcessControl(TargetProcessControl & TPC)359   SetterImpl &setTargetProcessControl(TargetProcessControl &TPC) {
360     impl().TPC = &TPC;
361     return impl();
362   }
363 
364   /// Create an instance of the JIT.
create()365   Expected<std::unique_ptr<JITType>> create() {
366     if (auto Err = impl().prepareForConstruction())
367       return std::move(Err);
368 
369     Error Err = Error::success();
370     std::unique_ptr<JITType> J(new JITType(impl(), Err));
371     if (Err)
372       return std::move(Err);
373     return std::move(J);
374   }
375 
376 protected:
impl()377   SetterImpl &impl() { return static_cast<SetterImpl &>(*this); }
378 };
379 
380 /// Constructs LLJIT instances.
381 class LLJITBuilder
382     : public LLJITBuilderState,
383       public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {};
384 
385 class LLLazyJITBuilderState : public LLJITBuilderState {
386   friend class LLLazyJIT;
387 
388 public:
389   using IndirectStubsManagerBuilderFunction =
390       std::function<std::unique_ptr<IndirectStubsManager>()>;
391 
392   Triple TT;
393   JITTargetAddress LazyCompileFailureAddr = 0;
394   std::unique_ptr<LazyCallThroughManager> LCTMgr;
395   IndirectStubsManagerBuilderFunction ISMBuilder;
396 
397   Error prepareForConstruction();
398 };
399 
400 template <typename JITType, typename SetterImpl, typename State>
401 class LLLazyJITBuilderSetters
402     : public LLJITBuilderSetters<JITType, SetterImpl, State> {
403 public:
404   /// Set the address in the target address to call if a lazy compile fails.
405   ///
406   /// If this method is not called then the value will default to 0.
setLazyCompileFailureAddr(JITTargetAddress Addr)407   SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) {
408     this->impl().LazyCompileFailureAddr = Addr;
409     return this->impl();
410   }
411 
412   /// Set the lazy-callthrough manager.
413   ///
414   /// If this method is not called then a default, in-process lazy callthrough
415   /// manager for the host platform will be used.
416   SetterImpl &
setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr)417   setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) {
418     this->impl().LCTMgr = std::move(LCTMgr);
419     return this->impl();
420   }
421 
422   /// Set the IndirectStubsManager builder function.
423   ///
424   /// If this method is not called then a default, in-process
425   /// IndirectStubsManager builder for the host platform will be used.
setIndirectStubsManagerBuilder(LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder)426   SetterImpl &setIndirectStubsManagerBuilder(
427       LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) {
428     this->impl().ISMBuilder = std::move(ISMBuilder);
429     return this->impl();
430   }
431 };
432 
433 /// Constructs LLLazyJIT instances.
434 class LLLazyJITBuilder
435     : public LLLazyJITBuilderState,
436       public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,
437                                      LLLazyJITBuilderState> {};
438 
439 /// Configure the LLJIT instance to scrape modules for llvm.global_ctors and
440 /// llvm.global_dtors variables and (if present) build initialization and
441 /// deinitialization functions. Platform specific initialization configurations
442 /// should be preferred where available.
443 void setUpGenericLLVMIRPlatform(LLJIT &J);
444 
445 /// Configure the LLJIT instance to use MachOPlatform support.
446 ///
447 /// Warning: MachOPlatform *requires* that LLJIT be configured to use
448 /// ObjectLinkingLayer (default on platforms supported by JITLink). If
449 /// MachOPlatform is used with RTDyldObjectLinkingLayer it will result in
450 /// undefined behavior).
451 ///
452 /// MachOPlatform installs an ObjectLinkingLayer plugin to scrape initializers
453 /// from the __mod_inits section. It also provides interposes for the dlfcn
454 /// functions (dlopen, dlclose, dlsym, dlerror) that work for JITDylibs as
455 /// well as regular libraries (JITDylibs will be preferenced, so make sure
456 /// your JITDylib names do not shadow any real library paths).
457 Error setUpMachOPlatform(LLJIT &J);
458 
459 /// Configure the LLJIT instance to disable platform support explicitly. This is
460 /// useful in two cases: for platforms that don't have such requirements and for
461 /// platforms, that we have no explicit support yet and that don't work well
462 /// with the generic IR platform.
463 Error setUpInactivePlatform(LLJIT &J);
464 
465 } // End namespace orc
466 } // End namespace llvm
467 
468 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H
469