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/Debug.h" 27 #include "llvm/Support/ThreadPool.h" 28 #include <variant> 29 30 namespace llvm { 31 namespace orc { 32 33 class LLJITBuilderState; 34 class LLLazyJITBuilderState; 35 class ObjectTransformLayer; 36 class ExecutorProcessControl; 37 38 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT. 39 /// 40 /// Create instances using LLJITBuilder. 41 class LLJIT { 42 template <typename, typename, typename> friend class LLJITBuilderSetters; 43 44 friend Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J); 45 46 public: 47 /// Initializer support for LLJIT. 48 class PlatformSupport { 49 public: 50 virtual ~PlatformSupport(); 51 52 virtual Error initialize(JITDylib &JD) = 0; 53 54 virtual Error deinitialize(JITDylib &JD) = 0; 55 56 protected: 57 static void setInitTransform(LLJIT &J, 58 IRTransformLayer::TransformFunction T); 59 }; 60 61 /// Destruct this instance. If a multi-threaded instance, waits for all 62 /// compile threads to complete. 63 virtual ~LLJIT(); 64 65 /// Returns the ExecutionSession for this instance. 66 ExecutionSession &getExecutionSession() { return *ES; } 67 68 /// Returns a reference to the triple for this instance. 69 const Triple &getTargetTriple() const { return TT; } 70 71 /// Returns a reference to the DataLayout for this instance. 72 const DataLayout &getDataLayout() const { return DL; } 73 74 /// Returns a reference to the JITDylib representing the JIT'd main program. 75 JITDylib &getMainJITDylib() { return *Main; } 76 77 /// Returns the ProcessSymbols JITDylib, which by default reflects non-JIT'd 78 /// symbols in the host process. 79 /// 80 /// Note: JIT'd code should not be added to the ProcessSymbols JITDylib. Use 81 /// the main JITDylib or a custom JITDylib instead. 82 JITDylibSP getProcessSymbolsJITDylib(); 83 84 /// Returns the Platform JITDylib, which will contain the ORC runtime (if 85 /// given) and any platform symbols. 86 /// 87 /// Note: JIT'd code should not be added to the Platform JITDylib. Use the 88 /// main JITDylib or a custom JITDylib instead. 89 JITDylibSP getPlatformJITDylib(); 90 91 /// Returns the JITDylib with the given name, or nullptr if no JITDylib with 92 /// that name exists. 93 JITDylib *getJITDylibByName(StringRef Name) { 94 return ES->getJITDylibByName(Name); 95 } 96 97 /// Load a (real) dynamic library and make its symbols available through a 98 /// new JITDylib with the same name. 99 /// 100 /// If the given *executor* path contains a valid platform dynamic library 101 /// then that library will be loaded, and a new bare JITDylib whose name is 102 /// the given path will be created to make the library's symbols available to 103 /// JIT'd code. 104 Expected<JITDylib &> loadPlatformDynamicLibrary(const char *Path); 105 106 /// Link a static library into the given JITDylib. 107 /// 108 /// If the given MemoryBuffer contains a valid static archive (or a universal 109 /// binary with an archive slice that fits the LLJIT instance's platform / 110 /// architecture) then it will be added to the given JITDylib using a 111 /// StaticLibraryDefinitionGenerator. 112 Error linkStaticLibraryInto(JITDylib &JD, 113 std::unique_ptr<MemoryBuffer> LibBuffer); 114 115 /// Link a static library into the given JITDylib. 116 /// 117 /// If the given *host* path contains a valid static archive (or a universal 118 /// binary with an archive slice that fits the LLJIT instance's platform / 119 /// architecture) then it will be added to the given JITDylib using a 120 /// StaticLibraryDefinitionGenerator. 121 Error linkStaticLibraryInto(JITDylib &JD, const char *Path); 122 123 /// Create a new JITDylib with the given name and return a reference to it. 124 /// 125 /// JITDylib names must be unique. If the given name is derived from user 126 /// input or elsewhere in the environment then the client should check 127 /// (e.g. by calling getJITDylibByName) that the given name is not already in 128 /// use. 129 Expected<JITDylib &> createJITDylib(std::string Name); 130 131 /// Returns the default link order for this LLJIT instance. This link order 132 /// will be appended to the link order of JITDylibs created by LLJIT's 133 /// createJITDylib method. 134 JITDylibSearchOrder defaultLinkOrder() { return DefaultLinks; } 135 136 /// Adds an IR module with the given ResourceTracker. 137 Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM); 138 139 /// Adds an IR module to the given JITDylib. 140 Error addIRModule(JITDylib &JD, ThreadSafeModule TSM); 141 142 /// Adds an IR module to the Main JITDylib. 143 Error addIRModule(ThreadSafeModule TSM) { 144 return addIRModule(*Main, std::move(TSM)); 145 } 146 147 /// Adds an object file to the given JITDylib. 148 Error addObjectFile(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> Obj); 149 150 /// Adds an object file to the given JITDylib. 151 Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj); 152 153 /// Adds an object file to the given JITDylib. 154 Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) { 155 return addObjectFile(*Main, std::move(Obj)); 156 } 157 158 /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to 159 /// look up symbols based on their IR name use the lookup function instead). 160 Expected<ExecutorAddr> lookupLinkerMangled(JITDylib &JD, 161 SymbolStringPtr Name); 162 163 /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to 164 /// look up symbols based on their IR name use the lookup function instead). 165 Expected<ExecutorAddr> lookupLinkerMangled(JITDylib &JD, 166 StringRef Name) { 167 return lookupLinkerMangled(JD, ES->intern(Name)); 168 } 169 170 /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name 171 /// (to look up symbols based on their IR name use the lookup function 172 /// instead). 173 Expected<ExecutorAddr> lookupLinkerMangled(StringRef Name) { 174 return lookupLinkerMangled(*Main, Name); 175 } 176 177 /// Look up a symbol in JITDylib JD based on its IR symbol name. 178 Expected<ExecutorAddr> lookup(JITDylib &JD, StringRef UnmangledName) { 179 return lookupLinkerMangled(JD, mangle(UnmangledName)); 180 } 181 182 /// Look up a symbol in the main JITDylib based on its IR symbol name. 183 Expected<ExecutorAddr> lookup(StringRef UnmangledName) { 184 return lookup(*Main, UnmangledName); 185 } 186 187 /// Set the PlatformSupport instance. 188 void setPlatformSupport(std::unique_ptr<PlatformSupport> PS) { 189 this->PS = std::move(PS); 190 } 191 192 /// Get the PlatformSupport instance. 193 PlatformSupport *getPlatformSupport() { return PS.get(); } 194 195 /// Run the initializers for the given JITDylib. 196 Error initialize(JITDylib &JD) { 197 DEBUG_WITH_TYPE("orc", { 198 dbgs() << "LLJIT running initializers for JITDylib \"" << JD.getName() 199 << "\"\n"; 200 }); 201 assert(PS && "PlatformSupport must be set to run initializers."); 202 return PS->initialize(JD); 203 } 204 205 /// Run the deinitializers for the given JITDylib. 206 Error deinitialize(JITDylib &JD) { 207 DEBUG_WITH_TYPE("orc", { 208 dbgs() << "LLJIT running deinitializers for JITDylib \"" << JD.getName() 209 << "\"\n"; 210 }); 211 assert(PS && "PlatformSupport must be set to run initializers."); 212 return PS->deinitialize(JD); 213 } 214 215 /// Returns a reference to the ObjLinkingLayer 216 ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; } 217 218 /// Returns a reference to the object transform layer. 219 ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; } 220 221 /// Returns a reference to the IR transform layer. 222 IRTransformLayer &getIRTransformLayer() { return *TransformLayer; } 223 224 /// Returns a reference to the IR compile layer. 225 IRCompileLayer &getIRCompileLayer() { return *CompileLayer; } 226 227 /// Returns a linker-mangled version of UnmangledName. 228 std::string mangle(StringRef UnmangledName) const; 229 230 /// Returns an interned, linker-mangled version of UnmangledName. 231 SymbolStringPtr mangleAndIntern(StringRef UnmangledName) const { 232 return ES->intern(mangle(UnmangledName)); 233 } 234 235 protected: 236 static Expected<std::unique_ptr<ObjectLayer>> 237 createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES); 238 239 static Expected<std::unique_ptr<IRCompileLayer::IRCompiler>> 240 createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB); 241 242 /// Create an LLJIT instance with a single compile thread. 243 LLJIT(LLJITBuilderState &S, Error &Err); 244 245 Error applyDataLayout(Module &M); 246 247 std::unique_ptr<ExecutionSession> ES; 248 std::unique_ptr<PlatformSupport> PS; 249 250 JITDylib *ProcessSymbols = nullptr; 251 JITDylib *Platform = nullptr; 252 JITDylib *Main = nullptr; 253 254 JITDylibSearchOrder DefaultLinks; 255 256 DataLayout DL; 257 Triple TT; 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 setPartitionFunction(IRPartitionLayer::PartitionFunction Partition) { 275 IPLayer->setPartitionFunction(std::move(Partition)); 276 } 277 278 /// Returns a reference to the on-demand layer. 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. 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<IRPartitionLayer> IPLayer; 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 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 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 & 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. 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. 363 SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) { 364 impl().JTMB = std::move(JTMB); 365 return impl(); 366 } 367 368 /// Return a reference to the JITTargetMachineBuilder. 369 /// 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. 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. 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. 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. 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). 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 & 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 & 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 & 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. 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. 483 SetterImpl &setSupportConcurrentCompilation( 484 std::optional<bool> SupportConcurrentCompilation) { 485 impl().SupportConcurrentCompilation = SupportConcurrentCompilation; 486 return impl(); 487 } 488 489 /// Create an instance of the JIT. 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: 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 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. 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 & 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. 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 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. 578 ExecutorNativePlatform(std::string OrcRuntimePath) 579 : OrcRuntime(std::move(OrcRuntimePath)) {} 580 581 /// Set up using the given memory buffer. 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. 588 ExecutorNativePlatform &addVCRuntime(std::string VCRuntimePath, 589 bool StaticVCRuntime) { 590 VCRuntime = {std::move(VCRuntimePath), StaticVCRuntime}; 591 return *this; 592 } 593 594 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 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 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 ORCPlatformSupport : public LLJIT::PlatformSupport { 616 public: 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