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