xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/ADT/SmallSet.h"
17 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
18 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
19 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
20 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
21 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
22 #include "llvm/ExecutionEngine/Orc/IRPartitionLayer.h"
23 #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
24 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
25 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
26 #include "llvm/Support/Compiler.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/ThreadPool.h"
29 #include <variant>
30 
31 namespace llvm {
32 namespace orc {
33 
34 class LLJITBuilderState;
35 class LLLazyJITBuilderState;
36 class ObjectTransformLayer;
37 class ExecutorProcessControl;
38 
39 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
40 ///
41 /// Create instances using LLJITBuilder.
42 class LLVM_ABI LLJIT {
43   template <typename, typename, typename> friend class LLJITBuilderSetters;
44 
45   LLVM_ABI friend Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J);
46 
47 public:
48   /// Initializer support for LLJIT.
49   class LLVM_ABI PlatformSupport {
50   public:
51     virtual ~PlatformSupport();
52 
53     virtual Error initialize(JITDylib &JD) = 0;
54 
55     virtual Error deinitialize(JITDylib &JD) = 0;
56 
57   protected:
58     static void setInitTransform(LLJIT &J,
59                                  IRTransformLayer::TransformFunction T);
60   };
61 
62   /// Destruct this instance. If a multi-threaded instance, waits for all
63   /// compile threads to complete.
64   virtual ~LLJIT();
65 
66   /// Returns the ExecutionSession for this instance.
getExecutionSession()67   ExecutionSession &getExecutionSession() { return *ES; }
68 
69   /// Returns a reference to the triple for this instance.
getTargetTriple()70   const Triple &getTargetTriple() const { return TT; }
71 
72   /// Returns a reference to the DataLayout for this instance.
getDataLayout()73   const DataLayout &getDataLayout() const { return DL; }
74 
75   /// Returns a reference to the JITDylib representing the JIT'd main program.
getMainJITDylib()76   JITDylib &getMainJITDylib() { return *Main; }
77 
78   /// Returns the ProcessSymbols JITDylib, which by default reflects non-JIT'd
79   /// symbols in the host process.
80   ///
81   /// Note: JIT'd code should not be added to the ProcessSymbols JITDylib. Use
82   /// the main JITDylib or a custom JITDylib instead.
83   JITDylibSP getProcessSymbolsJITDylib();
84 
85   /// Returns the Platform JITDylib, which will contain the ORC runtime (if
86   /// given) and any platform symbols.
87   ///
88   /// Note: JIT'd code should not be added to the Platform JITDylib. Use the
89   /// main JITDylib or a custom JITDylib instead.
90   JITDylibSP getPlatformJITDylib();
91 
92   /// Returns the JITDylib with the given name, or nullptr if no JITDylib with
93   /// that name exists.
getJITDylibByName(StringRef Name)94   JITDylib *getJITDylibByName(StringRef Name) {
95     return ES->getJITDylibByName(Name);
96   }
97 
98   /// Load a (real) dynamic library and make its symbols available through a
99   /// new JITDylib with the same name.
100   ///
101   /// If the given *executor* path contains a valid platform dynamic library
102   /// then that library will be loaded, and a new bare JITDylib whose name is
103   /// the given path will be created to make the library's symbols available to
104   /// JIT'd code.
105   Expected<JITDylib &> loadPlatformDynamicLibrary(const char *Path);
106 
107   /// Link a static library into the given JITDylib.
108   ///
109   /// If the given MemoryBuffer contains a valid static archive (or a universal
110   /// binary with an archive slice that fits the LLJIT instance's platform /
111   /// architecture) then it will be added to the given JITDylib using a
112   /// StaticLibraryDefinitionGenerator.
113   Error linkStaticLibraryInto(JITDylib &JD,
114                               std::unique_ptr<MemoryBuffer> LibBuffer);
115 
116   /// Link a static library into the given JITDylib.
117   ///
118   /// If the given *host* path contains a valid static archive (or a universal
119   /// binary with an archive slice that fits the LLJIT instance's platform /
120   /// architecture) then it will be added to the given JITDylib using a
121   /// StaticLibraryDefinitionGenerator.
122   Error linkStaticLibraryInto(JITDylib &JD, const char *Path);
123 
124   /// Create a new JITDylib with the given name and return a reference to it.
125   ///
126   /// JITDylib names must be unique. If the given name is derived from user
127   /// input or elsewhere in the environment then the client should check
128   /// (e.g. by calling getJITDylibByName) that the given name is not already in
129   /// use.
130   Expected<JITDylib &> createJITDylib(std::string Name);
131 
132   /// Returns the default link order for this LLJIT instance. This link order
133   /// will be appended to the link order of JITDylibs created by LLJIT's
134   /// createJITDylib method.
defaultLinkOrder()135   JITDylibSearchOrder defaultLinkOrder() { return DefaultLinks; }
136 
137   /// Adds an IR module with the given ResourceTracker.
138   Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM);
139 
140   /// Adds an IR module to the given JITDylib.
141   Error addIRModule(JITDylib &JD, ThreadSafeModule TSM);
142 
143   /// Adds an IR module to the Main JITDylib.
addIRModule(ThreadSafeModule TSM)144   Error addIRModule(ThreadSafeModule TSM) {
145     return addIRModule(*Main, std::move(TSM));
146   }
147 
148   /// Adds an object file to the given JITDylib.
149   Error addObjectFile(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> Obj);
150 
151   /// Adds an object file to the given JITDylib.
152   Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj);
153 
154   /// Adds an object file to the given JITDylib.
addObjectFile(std::unique_ptr<MemoryBuffer> Obj)155   Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) {
156     return addObjectFile(*Main, std::move(Obj));
157   }
158 
159   /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
160   /// look up symbols based on their IR name use the lookup function instead).
161   Expected<ExecutorAddr> lookupLinkerMangled(JITDylib &JD,
162                                              SymbolStringPtr Name);
163 
164   /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
165   /// look up symbols based on their IR name use the lookup function instead).
lookupLinkerMangled(JITDylib & JD,StringRef Name)166   Expected<ExecutorAddr> lookupLinkerMangled(JITDylib &JD,
167                                              StringRef Name) {
168     return lookupLinkerMangled(JD, ES->intern(Name));
169   }
170 
171   /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name
172   /// (to look up symbols based on their IR name use the lookup function
173   /// instead).
lookupLinkerMangled(StringRef Name)174   Expected<ExecutorAddr> lookupLinkerMangled(StringRef Name) {
175     return lookupLinkerMangled(*Main, Name);
176   }
177 
178   /// Look up a symbol in JITDylib JD based on its IR symbol name.
lookup(JITDylib & JD,StringRef UnmangledName)179   Expected<ExecutorAddr> lookup(JITDylib &JD, StringRef UnmangledName) {
180     return lookupLinkerMangled(JD, mangle(UnmangledName));
181   }
182 
183   /// Look up a symbol in the main JITDylib based on its IR symbol name.
lookup(StringRef UnmangledName)184   Expected<ExecutorAddr> lookup(StringRef UnmangledName) {
185     return lookup(*Main, UnmangledName);
186   }
187 
188   /// Set the PlatformSupport instance.
setPlatformSupport(std::unique_ptr<PlatformSupport> PS)189   void setPlatformSupport(std::unique_ptr<PlatformSupport> PS) {
190     this->PS = std::move(PS);
191   }
192 
193   /// Get the PlatformSupport instance.
getPlatformSupport()194   PlatformSupport *getPlatformSupport() { return PS.get(); }
195 
196   /// Run the initializers for the given JITDylib.
initialize(JITDylib & JD)197   Error initialize(JITDylib &JD) {
198     DEBUG_WITH_TYPE("orc", {
199       dbgs() << "LLJIT running initializers for JITDylib \"" << JD.getName()
200              << "\"\n";
201     });
202     assert(PS && "PlatformSupport must be set to run initializers.");
203     return PS->initialize(JD);
204   }
205 
206   /// Run the deinitializers for the given JITDylib.
deinitialize(JITDylib & JD)207   Error deinitialize(JITDylib &JD) {
208     DEBUG_WITH_TYPE("orc", {
209       dbgs() << "LLJIT running deinitializers for JITDylib \"" << JD.getName()
210              << "\"\n";
211     });
212     assert(PS && "PlatformSupport must be set to run initializers.");
213     return PS->deinitialize(JD);
214   }
215 
216   /// Returns a reference to the ObjLinkingLayer
getObjLinkingLayer()217   ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }
218 
219   /// Returns a reference to the object transform layer.
getObjTransformLayer()220   ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; }
221 
222   /// Returns a reference to the IR transform layer.
getIRTransformLayer()223   IRTransformLayer &getIRTransformLayer() { return *TransformLayer; }
224 
225   /// Returns a reference to the IR compile layer.
getIRCompileLayer()226   IRCompileLayer &getIRCompileLayer() { return *CompileLayer; }
227 
228   /// Returns a linker-mangled version of UnmangledName.
229   std::string mangle(StringRef UnmangledName) const;
230 
231   /// Returns an interned, linker-mangled version of UnmangledName.
mangleAndIntern(StringRef UnmangledName)232   SymbolStringPtr mangleAndIntern(StringRef UnmangledName) const {
233     return ES->intern(mangle(UnmangledName));
234   }
235 
236 protected:
237   static Expected<std::unique_ptr<ObjectLayer>>
238   createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);
239 
240   static Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>
241   createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB);
242 
243   /// Create an LLJIT instance with a single compile thread.
244   LLJIT(LLJITBuilderState &S, Error &Err);
245 
246   Error applyDataLayout(Module &M);
247 
248   std::unique_ptr<ExecutionSession> ES;
249   std::unique_ptr<PlatformSupport> PS;
250 
251   JITDylib *ProcessSymbols = nullptr;
252   JITDylib *Platform = nullptr;
253   JITDylib *Main = nullptr;
254 
255   JITDylibSearchOrder DefaultLinks;
256 
257   DataLayout DL;
258   Triple TT;
259 
260   std::unique_ptr<ObjectLayer> ObjLinkingLayer;
261   std::unique_ptr<ObjectTransformLayer> ObjTransformLayer;
262   std::unique_ptr<IRCompileLayer> CompileLayer;
263   std::unique_ptr<IRTransformLayer> TransformLayer;
264   std::unique_ptr<IRTransformLayer> InitHelperTransformLayer;
265 };
266 
267 /// An extended version of LLJIT that supports lazy function-at-a-time
268 /// compilation of LLVM IR.
269 class LLLazyJIT : public LLJIT {
270   template <typename, typename, typename> friend class LLJITBuilderSetters;
271 
272 public:
273 
274   /// Sets the partition function.
setPartitionFunction(IRPartitionLayer::PartitionFunction Partition)275   void setPartitionFunction(IRPartitionLayer::PartitionFunction Partition) {
276     IPLayer->setPartitionFunction(std::move(Partition));
277   }
278 
279   /// Returns a reference to the on-demand layer.
getCompileOnDemandLayer()280   CompileOnDemandLayer &getCompileOnDemandLayer() { return *CODLayer; }
281 
282   /// Add a module to be lazily compiled to JITDylib JD.
283   LLVM_ABI Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M);
284 
285   /// Add a module to be lazily compiled to the main JITDylib.
addLazyIRModule(ThreadSafeModule M)286   Error addLazyIRModule(ThreadSafeModule M) {
287     return addLazyIRModule(*Main, std::move(M));
288   }
289 
290 private:
291 
292   // Create a single-threaded LLLazyJIT instance.
293   LLVM_ABI LLLazyJIT(LLLazyJITBuilderState &S, Error &Err);
294 
295   std::unique_ptr<LazyCallThroughManager> LCTMgr;
296   std::unique_ptr<IRPartitionLayer> IPLayer;
297   std::unique_ptr<CompileOnDemandLayer> CODLayer;
298 };
299 
300 class LLJITBuilderState {
301 public:
302   using ObjectLinkingLayerCreator =
303       std::function<Expected<std::unique_ptr<ObjectLayer>>(ExecutionSession &)>;
304 
305   using CompileFunctionCreator =
306       std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>(
307           JITTargetMachineBuilder JTMB)>;
308 
309   using ProcessSymbolsJITDylibSetupFunction =
310       unique_function<Expected<JITDylibSP>(LLJIT &J)>;
311 
312   using PlatformSetupFunction = unique_function<Expected<JITDylibSP>(LLJIT &J)>;
313 
314   using NotifyCreatedFunction = std::function<Error(LLJIT &)>;
315 
316   std::unique_ptr<ExecutorProcessControl> EPC;
317   std::unique_ptr<ExecutionSession> ES;
318   std::optional<JITTargetMachineBuilder> JTMB;
319   std::optional<DataLayout> DL;
320   bool LinkProcessSymbolsByDefault = true;
321   ProcessSymbolsJITDylibSetupFunction SetupProcessSymbolsJITDylib;
322   ObjectLinkingLayerCreator CreateObjectLinkingLayer;
323   CompileFunctionCreator CreateCompileFunction;
324   unique_function<Error(LLJIT &)> PrePlatformSetup;
325   PlatformSetupFunction SetUpPlatform;
326   NotifyCreatedFunction NotifyCreated;
327   unsigned NumCompileThreads = 0;
328   std::optional<bool> SupportConcurrentCompilation;
329 
330   /// Called prior to JIT class construcion to fix up defaults.
331   LLVM_ABI Error prepareForConstruction();
332 };
333 
334 template <typename JITType, typename SetterImpl, typename State>
335 class LLJITBuilderSetters {
336 public:
337   /// Set an ExecutorProcessControl for this instance.
338   /// This should not be called if ExecutionSession has already been set.
339   SetterImpl &
setExecutorProcessControl(std::unique_ptr<ExecutorProcessControl> EPC)340   setExecutorProcessControl(std::unique_ptr<ExecutorProcessControl> EPC) {
341     assert(
342         !impl().ES &&
343         "setExecutorProcessControl should not be called if an ExecutionSession "
344         "has already been set");
345     impl().EPC = std::move(EPC);
346     return impl();
347   }
348 
349   /// Set an ExecutionSession for this instance.
setExecutionSession(std::unique_ptr<ExecutionSession> ES)350   SetterImpl &setExecutionSession(std::unique_ptr<ExecutionSession> ES) {
351     assert(
352         !impl().EPC &&
353         "setExecutionSession should not be called if an ExecutorProcessControl "
354         "object has already been set");
355     impl().ES = std::move(ES);
356     return impl();
357   }
358 
359   /// Set the JITTargetMachineBuilder for this instance.
360   ///
361   /// If this method is not called, JITTargetMachineBuilder::detectHost will be
362   /// used to construct a default target machine builder for the host platform.
setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB)363   SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) {
364     impl().JTMB = std::move(JTMB);
365     return impl();
366   }
367 
368   /// Return a reference to the JITTargetMachineBuilder.
369   ///
getJITTargetMachineBuilder()370   std::optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() {
371     return impl().JTMB;
372   }
373 
374   /// Set a DataLayout for this instance. If no data layout is specified then
375   /// the target's default data layout will be used.
setDataLayout(std::optional<DataLayout> DL)376   SetterImpl &setDataLayout(std::optional<DataLayout> DL) {
377     impl().DL = std::move(DL);
378     return impl();
379   }
380 
381   /// The LinkProcessSymbolsDyDefault flag determines whether the "Process"
382   /// JITDylib will be added to the default link order at LLJIT construction
383   /// time. If true, the Process JITDylib will be added as the last item in the
384   /// default link order. If false (or if the Process JITDylib is disabled via
385   /// setProcessSymbolsJITDylibSetup) then the Process JITDylib will not appear
386   /// in the default link order.
setLinkProcessSymbolsByDefault(bool LinkProcessSymbolsByDefault)387   SetterImpl &setLinkProcessSymbolsByDefault(bool LinkProcessSymbolsByDefault) {
388     impl().LinkProcessSymbolsByDefault = LinkProcessSymbolsByDefault;
389     return impl();
390   }
391 
392   /// Set a setup function for the process symbols dylib. If not provided,
393   /// but LinkProcessSymbolsJITDylibByDefault is true, then the process-symbols
394   /// JITDylib will be configured with a DynamicLibrarySearchGenerator with a
395   /// default symbol filter.
setProcessSymbolsJITDylibSetup(LLJITBuilderState::ProcessSymbolsJITDylibSetupFunction SetupProcessSymbolsJITDylib)396   SetterImpl &setProcessSymbolsJITDylibSetup(
397       LLJITBuilderState::ProcessSymbolsJITDylibSetupFunction
398           SetupProcessSymbolsJITDylib) {
399     impl().SetupProcessSymbolsJITDylib = std::move(SetupProcessSymbolsJITDylib);
400     return impl();
401   }
402 
403   /// Set an ObjectLinkingLayer creation function.
404   ///
405   /// If this method is not called, a default creation function will be used
406   /// that will construct an RTDyldObjectLinkingLayer.
setObjectLinkingLayerCreator(LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer)407   SetterImpl &setObjectLinkingLayerCreator(
408       LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) {
409     impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer);
410     return impl();
411   }
412 
413   /// Set a CompileFunctionCreator.
414   ///
415   /// If this method is not called, a default creation function wil be used
416   /// that will construct a basic IR compile function that is compatible with
417   /// the selected number of threads (SimpleCompiler for '0' compile threads,
418   /// ConcurrentIRCompiler otherwise).
setCompileFunctionCreator(LLJITBuilderState::CompileFunctionCreator CreateCompileFunction)419   SetterImpl &setCompileFunctionCreator(
420       LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) {
421     impl().CreateCompileFunction = std::move(CreateCompileFunction);
422     return impl();
423   }
424 
425   /// Set a setup function to be run just before the PlatformSetupFunction is
426   /// run.
427   ///
428   /// This can be used to customize the LLJIT instance before the platform is
429   /// set up. E.g. By installing a debugger support plugin before the platform
430   /// is set up (when the ORC runtime is loaded) we enable debugging of the
431   /// runtime itself.
432   SetterImpl &
setPrePlatformSetup(unique_function<Error (LLJIT &)> PrePlatformSetup)433   setPrePlatformSetup(unique_function<Error(LLJIT &)> PrePlatformSetup) {
434     impl().PrePlatformSetup = std::move(PrePlatformSetup);
435     return impl();
436   }
437 
438   /// Set up an PlatformSetupFunction.
439   ///
440   /// If this method is not called then setUpGenericLLVMIRPlatform
441   /// will be used to configure the JIT's platform support.
442   SetterImpl &
setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform)443   setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform) {
444     impl().SetUpPlatform = std::move(SetUpPlatform);
445     return impl();
446   }
447 
448   /// Set up a callback after successful construction of the JIT.
449   ///
450   /// This is useful to attach generators to JITDylibs or inject initial symbol
451   /// definitions.
452   SetterImpl &
setNotifyCreatedCallback(LLJITBuilderState::NotifyCreatedFunction Callback)453   setNotifyCreatedCallback(LLJITBuilderState::NotifyCreatedFunction Callback) {
454     impl().NotifyCreated = std::move(Callback);
455     return impl();
456   }
457 
458   /// Set the number of compile threads to use.
459   ///
460   /// If set to zero, compilation will be performed on the execution thread when
461   /// JITing in-process. If set to any other number N, a thread pool of N
462   /// threads will be created for compilation.
463   ///
464   /// If this method is not called, behavior will be as if it were called with
465   /// a zero argument.
466   ///
467   /// This setting should not be used if a custom ExecutionSession or
468   /// ExecutorProcessControl object is set: in those cases a custom
469   /// TaskDispatcher should be used instead.
setNumCompileThreads(unsigned NumCompileThreads)470   SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) {
471     impl().NumCompileThreads = NumCompileThreads;
472     return impl();
473   }
474 
475   /// If set, this forces LLJIT concurrent compilation support to be either on
476   /// or off. This controls the selection of compile function (concurrent vs
477   /// single threaded) and whether or not sub-modules are cloned to new
478   /// contexts for lazy emission.
479   ///
480   /// If not explicitly set then concurrency support will be turned on if
481   /// NumCompileThreads is set to a non-zero value, or if a custom
482   /// ExecutionSession or ExecutorProcessControl instance is provided.
setSupportConcurrentCompilation(std::optional<bool> SupportConcurrentCompilation)483   SetterImpl &setSupportConcurrentCompilation(
484       std::optional<bool> SupportConcurrentCompilation) {
485     impl().SupportConcurrentCompilation = SupportConcurrentCompilation;
486     return impl();
487   }
488 
489   /// Create an instance of the JIT.
create()490   Expected<std::unique_ptr<JITType>> create() {
491     if (auto Err = impl().prepareForConstruction())
492       return std::move(Err);
493 
494     Error Err = Error::success();
495     std::unique_ptr<JITType> J(new JITType(impl(), Err));
496     if (Err)
497       return std::move(Err);
498 
499     if (impl().NotifyCreated)
500       if (Error Err = impl().NotifyCreated(*J))
501         return std::move(Err);
502 
503     return std::move(J);
504   }
505 
506 protected:
impl()507   SetterImpl &impl() { return static_cast<SetterImpl &>(*this); }
508 };
509 
510 /// Constructs LLJIT instances.
511 class LLJITBuilder
512     : public LLJITBuilderState,
513       public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {};
514 
515 class LLLazyJITBuilderState : public LLJITBuilderState {
516   friend class LLLazyJIT;
517 
518 public:
519   using IndirectStubsManagerBuilderFunction =
520       std::function<std::unique_ptr<IndirectStubsManager>()>;
521 
522   Triple TT;
523   ExecutorAddr LazyCompileFailureAddr;
524   std::unique_ptr<LazyCallThroughManager> LCTMgr;
525   IndirectStubsManagerBuilderFunction ISMBuilder;
526 
527   LLVM_ABI Error prepareForConstruction();
528 };
529 
530 template <typename JITType, typename SetterImpl, typename State>
531 class LLLazyJITBuilderSetters
532     : public LLJITBuilderSetters<JITType, SetterImpl, State> {
533 public:
534   /// Set the address in the target address to call if a lazy compile fails.
535   ///
536   /// If this method is not called then the value will default to 0.
setLazyCompileFailureAddr(ExecutorAddr Addr)537   SetterImpl &setLazyCompileFailureAddr(ExecutorAddr Addr) {
538     this->impl().LazyCompileFailureAddr = Addr;
539     return this->impl();
540   }
541 
542   /// Set the lazy-callthrough manager.
543   ///
544   /// If this method is not called then a default, in-process lazy callthrough
545   /// manager for the host platform will be used.
546   SetterImpl &
setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr)547   setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) {
548     this->impl().LCTMgr = std::move(LCTMgr);
549     return this->impl();
550   }
551 
552   /// Set the IndirectStubsManager builder function.
553   ///
554   /// If this method is not called then a default, in-process
555   /// IndirectStubsManager builder for the host platform will be used.
setIndirectStubsManagerBuilder(LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder)556   SetterImpl &setIndirectStubsManagerBuilder(
557       LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) {
558     this->impl().ISMBuilder = std::move(ISMBuilder);
559     return this->impl();
560   }
561 };
562 
563 /// Constructs LLLazyJIT instances.
564 class LLLazyJITBuilder
565     : public LLLazyJITBuilderState,
566       public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,
567                                      LLLazyJITBuilderState> {};
568 
569 /// Configure the LLJIT instance to use orc runtime support. This overload
570 /// assumes that the client has manually configured a Platform object.
571 LLVM_ABI Error setUpOrcPlatformManually(LLJIT &J);
572 
573 /// Configure the LLJIT instance to use the ORC runtime and the detected
574 /// native target for the executor.
575 class ExecutorNativePlatform {
576 public:
577   /// Set up using path to Orc runtime.
ExecutorNativePlatform(std::string OrcRuntimePath)578   ExecutorNativePlatform(std::string OrcRuntimePath)
579       : OrcRuntime(std::move(OrcRuntimePath)) {}
580 
581   /// Set up using the given memory buffer.
ExecutorNativePlatform(std::unique_ptr<MemoryBuffer> OrcRuntimeMB)582   ExecutorNativePlatform(std::unique_ptr<MemoryBuffer> OrcRuntimeMB)
583       : OrcRuntime(std::move(OrcRuntimeMB)) {}
584 
585   // TODO: add compiler-rt.
586 
587   /// Add a path to the VC runtime.
addVCRuntime(std::string VCRuntimePath,bool StaticVCRuntime)588   ExecutorNativePlatform &addVCRuntime(std::string VCRuntimePath,
589                                        bool StaticVCRuntime) {
590     VCRuntime = {std::move(VCRuntimePath), StaticVCRuntime};
591     return *this;
592   }
593 
594   LLVM_ABI Expected<JITDylibSP> operator()(LLJIT &J);
595 
596 private:
597   std::variant<std::string, std::unique_ptr<MemoryBuffer>> OrcRuntime;
598   std::optional<std::pair<std::string, bool>> VCRuntime;
599 };
600 
601 /// Configure the LLJIT instance to scrape modules for llvm.global_ctors and
602 /// llvm.global_dtors variables and (if present) build initialization and
603 /// deinitialization functions. Platform specific initialization configurations
604 /// should be preferred where available.
605 LLVM_ABI Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J);
606 
607 /// Configure the LLJIT instance to disable platform support explicitly. This is
608 /// useful in two cases: for platforms that don't have such requirements and for
609 /// platforms, that we have no explicit support yet and that don't work well
610 /// with the generic IR platform.
611 LLVM_ABI Expected<JITDylibSP> setUpInactivePlatform(LLJIT &J);
612 
613 /// A Platform-support class that implements initialize / deinitialize by
614 /// forwarding to ORC runtime dlopen / dlclose operations.
615 class LLVM_ABI ORCPlatformSupport : public LLJIT::PlatformSupport {
616 public:
ORCPlatformSupport(orc::LLJIT & J)617   ORCPlatformSupport(orc::LLJIT &J) : J(J) {}
618   Error initialize(orc::JITDylib &JD) override;
619   Error deinitialize(orc::JITDylib &JD) override;
620 
621 private:
622   orc::LLJIT &J;
623   DenseMap<orc::JITDylib *, orc::ExecutorAddr> DSOHandles;
624   SmallPtrSet<JITDylib const *, 8> InitializedDylib;
625 };
626 
627 } // End namespace orc
628 } // End namespace llvm
629 
630 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H
631