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