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 26 namespace llvm { 27 namespace orc { 28 29 class LLJITBuilderState; 30 class LLLazyJITBuilderState; 31 class ObjectTransformLayer; 32 class ExecutorProcessControl; 33 34 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT. 35 /// 36 /// Create instances using LLJITBuilder. 37 class LLJIT { 38 template <typename, typename, typename> friend class LLJITBuilderSetters; 39 40 friend void setUpGenericLLVMIRPlatform(LLJIT &J); 41 42 public: 43 /// Initializer support for LLJIT. 44 class PlatformSupport { 45 public: 46 virtual ~PlatformSupport(); 47 48 virtual Error initialize(JITDylib &JD) = 0; 49 50 virtual Error deinitialize(JITDylib &JD) = 0; 51 52 protected: 53 static void setInitTransform(LLJIT &J, 54 IRTransformLayer::TransformFunction T); 55 }; 56 57 /// Destruct this instance. If a multi-threaded instance, waits for all 58 /// compile threads to complete. 59 ~LLJIT(); 60 61 /// Returns the ExecutionSession for this instance. getExecutionSession()62 ExecutionSession &getExecutionSession() { return *ES; } 63 64 /// Returns a reference to the triple for this instance. getTargetTriple()65 const Triple &getTargetTriple() const { return TT; } 66 67 /// Returns a reference to the DataLayout for this instance. getDataLayout()68 const DataLayout &getDataLayout() const { return DL; } 69 70 /// Returns a reference to the JITDylib representing the JIT'd main program. getMainJITDylib()71 JITDylib &getMainJITDylib() { return *Main; } 72 73 /// Returns the JITDylib with the given name, or nullptr if no JITDylib with 74 /// that name exists. getJITDylibByName(StringRef Name)75 JITDylib *getJITDylibByName(StringRef Name) { 76 return ES->getJITDylibByName(Name); 77 } 78 79 /// Create a new JITDylib with the given name and return a reference to it. 80 /// 81 /// JITDylib names must be unique. If the given name is derived from user 82 /// input or elsewhere in the environment then the client should check 83 /// (e.g. by calling getJITDylibByName) that the given name is not already in 84 /// use. createJITDylib(std::string Name)85 Expected<JITDylib &> createJITDylib(std::string Name) { 86 return ES->createJITDylib(std::move(Name)); 87 } 88 89 /// Adds an IR module with the given ResourceTracker. 90 Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM); 91 92 /// Adds an IR module to the given JITDylib. 93 Error addIRModule(JITDylib &JD, ThreadSafeModule TSM); 94 95 /// Adds an IR module to the Main JITDylib. addIRModule(ThreadSafeModule TSM)96 Error addIRModule(ThreadSafeModule TSM) { 97 return addIRModule(*Main, std::move(TSM)); 98 } 99 100 /// Adds an object file to the given JITDylib. 101 Error addObjectFile(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> Obj); 102 103 /// Adds an object file to the given JITDylib. 104 Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj); 105 106 /// Adds an object file to the given JITDylib. addObjectFile(std::unique_ptr<MemoryBuffer> Obj)107 Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) { 108 return addObjectFile(*Main, std::move(Obj)); 109 } 110 111 /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to 112 /// look up symbols based on their IR name use the lookup function instead). 113 Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD, 114 SymbolStringPtr Name); 115 116 /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to 117 /// look up symbols based on their IR name use the lookup function instead). lookupLinkerMangled(JITDylib & JD,StringRef Name)118 Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD, 119 StringRef Name) { 120 return lookupLinkerMangled(JD, ES->intern(Name)); 121 } 122 123 /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name 124 /// (to look up symbols based on their IR name use the lookup function 125 /// instead). lookupLinkerMangled(StringRef Name)126 Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) { 127 return lookupLinkerMangled(*Main, Name); 128 } 129 130 /// Look up a symbol in JITDylib JD based on its IR symbol name. lookup(JITDylib & JD,StringRef UnmangledName)131 Expected<JITEvaluatedSymbol> lookup(JITDylib &JD, StringRef UnmangledName) { 132 return lookupLinkerMangled(JD, mangle(UnmangledName)); 133 } 134 135 /// Look up a symbol in the main JITDylib based on its IR symbol name. lookup(StringRef UnmangledName)136 Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) { 137 return lookup(*Main, UnmangledName); 138 } 139 140 /// Set the PlatformSupport instance. setPlatformSupport(std::unique_ptr<PlatformSupport> PS)141 void setPlatformSupport(std::unique_ptr<PlatformSupport> PS) { 142 this->PS = std::move(PS); 143 } 144 145 /// Get the PlatformSupport instance. getPlatformSupport()146 PlatformSupport *getPlatformSupport() { return PS.get(); } 147 148 /// Run the initializers for the given JITDylib. initialize(JITDylib & JD)149 Error initialize(JITDylib &JD) { 150 DEBUG_WITH_TYPE("orc", { 151 dbgs() << "LLJIT running initializers for JITDylib \"" << JD.getName() 152 << "\"\n"; 153 }); 154 assert(PS && "PlatformSupport must be set to run initializers."); 155 return PS->initialize(JD); 156 } 157 158 /// Run the deinitializers for the given JITDylib. deinitialize(JITDylib & JD)159 Error deinitialize(JITDylib &JD) { 160 DEBUG_WITH_TYPE("orc", { 161 dbgs() << "LLJIT running deinitializers for JITDylib \"" << JD.getName() 162 << "\"\n"; 163 }); 164 assert(PS && "PlatformSupport must be set to run initializers."); 165 return PS->deinitialize(JD); 166 } 167 168 /// Returns a reference to the ObjLinkingLayer getObjLinkingLayer()169 ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; } 170 171 /// Returns a reference to the object transform layer. getObjTransformLayer()172 ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; } 173 174 /// Returns a reference to the IR transform layer. getIRTransformLayer()175 IRTransformLayer &getIRTransformLayer() { return *TransformLayer; } 176 177 /// Returns a reference to the IR compile layer. getIRCompileLayer()178 IRCompileLayer &getIRCompileLayer() { return *CompileLayer; } 179 180 /// Returns a linker-mangled version of UnmangledName. 181 std::string mangle(StringRef UnmangledName) const; 182 183 /// Returns an interned, linker-mangled version of UnmangledName. mangleAndIntern(StringRef UnmangledName)184 SymbolStringPtr mangleAndIntern(StringRef UnmangledName) const { 185 return ES->intern(mangle(UnmangledName)); 186 } 187 188 protected: 189 static Expected<std::unique_ptr<ObjectLayer>> 190 createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES); 191 192 static Expected<std::unique_ptr<IRCompileLayer::IRCompiler>> 193 createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB); 194 195 /// Create an LLJIT instance with a single compile thread. 196 LLJIT(LLJITBuilderState &S, Error &Err); 197 198 Error applyDataLayout(Module &M); 199 200 void recordCtorDtors(Module &M); 201 202 std::unique_ptr<ExecutionSession> ES; 203 std::unique_ptr<PlatformSupport> PS; 204 205 JITDylib *Main = nullptr; 206 207 DataLayout DL; 208 Triple TT; 209 std::unique_ptr<ThreadPool> CompileThreads; 210 211 std::unique_ptr<ObjectLayer> ObjLinkingLayer; 212 std::unique_ptr<ObjectTransformLayer> ObjTransformLayer; 213 std::unique_ptr<IRCompileLayer> CompileLayer; 214 std::unique_ptr<IRTransformLayer> TransformLayer; 215 std::unique_ptr<IRTransformLayer> InitHelperTransformLayer; 216 }; 217 218 /// An extended version of LLJIT that supports lazy function-at-a-time 219 /// compilation of LLVM IR. 220 class LLLazyJIT : public LLJIT { 221 template <typename, typename, typename> friend class LLJITBuilderSetters; 222 223 public: 224 225 /// Sets the partition function. 226 void setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition)227 setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) { 228 CODLayer->setPartitionFunction(std::move(Partition)); 229 } 230 231 /// Returns a reference to the on-demand layer. getCompileOnDemandLayer()232 CompileOnDemandLayer &getCompileOnDemandLayer() { return *CODLayer; } 233 234 /// Add a module to be lazily compiled to JITDylib JD. 235 Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M); 236 237 /// Add a module to be lazily compiled to the main JITDylib. addLazyIRModule(ThreadSafeModule M)238 Error addLazyIRModule(ThreadSafeModule M) { 239 return addLazyIRModule(*Main, std::move(M)); 240 } 241 242 private: 243 244 // Create a single-threaded LLLazyJIT instance. 245 LLLazyJIT(LLLazyJITBuilderState &S, Error &Err); 246 247 std::unique_ptr<LazyCallThroughManager> LCTMgr; 248 std::unique_ptr<CompileOnDemandLayer> CODLayer; 249 }; 250 251 class LLJITBuilderState { 252 public: 253 using ObjectLinkingLayerCreator = 254 std::function<Expected<std::unique_ptr<ObjectLayer>>(ExecutionSession &, 255 const Triple &)>; 256 257 using CompileFunctionCreator = 258 std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>( 259 JITTargetMachineBuilder JTMB)>; 260 261 using PlatformSetupFunction = std::function<Error(LLJIT &J)>; 262 263 std::unique_ptr<ExecutorProcessControl> EPC; 264 std::unique_ptr<ExecutionSession> ES; 265 Optional<JITTargetMachineBuilder> JTMB; 266 Optional<DataLayout> DL; 267 ObjectLinkingLayerCreator CreateObjectLinkingLayer; 268 CompileFunctionCreator CreateCompileFunction; 269 PlatformSetupFunction SetUpPlatform; 270 unsigned NumCompileThreads = 0; 271 272 /// Called prior to JIT class construcion to fix up defaults. 273 Error prepareForConstruction(); 274 }; 275 276 template <typename JITType, typename SetterImpl, typename State> 277 class LLJITBuilderSetters { 278 public: 279 /// Set a ExecutorProcessControl for this instance. 280 /// This should not be called if ExecutionSession has already been set. 281 SetterImpl & setExecutorProcessControl(std::unique_ptr<ExecutorProcessControl> EPC)282 setExecutorProcessControl(std::unique_ptr<ExecutorProcessControl> EPC) { 283 assert( 284 !impl().ES && 285 "setExecutorProcessControl should not be called if an ExecutionSession " 286 "has already been set"); 287 impl().EPC = std::move(EPC); 288 return impl(); 289 } 290 291 /// Set an ExecutionSession for this instance. setExecutionSession(std::unique_ptr<ExecutionSession> ES)292 SetterImpl &setExecutionSession(std::unique_ptr<ExecutionSession> ES) { 293 impl().ES = std::move(ES); 294 return impl(); 295 } 296 297 /// Set the JITTargetMachineBuilder for this instance. 298 /// 299 /// If this method is not called, JITTargetMachineBuilder::detectHost will be 300 /// used to construct a default target machine builder for the host platform. setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB)301 SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) { 302 impl().JTMB = std::move(JTMB); 303 return impl(); 304 } 305 306 /// Return a reference to the JITTargetMachineBuilder. 307 /// getJITTargetMachineBuilder()308 Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() { 309 return impl().JTMB; 310 } 311 312 /// Set a DataLayout for this instance. If no data layout is specified then 313 /// the target's default data layout will be used. setDataLayout(Optional<DataLayout> DL)314 SetterImpl &setDataLayout(Optional<DataLayout> DL) { 315 impl().DL = std::move(DL); 316 return impl(); 317 } 318 319 /// Set an ObjectLinkingLayer creation function. 320 /// 321 /// If this method is not called, a default creation function will be used 322 /// that will construct an RTDyldObjectLinkingLayer. setObjectLinkingLayerCreator(LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer)323 SetterImpl &setObjectLinkingLayerCreator( 324 LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) { 325 impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer); 326 return impl(); 327 } 328 329 /// Set a CompileFunctionCreator. 330 /// 331 /// If this method is not called, a default creation function wil be used 332 /// that will construct a basic IR compile function that is compatible with 333 /// the selected number of threads (SimpleCompiler for '0' compile threads, 334 /// ConcurrentIRCompiler otherwise). setCompileFunctionCreator(LLJITBuilderState::CompileFunctionCreator CreateCompileFunction)335 SetterImpl &setCompileFunctionCreator( 336 LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) { 337 impl().CreateCompileFunction = std::move(CreateCompileFunction); 338 return impl(); 339 } 340 341 /// Set up an PlatformSetupFunction. 342 /// 343 /// If this method is not called then setUpGenericLLVMIRPlatform 344 /// will be used to configure the JIT's platform support. 345 SetterImpl & setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform)346 setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform) { 347 impl().SetUpPlatform = std::move(SetUpPlatform); 348 return impl(); 349 } 350 351 /// Set the number of compile threads to use. 352 /// 353 /// If set to zero, compilation will be performed on the execution thread when 354 /// JITing in-process. If set to any other number N, a thread pool of N 355 /// threads will be created for compilation. 356 /// 357 /// If this method is not called, behavior will be as if it were called with 358 /// a zero argument. setNumCompileThreads(unsigned NumCompileThreads)359 SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) { 360 impl().NumCompileThreads = NumCompileThreads; 361 return impl(); 362 } 363 364 /// Set an ExecutorProcessControl object. 365 /// 366 /// If the platform uses ObjectLinkingLayer by default and no 367 /// ObjectLinkingLayerCreator has been set then the ExecutorProcessControl 368 /// object will be used to supply the memory manager for the 369 /// ObjectLinkingLayer. setExecutorProcessControl(ExecutorProcessControl & EPC)370 SetterImpl &setExecutorProcessControl(ExecutorProcessControl &EPC) { 371 impl().EPC = &EPC; 372 return impl(); 373 } 374 375 /// Create an instance of the JIT. create()376 Expected<std::unique_ptr<JITType>> create() { 377 if (auto Err = impl().prepareForConstruction()) 378 return std::move(Err); 379 380 Error Err = Error::success(); 381 std::unique_ptr<JITType> J(new JITType(impl(), Err)); 382 if (Err) 383 return std::move(Err); 384 return std::move(J); 385 } 386 387 protected: impl()388 SetterImpl &impl() { return static_cast<SetterImpl &>(*this); } 389 }; 390 391 /// Constructs LLJIT instances. 392 class LLJITBuilder 393 : public LLJITBuilderState, 394 public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {}; 395 396 class LLLazyJITBuilderState : public LLJITBuilderState { 397 friend class LLLazyJIT; 398 399 public: 400 using IndirectStubsManagerBuilderFunction = 401 std::function<std::unique_ptr<IndirectStubsManager>()>; 402 403 Triple TT; 404 JITTargetAddress LazyCompileFailureAddr = 0; 405 std::unique_ptr<LazyCallThroughManager> LCTMgr; 406 IndirectStubsManagerBuilderFunction ISMBuilder; 407 408 Error prepareForConstruction(); 409 }; 410 411 template <typename JITType, typename SetterImpl, typename State> 412 class LLLazyJITBuilderSetters 413 : public LLJITBuilderSetters<JITType, SetterImpl, State> { 414 public: 415 /// Set the address in the target address to call if a lazy compile fails. 416 /// 417 /// If this method is not called then the value will default to 0. setLazyCompileFailureAddr(JITTargetAddress Addr)418 SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) { 419 this->impl().LazyCompileFailureAddr = Addr; 420 return this->impl(); 421 } 422 423 /// Set the lazy-callthrough manager. 424 /// 425 /// If this method is not called then a default, in-process lazy callthrough 426 /// manager for the host platform will be used. 427 SetterImpl & setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr)428 setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) { 429 this->impl().LCTMgr = std::move(LCTMgr); 430 return this->impl(); 431 } 432 433 /// Set the IndirectStubsManager builder function. 434 /// 435 /// If this method is not called then a default, in-process 436 /// IndirectStubsManager builder for the host platform will be used. setIndirectStubsManagerBuilder(LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder)437 SetterImpl &setIndirectStubsManagerBuilder( 438 LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) { 439 this->impl().ISMBuilder = std::move(ISMBuilder); 440 return this->impl(); 441 } 442 }; 443 444 /// Constructs LLLazyJIT instances. 445 class LLLazyJITBuilder 446 : public LLLazyJITBuilderState, 447 public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder, 448 LLLazyJITBuilderState> {}; 449 450 /// Configure the LLJIT instance to scrape modules for llvm.global_ctors and 451 /// llvm.global_dtors variables and (if present) build initialization and 452 /// deinitialization functions. Platform specific initialization configurations 453 /// should be preferred where available. 454 void setUpGenericLLVMIRPlatform(LLJIT &J); 455 456 /// Configure the LLJIT instance to disable platform support explicitly. This is 457 /// useful in two cases: for platforms that don't have such requirements and for 458 /// platforms, that we have no explicit support yet and that don't work well 459 /// with the generic IR platform. 460 Error setUpInactivePlatform(LLJIT &J); 461 462 } // End namespace orc 463 } // End namespace llvm 464 465 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H 466