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. |
63 | ExecutionSession &getExecutionSession() { return *ES; } |
64 | |
65 | /// Returns a reference to the triple for this instance. |
66 | const Triple &getTargetTriple() const { return TT; } |
67 | |
68 | /// Returns a reference to the DataLayout for this instance. |
69 | const DataLayout &getDataLayout() const { return DL; } |
70 | |
71 | /// Returns a reference to the JITDylib representing the JIT'd main program. |
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. |
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. |
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. |
140 | Error addIRModule(ThreadSafeModule TSM) { |
141 | return addIRModule(JD&: *Main, TSM: 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. |
151 | Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) { |
152 | return addObjectFile(JD&: *Main, Obj: 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). |
162 | Expected<ExecutorAddr> lookupLinkerMangled(JITDylib &JD, |
163 | StringRef Name) { |
164 | return lookupLinkerMangled(JD, Name: ES->intern(SymName: 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). |
170 | Expected<ExecutorAddr> lookupLinkerMangled(StringRef Name) { |
171 | return lookupLinkerMangled(JD&: *Main, Name); |
172 | } |
173 | |
174 | /// Look up a symbol in JITDylib JD based on its IR symbol name. |
175 | Expected<ExecutorAddr> lookup(JITDylib &JD, StringRef UnmangledName) { |
176 | return lookupLinkerMangled(JD, Name: mangle(UnmangledName)); |
177 | } |
178 | |
179 | /// Look up a symbol in the main JITDylib based on its IR symbol name. |
180 | Expected<ExecutorAddr> lookup(StringRef UnmangledName) { |
181 | return lookup(JD&: *Main, UnmangledName); |
182 | } |
183 | |
184 | /// Set the PlatformSupport instance. |
185 | void setPlatformSupport(std::unique_ptr<PlatformSupport> PS) { |
186 | this->PS = std::move(PS); |
187 | } |
188 | |
189 | /// Get the PlatformSupport instance. |
190 | PlatformSupport *getPlatformSupport() { return PS.get(); } |
191 | |
192 | /// Run the initializers for the given JITDylib. |
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. |
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 |
213 | ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; } |
214 | |
215 | /// Returns a reference to the object transform layer. |
216 | ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; } |
217 | |
218 | /// Returns a reference to the IR transform layer. |
219 | IRTransformLayer &getIRTransformLayer() { return *TransformLayer; } |
220 | |
221 | /// Returns a reference to the IR compile layer. |
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. |
228 | SymbolStringPtr mangleAndIntern(StringRef UnmangledName) const { |
229 | return ES->intern(SymName: 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 | std::unique_ptr<ThreadPool> CompileThreads; |
258 | |
259 | std::unique_ptr<ObjectLayer> ObjLinkingLayer; |
260 | std::unique_ptr<ObjectTransformLayer> ObjTransformLayer; |
261 | std::unique_ptr<IRCompileLayer> CompileLayer; |
262 | std::unique_ptr<IRTransformLayer> TransformLayer; |
263 | std::unique_ptr<IRTransformLayer> InitHelperTransformLayer; |
264 | }; |
265 | |
266 | /// An extended version of LLJIT that supports lazy function-at-a-time |
267 | /// compilation of LLVM IR. |
268 | class LLLazyJIT : public LLJIT { |
269 | template <typename, typename, typename> friend class LLJITBuilderSetters; |
270 | |
271 | public: |
272 | |
273 | /// Sets the partition function. |
274 | void |
275 | setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) { |
276 | CODLayer->setPartitionFunction(std::move(Partition)); |
277 | } |
278 | |
279 | /// Returns a reference to the on-demand layer. |
280 | CompileOnDemandLayer &getCompileOnDemandLayer() { return *CODLayer; } |
281 | |
282 | /// Add a module to be lazily compiled to JITDylib JD. |
283 | Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M); |
284 | |
285 | /// Add a module to be lazily compiled to the main JITDylib. |
286 | Error addLazyIRModule(ThreadSafeModule M) { |
287 | return addLazyIRModule(JD&: *Main, M: std::move(M)); |
288 | } |
289 | |
290 | private: |
291 | |
292 | // Create a single-threaded LLLazyJIT instance. |
293 | LLLazyJIT(LLLazyJITBuilderState &S, Error &Err); |
294 | |
295 | std::unique_ptr<LazyCallThroughManager> LCTMgr; |
296 | std::unique_ptr<CompileOnDemandLayer> CODLayer; |
297 | }; |
298 | |
299 | class LLJITBuilderState { |
300 | public: |
301 | using ObjectLinkingLayerCreator = |
302 | std::function<Expected<std::unique_ptr<ObjectLayer>>(ExecutionSession &, |
303 | const Triple &)>; |
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 | std::unique_ptr<ExecutorProcessControl> EPC; |
315 | std::unique_ptr<ExecutionSession> ES; |
316 | std::optional<JITTargetMachineBuilder> JTMB; |
317 | std::optional<DataLayout> DL; |
318 | bool LinkProcessSymbolsByDefault = true; |
319 | ProcessSymbolsJITDylibSetupFunction SetupProcessSymbolsJITDylib; |
320 | ObjectLinkingLayerCreator CreateObjectLinkingLayer; |
321 | CompileFunctionCreator CreateCompileFunction; |
322 | unique_function<Error(LLJIT &)> PrePlatformSetup; |
323 | PlatformSetupFunction SetUpPlatform; |
324 | unsigned NumCompileThreads = 0; |
325 | |
326 | /// Called prior to JIT class construcion to fix up defaults. |
327 | Error prepareForConstruction(); |
328 | }; |
329 | |
330 | template <typename JITType, typename SetterImpl, typename State> |
331 | class LLJITBuilderSetters { |
332 | public: |
333 | /// Set a ExecutorProcessControl for this instance. |
334 | /// This should not be called if ExecutionSession has already been set. |
335 | SetterImpl & |
336 | setExecutorProcessControl(std::unique_ptr<ExecutorProcessControl> EPC) { |
337 | assert( |
338 | !impl().ES && |
339 | "setExecutorProcessControl should not be called if an ExecutionSession " |
340 | "has already been set" ); |
341 | impl().EPC = std::move(EPC); |
342 | return impl(); |
343 | } |
344 | |
345 | /// Set an ExecutionSession for this instance. |
346 | SetterImpl &setExecutionSession(std::unique_ptr<ExecutionSession> ES) { |
347 | assert( |
348 | !impl().EPC && |
349 | "setExecutionSession should not be called if an ExecutorProcessControl " |
350 | "object has already been set" ); |
351 | impl().ES = std::move(ES); |
352 | return impl(); |
353 | } |
354 | |
355 | /// Set the JITTargetMachineBuilder for this instance. |
356 | /// |
357 | /// If this method is not called, JITTargetMachineBuilder::detectHost will be |
358 | /// used to construct a default target machine builder for the host platform. |
359 | SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) { |
360 | impl().JTMB = std::move(JTMB); |
361 | return impl(); |
362 | } |
363 | |
364 | /// Return a reference to the JITTargetMachineBuilder. |
365 | /// |
366 | std::optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() { |
367 | return impl().JTMB; |
368 | } |
369 | |
370 | /// Set a DataLayout for this instance. If no data layout is specified then |
371 | /// the target's default data layout will be used. |
372 | SetterImpl &setDataLayout(std::optional<DataLayout> DL) { |
373 | impl().DL = std::move(DL); |
374 | return impl(); |
375 | } |
376 | |
377 | /// The LinkProcessSymbolsDyDefault flag determines whether the "Process" |
378 | /// JITDylib will be added to the default link order at LLJIT construction |
379 | /// time. If true, the Process JITDylib will be added as the last item in the |
380 | /// default link order. If false (or if the Process JITDylib is disabled via |
381 | /// setProcessSymbolsJITDylibSetup) then the Process JITDylib will not appear |
382 | /// in the default link order. |
383 | SetterImpl &setLinkProcessSymbolsByDefault(bool LinkProcessSymbolsByDefault) { |
384 | impl().LinkProcessSymbolsByDefault = LinkProcessSymbolsByDefault; |
385 | return impl(); |
386 | } |
387 | |
388 | /// Set a setup function for the process symbols dylib. If not provided, |
389 | /// but LinkProcessSymbolsJITDylibByDefault is true, then the process-symbols |
390 | /// JITDylib will be configured with a DynamicLibrarySearchGenerator with a |
391 | /// default symbol filter. |
392 | SetterImpl &setProcessSymbolsJITDylibSetup( |
393 | LLJITBuilderState::ProcessSymbolsJITDylibSetupFunction |
394 | SetupProcessSymbolsJITDylib) { |
395 | impl().SetupProcessSymbolsJITDylib = std::move(SetupProcessSymbolsJITDylib); |
396 | return impl(); |
397 | } |
398 | |
399 | /// Set an ObjectLinkingLayer creation function. |
400 | /// |
401 | /// If this method is not called, a default creation function will be used |
402 | /// that will construct an RTDyldObjectLinkingLayer. |
403 | SetterImpl &setObjectLinkingLayerCreator( |
404 | LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) { |
405 | impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer); |
406 | return impl(); |
407 | } |
408 | |
409 | /// Set a CompileFunctionCreator. |
410 | /// |
411 | /// If this method is not called, a default creation function wil be used |
412 | /// that will construct a basic IR compile function that is compatible with |
413 | /// the selected number of threads (SimpleCompiler for '0' compile threads, |
414 | /// ConcurrentIRCompiler otherwise). |
415 | SetterImpl &setCompileFunctionCreator( |
416 | LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) { |
417 | impl().CreateCompileFunction = std::move(CreateCompileFunction); |
418 | return impl(); |
419 | } |
420 | |
421 | /// Set a setup function to be run just before the PlatformSetupFunction is |
422 | /// run. |
423 | /// |
424 | /// This can be used to customize the LLJIT instance before the platform is |
425 | /// set up. E.g. By installing a debugger support plugin before the platform |
426 | /// is set up (when the ORC runtime is loaded) we enable debugging of the |
427 | /// runtime itself. |
428 | SetterImpl & |
429 | setPrePlatformSetup(unique_function<Error(LLJIT &)> PrePlatformSetup) { |
430 | impl().PrePlatformSetup = std::move(PrePlatformSetup); |
431 | return impl(); |
432 | } |
433 | |
434 | /// Set up an PlatformSetupFunction. |
435 | /// |
436 | /// If this method is not called then setUpGenericLLVMIRPlatform |
437 | /// will be used to configure the JIT's platform support. |
438 | SetterImpl & |
439 | setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform) { |
440 | impl().SetUpPlatform = std::move(SetUpPlatform); |
441 | return impl(); |
442 | } |
443 | |
444 | /// Set the number of compile threads to use. |
445 | /// |
446 | /// If set to zero, compilation will be performed on the execution thread when |
447 | /// JITing in-process. If set to any other number N, a thread pool of N |
448 | /// threads will be created for compilation. |
449 | /// |
450 | /// If this method is not called, behavior will be as if it were called with |
451 | /// a zero argument. |
452 | SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) { |
453 | impl().NumCompileThreads = NumCompileThreads; |
454 | return impl(); |
455 | } |
456 | |
457 | /// Set an ExecutorProcessControl object. |
458 | /// |
459 | /// If the platform uses ObjectLinkingLayer by default and no |
460 | /// ObjectLinkingLayerCreator has been set then the ExecutorProcessControl |
461 | /// object will be used to supply the memory manager for the |
462 | /// ObjectLinkingLayer. |
463 | SetterImpl &setExecutorProcessControl(ExecutorProcessControl &EPC) { |
464 | impl().EPC = &EPC; |
465 | return impl(); |
466 | } |
467 | |
468 | /// Create an instance of the JIT. |
469 | Expected<std::unique_ptr<JITType>> create() { |
470 | if (auto Err = impl().prepareForConstruction()) |
471 | return std::move(Err); |
472 | |
473 | Error Err = Error::success(); |
474 | std::unique_ptr<JITType> J(new JITType(impl(), Err)); |
475 | if (Err) |
476 | return std::move(Err); |
477 | return std::move(J); |
478 | } |
479 | |
480 | protected: |
481 | SetterImpl &impl() { return static_cast<SetterImpl &>(*this); } |
482 | }; |
483 | |
484 | /// Constructs LLJIT instances. |
485 | class LLJITBuilder |
486 | : public LLJITBuilderState, |
487 | public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {}; |
488 | |
489 | class LLLazyJITBuilderState : public LLJITBuilderState { |
490 | friend class LLLazyJIT; |
491 | |
492 | public: |
493 | using IndirectStubsManagerBuilderFunction = |
494 | std::function<std::unique_ptr<IndirectStubsManager>()>; |
495 | |
496 | Triple TT; |
497 | ExecutorAddr LazyCompileFailureAddr; |
498 | std::unique_ptr<LazyCallThroughManager> LCTMgr; |
499 | IndirectStubsManagerBuilderFunction ISMBuilder; |
500 | |
501 | Error prepareForConstruction(); |
502 | }; |
503 | |
504 | template <typename JITType, typename SetterImpl, typename State> |
505 | class LLLazyJITBuilderSetters |
506 | : public LLJITBuilderSetters<JITType, SetterImpl, State> { |
507 | public: |
508 | /// Set the address in the target address to call if a lazy compile fails. |
509 | /// |
510 | /// If this method is not called then the value will default to 0. |
511 | SetterImpl &setLazyCompileFailureAddr(ExecutorAddr Addr) { |
512 | this->impl().LazyCompileFailureAddr = Addr; |
513 | return this->impl(); |
514 | } |
515 | |
516 | /// Set the lazy-callthrough manager. |
517 | /// |
518 | /// If this method is not called then a default, in-process lazy callthrough |
519 | /// manager for the host platform will be used. |
520 | SetterImpl & |
521 | setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) { |
522 | this->impl().LCTMgr = std::move(LCTMgr); |
523 | return this->impl(); |
524 | } |
525 | |
526 | /// Set the IndirectStubsManager builder function. |
527 | /// |
528 | /// If this method is not called then a default, in-process |
529 | /// IndirectStubsManager builder for the host platform will be used. |
530 | SetterImpl &setIndirectStubsManagerBuilder( |
531 | LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) { |
532 | this->impl().ISMBuilder = std::move(ISMBuilder); |
533 | return this->impl(); |
534 | } |
535 | }; |
536 | |
537 | /// Constructs LLLazyJIT instances. |
538 | class LLLazyJITBuilder |
539 | : public LLLazyJITBuilderState, |
540 | public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder, |
541 | LLLazyJITBuilderState> {}; |
542 | |
543 | /// Configure the LLJIT instance to use orc runtime support. This overload |
544 | /// assumes that the client has manually configured a Platform object. |
545 | Error setUpOrcPlatformManually(LLJIT &J); |
546 | |
547 | /// Configure the LLJIT instance to use the ORC runtime and the detected |
548 | /// native target for the executor. |
549 | class ExecutorNativePlatform { |
550 | public: |
551 | /// Set up using path to Orc runtime. |
552 | ExecutorNativePlatform(std::string OrcRuntimePath) |
553 | : OrcRuntime(std::move(OrcRuntimePath)) {} |
554 | |
555 | /// Set up using the given memory buffer. |
556 | ExecutorNativePlatform(std::unique_ptr<MemoryBuffer> OrcRuntimeMB) |
557 | : OrcRuntime(std::move(OrcRuntimeMB)) {} |
558 | |
559 | // TODO: add compiler-rt. |
560 | |
561 | /// Add a path to the VC runtime. |
562 | ExecutorNativePlatform &addVCRuntime(std::string VCRuntimePath, |
563 | bool StaticVCRuntime) { |
564 | VCRuntime = {std::move(VCRuntimePath), StaticVCRuntime}; |
565 | return *this; |
566 | } |
567 | |
568 | Expected<JITDylibSP> operator()(LLJIT &J); |
569 | |
570 | private: |
571 | std::variant<std::string, std::unique_ptr<MemoryBuffer>> OrcRuntime; |
572 | std::optional<std::pair<std::string, bool>> VCRuntime; |
573 | }; |
574 | |
575 | /// Configure the LLJIT instance to scrape modules for llvm.global_ctors and |
576 | /// llvm.global_dtors variables and (if present) build initialization and |
577 | /// deinitialization functions. Platform specific initialization configurations |
578 | /// should be preferred where available. |
579 | Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J); |
580 | |
581 | /// Configure the LLJIT instance to disable platform support explicitly. This is |
582 | /// useful in two cases: for platforms that don't have such requirements and for |
583 | /// platforms, that we have no explicit support yet and that don't work well |
584 | /// with the generic IR platform. |
585 | Expected<JITDylibSP> setUpInactivePlatform(LLJIT &J); |
586 | |
587 | /// A Platform-support class that implements initialize / deinitialize by |
588 | /// forwarding to ORC runtime dlopen / dlclose operations. |
589 | class ORCPlatformSupport : public LLJIT::PlatformSupport { |
590 | public: |
591 | ORCPlatformSupport(orc::LLJIT &J) : J(J) {} |
592 | Error initialize(orc::JITDylib &JD) override; |
593 | Error deinitialize(orc::JITDylib &JD) override; |
594 | |
595 | private: |
596 | orc::LLJIT &J; |
597 | DenseMap<orc::JITDylib *, orc::ExecutorAddr> DSOHandles; |
598 | }; |
599 | |
600 | } // End namespace orc |
601 | } // End namespace llvm |
602 | |
603 | #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H |
604 | |