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