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 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 setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition)275 setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) { 276 CODLayer->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 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 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 & setExecutorProcessControl(std::unique_ptr<ExecutorProcessControl> EPC)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. setExecutionSession(std::unique_ptr<ExecutionSession> ES)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. setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB)359 SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) { 360 impl().JTMB = std::move(JTMB); 361 return impl(); 362 } 363 364 /// Return a reference to the JITTargetMachineBuilder. 365 /// getJITTargetMachineBuilder()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. setDataLayout(std::optional<DataLayout> DL)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. setLinkProcessSymbolsByDefault(bool LinkProcessSymbolsByDefault)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. setProcessSymbolsJITDylibSetup(LLJITBuilderState::ProcessSymbolsJITDylibSetupFunction SetupProcessSymbolsJITDylib)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. setObjectLinkingLayerCreator(LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer)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). setCompileFunctionCreator(LLJITBuilderState::CompileFunctionCreator CreateCompileFunction)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 & setPrePlatformSetup(unique_function<Error (LLJIT &)> PrePlatformSetup)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 & setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform)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. setNumCompileThreads(unsigned NumCompileThreads)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. setExecutorProcessControl(ExecutorProcessControl & EPC)463 SetterImpl &setExecutorProcessControl(ExecutorProcessControl &EPC) { 464 impl().EPC = &EPC; 465 return impl(); 466 } 467 468 /// Create an instance of the JIT. create()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: impl()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. setLazyCompileFailureAddr(ExecutorAddr Addr)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 & setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr)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. setIndirectStubsManagerBuilder(LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder)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. ExecutorNativePlatform(std::string OrcRuntimePath)552 ExecutorNativePlatform(std::string OrcRuntimePath) 553 : OrcRuntime(std::move(OrcRuntimePath)) {} 554 555 /// Set up using the given memory buffer. ExecutorNativePlatform(std::unique_ptr<MemoryBuffer> OrcRuntimeMB)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. addVCRuntime(std::string VCRuntimePath,bool StaticVCRuntime)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: ORCPlatformSupport(orc::LLJIT & J)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