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/ObjectTransformLayer.h" 23 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" 24 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/ThreadPool.h" 26 27 namespace llvm { 28 namespace orc { 29 30 class LLJITBuilderState; 31 class LLLazyJITBuilderState; 32 class TargetProcessControl; 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 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 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 = std::function<std::unique_ptr<ObjectLayer>( 254 ExecutionSession &, const Triple &TT)>; 255 256 using CompileFunctionCreator = 257 std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>( 258 JITTargetMachineBuilder JTMB)>; 259 260 using PlatformSetupFunction = std::function<Error(LLJIT &J)>; 261 262 std::unique_ptr<ExecutionSession> ES; 263 Optional<JITTargetMachineBuilder> JTMB; 264 Optional<DataLayout> DL; 265 ObjectLinkingLayerCreator CreateObjectLinkingLayer; 266 CompileFunctionCreator CreateCompileFunction; 267 PlatformSetupFunction SetUpPlatform; 268 unsigned NumCompileThreads = 0; 269 TargetProcessControl *TPC = nullptr; 270 271 /// Called prior to JIT class construcion to fix up defaults. 272 Error prepareForConstruction(); 273 }; 274 275 template <typename JITType, typename SetterImpl, typename State> 276 class LLJITBuilderSetters { 277 public: 278 279 /// Set an ExecutionSession for this instance. setExecutionSession(std::unique_ptr<ExecutionSession> ES)280 SetterImpl &setExecutionSession(std::unique_ptr<ExecutionSession> ES) { 281 impl().ES = std::move(ES); 282 return impl(); 283 } 284 285 /// Set the JITTargetMachineBuilder for this instance. 286 /// 287 /// If this method is not called, JITTargetMachineBuilder::detectHost will be 288 /// used to construct a default target machine builder for the host platform. setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB)289 SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) { 290 impl().JTMB = std::move(JTMB); 291 return impl(); 292 } 293 294 /// Return a reference to the JITTargetMachineBuilder. 295 /// getJITTargetMachineBuilder()296 Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() { 297 return impl().JTMB; 298 } 299 300 /// Set a DataLayout for this instance. If no data layout is specified then 301 /// the target's default data layout will be used. setDataLayout(Optional<DataLayout> DL)302 SetterImpl &setDataLayout(Optional<DataLayout> DL) { 303 impl().DL = std::move(DL); 304 return impl(); 305 } 306 307 /// Set an ObjectLinkingLayer creation function. 308 /// 309 /// If this method is not called, a default creation function will be used 310 /// that will construct an RTDyldObjectLinkingLayer. setObjectLinkingLayerCreator(LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer)311 SetterImpl &setObjectLinkingLayerCreator( 312 LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) { 313 impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer); 314 return impl(); 315 } 316 317 /// Set a CompileFunctionCreator. 318 /// 319 /// If this method is not called, a default creation function wil be used 320 /// that will construct a basic IR compile function that is compatible with 321 /// the selected number of threads (SimpleCompiler for '0' compile threads, 322 /// ConcurrentIRCompiler otherwise). setCompileFunctionCreator(LLJITBuilderState::CompileFunctionCreator CreateCompileFunction)323 SetterImpl &setCompileFunctionCreator( 324 LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) { 325 impl().CreateCompileFunction = std::move(CreateCompileFunction); 326 return impl(); 327 } 328 329 /// Set up an PlatformSetupFunction. 330 /// 331 /// If this method is not called then setUpGenericLLVMIRPlatform 332 /// will be used to configure the JIT's platform support. 333 SetterImpl & setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform)334 setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform) { 335 impl().SetUpPlatform = std::move(SetUpPlatform); 336 return impl(); 337 } 338 339 /// Set the number of compile threads to use. 340 /// 341 /// If set to zero, compilation will be performed on the execution thread when 342 /// JITing in-process. If set to any other number N, a thread pool of N 343 /// threads will be created for compilation. 344 /// 345 /// If this method is not called, behavior will be as if it were called with 346 /// a zero argument. setNumCompileThreads(unsigned NumCompileThreads)347 SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) { 348 impl().NumCompileThreads = NumCompileThreads; 349 return impl(); 350 } 351 352 /// Set a TargetProcessControl object. 353 /// 354 /// If the platform uses ObjectLinkingLayer by default and no 355 /// ObjectLinkingLayerCreator has been set then the TargetProcessControl 356 /// object will be used to supply the memory manager for the 357 /// ObjectLinkingLayer. setTargetProcessControl(TargetProcessControl & TPC)358 SetterImpl &setTargetProcessControl(TargetProcessControl &TPC) { 359 impl().TPC = &TPC; 360 return impl(); 361 } 362 363 /// Create an instance of the JIT. create()364 Expected<std::unique_ptr<JITType>> create() { 365 if (auto Err = impl().prepareForConstruction()) 366 return std::move(Err); 367 368 Error Err = Error::success(); 369 std::unique_ptr<JITType> J(new JITType(impl(), Err)); 370 if (Err) 371 return std::move(Err); 372 return std::move(J); 373 } 374 375 protected: impl()376 SetterImpl &impl() { return static_cast<SetterImpl &>(*this); } 377 }; 378 379 /// Constructs LLJIT instances. 380 class LLJITBuilder 381 : public LLJITBuilderState, 382 public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {}; 383 384 class LLLazyJITBuilderState : public LLJITBuilderState { 385 friend class LLLazyJIT; 386 387 public: 388 using IndirectStubsManagerBuilderFunction = 389 std::function<std::unique_ptr<IndirectStubsManager>()>; 390 391 Triple TT; 392 JITTargetAddress LazyCompileFailureAddr = 0; 393 std::unique_ptr<LazyCallThroughManager> LCTMgr; 394 IndirectStubsManagerBuilderFunction ISMBuilder; 395 396 Error prepareForConstruction(); 397 }; 398 399 template <typename JITType, typename SetterImpl, typename State> 400 class LLLazyJITBuilderSetters 401 : public LLJITBuilderSetters<JITType, SetterImpl, State> { 402 public: 403 /// Set the address in the target address to call if a lazy compile fails. 404 /// 405 /// If this method is not called then the value will default to 0. setLazyCompileFailureAddr(JITTargetAddress Addr)406 SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) { 407 this->impl().LazyCompileFailureAddr = Addr; 408 return this->impl(); 409 } 410 411 /// Set the lazy-callthrough manager. 412 /// 413 /// If this method is not called then a default, in-process lazy callthrough 414 /// manager for the host platform will be used. 415 SetterImpl & setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr)416 setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) { 417 this->impl().LCTMgr = std::move(LCTMgr); 418 return this->impl(); 419 } 420 421 /// Set the IndirectStubsManager builder function. 422 /// 423 /// If this method is not called then a default, in-process 424 /// IndirectStubsManager builder for the host platform will be used. setIndirectStubsManagerBuilder(LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder)425 SetterImpl &setIndirectStubsManagerBuilder( 426 LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) { 427 this->impl().ISMBuilder = std::move(ISMBuilder); 428 return this->impl(); 429 } 430 }; 431 432 /// Constructs LLLazyJIT instances. 433 class LLLazyJITBuilder 434 : public LLLazyJITBuilderState, 435 public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder, 436 LLLazyJITBuilderState> {}; 437 438 /// Configure the LLJIT instance to scrape modules for llvm.global_ctors and 439 /// llvm.global_dtors variables and (if present) build initialization and 440 /// deinitialization functions. Platform specific initialization configurations 441 /// should be preferred where available. 442 void setUpGenericLLVMIRPlatform(LLJIT &J); 443 444 /// Configure the LLJIT instance to use MachOPlatform support. 445 /// 446 /// Warning: MachOPlatform *requires* that LLJIT be configured to use 447 /// ObjectLinkingLayer (default on platforms supported by JITLink). If 448 /// MachOPlatform is used with RTDyldObjectLinkingLayer it will result in 449 /// undefined behavior). 450 /// 451 /// MachOPlatform installs an ObjectLinkingLayer plugin to scrape initializers 452 /// from the __mod_inits section. It also provides interposes for the dlfcn 453 /// functions (dlopen, dlclose, dlsym, dlerror) that work for JITDylibs as 454 /// well as regular libraries (JITDylibs will be preferenced, so make sure 455 /// your JITDylib names do not shadow any real library paths). 456 Error setUpMachOPlatform(LLJIT &J); 457 458 } // End namespace orc 459 } // End namespace llvm 460 461 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H 462