LLJIT.h revision 355940
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/ThreadPool.h" 25 26namespace llvm { 27namespace orc { 28 29class LLJITBuilderState; 30class LLLazyJITBuilderState; 31 32/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT. 33/// 34/// Create instances using LLJITBuilder. 35class LLJIT { 36 template <typename, typename, typename> friend class LLJITBuilderSetters; 37 38public: 39 static Expected<std::unique_ptr<LLJIT>> Create(LLJITBuilderState &S); 40 41 /// Destruct this instance. If a multi-threaded instance, waits for all 42 /// compile threads to complete. 43 ~LLJIT(); 44 45 /// Returns the ExecutionSession for this instance. 46 ExecutionSession &getExecutionSession() { return *ES; } 47 48 /// Returns a reference to the DataLayout for this instance. 49 const DataLayout &getDataLayout() const { return DL; } 50 51 /// Returns a reference to the JITDylib representing the JIT'd main program. 52 JITDylib &getMainJITDylib() { return Main; } 53 54 /// Returns the JITDylib with the given name, or nullptr if no JITDylib with 55 /// that name exists. 56 JITDylib *getJITDylibByName(StringRef Name) { 57 return ES->getJITDylibByName(Name); 58 } 59 60 /// Create a new JITDylib with the given name and return a reference to it. 61 /// 62 /// JITDylib names must be unique. If the given name is derived from user 63 /// input or elsewhere in the environment then the client should check 64 /// (e.g. by calling getJITDylibByName) that the given name is not already in 65 /// use. 66 JITDylib &createJITDylib(std::string Name) { 67 return ES->createJITDylib(std::move(Name)); 68 } 69 70 /// Convenience method for defining an absolute symbol. 71 Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address); 72 73 /// Adds an IR module to the given JITDylib. 74 Error addIRModule(JITDylib &JD, ThreadSafeModule TSM); 75 76 /// Adds an IR module to the Main JITDylib. 77 Error addIRModule(ThreadSafeModule TSM) { 78 return addIRModule(Main, std::move(TSM)); 79 } 80 81 /// Adds an object file to the given JITDylib. 82 Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj); 83 84 /// Adds an object file to the given JITDylib. 85 Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) { 86 return addObjectFile(Main, std::move(Obj)); 87 } 88 89 /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to 90 /// look up symbols based on their IR name use the lookup function instead). 91 Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD, 92 StringRef Name); 93 94 /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name 95 /// (to look up symbols based on their IR name use the lookup function 96 /// instead). 97 Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) { 98 return lookupLinkerMangled(Main, Name); 99 } 100 101 /// Look up a symbol in JITDylib JD based on its IR symbol name. 102 Expected<JITEvaluatedSymbol> lookup(JITDylib &JD, StringRef UnmangledName) { 103 return lookupLinkerMangled(JD, mangle(UnmangledName)); 104 } 105 106 /// Look up a symbol in the main JITDylib based on its IR symbol name. 107 Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) { 108 return lookup(Main, UnmangledName); 109 } 110 111 /// Runs all not-yet-run static constructors. 112 Error runConstructors() { return CtorRunner.run(); } 113 114 /// Runs all not-yet-run static destructors. 115 Error runDestructors() { return DtorRunner.run(); } 116 117 /// Returns a reference to the ObjLinkingLayer 118 ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; } 119 120protected: 121 static std::unique_ptr<ObjectLayer> 122 createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES); 123 124 static Expected<IRCompileLayer::CompileFunction> 125 createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB); 126 127 /// Create an LLJIT instance with a single compile thread. 128 LLJIT(LLJITBuilderState &S, Error &Err); 129 130 std::string mangle(StringRef UnmangledName); 131 132 Error applyDataLayout(Module &M); 133 134 void recordCtorDtors(Module &M); 135 136 std::unique_ptr<ExecutionSession> ES; 137 JITDylib &Main; 138 139 DataLayout DL; 140 std::unique_ptr<ThreadPool> CompileThreads; 141 142 std::unique_ptr<ObjectLayer> ObjLinkingLayer; 143 std::unique_ptr<IRCompileLayer> CompileLayer; 144 145 CtorDtorRunner CtorRunner, DtorRunner; 146}; 147 148/// An extended version of LLJIT that supports lazy function-at-a-time 149/// compilation of LLVM IR. 150class LLLazyJIT : public LLJIT { 151 template <typename, typename, typename> friend class LLJITBuilderSetters; 152 153public: 154 155 /// Set an IR transform (e.g. pass manager pipeline) to run on each function 156 /// when it is compiled. 157 void setLazyCompileTransform(IRTransformLayer::TransformFunction Transform) { 158 TransformLayer->setTransform(std::move(Transform)); 159 } 160 161 /// Sets the partition function. 162 void 163 setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) { 164 CODLayer->setPartitionFunction(std::move(Partition)); 165 } 166 167 /// Add a module to be lazily compiled to JITDylib JD. 168 Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M); 169 170 /// Add a module to be lazily compiled to the main JITDylib. 171 Error addLazyIRModule(ThreadSafeModule M) { 172 return addLazyIRModule(Main, std::move(M)); 173 } 174 175private: 176 177 // Create a single-threaded LLLazyJIT instance. 178 LLLazyJIT(LLLazyJITBuilderState &S, Error &Err); 179 180 std::unique_ptr<LazyCallThroughManager> LCTMgr; 181 std::unique_ptr<IRTransformLayer> TransformLayer; 182 std::unique_ptr<CompileOnDemandLayer> CODLayer; 183}; 184 185class LLJITBuilderState { 186public: 187 using ObjectLinkingLayerCreator = 188 std::function<std::unique_ptr<ObjectLayer>(ExecutionSession &)>; 189 190 using CompileFunctionCreator = 191 std::function<Expected<IRCompileLayer::CompileFunction>( 192 JITTargetMachineBuilder JTMB)>; 193 194 std::unique_ptr<ExecutionSession> ES; 195 Optional<JITTargetMachineBuilder> JTMB; 196 ObjectLinkingLayerCreator CreateObjectLinkingLayer; 197 CompileFunctionCreator CreateCompileFunction; 198 unsigned NumCompileThreads = 0; 199 200 /// Called prior to JIT class construcion to fix up defaults. 201 Error prepareForConstruction(); 202}; 203 204template <typename JITType, typename SetterImpl, typename State> 205class LLJITBuilderSetters { 206public: 207 /// Set the JITTargetMachineBuilder for this instance. 208 /// 209 /// If this method is not called, JITTargetMachineBuilder::detectHost will be 210 /// used to construct a default target machine builder for the host platform. 211 SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) { 212 impl().JTMB = std::move(JTMB); 213 return impl(); 214 } 215 216 /// Return a reference to the JITTargetMachineBuilder. 217 /// 218 Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() { 219 return impl().JTMB; 220 } 221 222 /// Set an ObjectLinkingLayer creation function. 223 /// 224 /// If this method is not called, a default creation function will be used 225 /// that will construct an RTDyldObjectLinkingLayer. 226 SetterImpl &setObjectLinkingLayerCreator( 227 LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) { 228 impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer); 229 return impl(); 230 } 231 232 /// Set a CompileFunctionCreator. 233 /// 234 /// If this method is not called, a default creation function wil be used 235 /// that will construct a basic IR compile function that is compatible with 236 /// the selected number of threads (SimpleCompiler for '0' compile threads, 237 /// ConcurrentIRCompiler otherwise). 238 SetterImpl &setCompileFunctionCreator( 239 LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) { 240 impl().CreateCompileFunction = std::move(CreateCompileFunction); 241 return impl(); 242 } 243 244 /// Set the number of compile threads to use. 245 /// 246 /// If set to zero, compilation will be performed on the execution thread when 247 /// JITing in-process. If set to any other number N, a thread pool of N 248 /// threads will be created for compilation. 249 /// 250 /// If this method is not called, behavior will be as if it were called with 251 /// a zero argument. 252 SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) { 253 impl().NumCompileThreads = NumCompileThreads; 254 return impl(); 255 } 256 257 /// Create an instance of the JIT. 258 Expected<std::unique_ptr<JITType>> create() { 259 if (auto Err = impl().prepareForConstruction()) 260 return std::move(Err); 261 262 Error Err = Error::success(); 263 std::unique_ptr<JITType> J(new JITType(impl(), Err)); 264 if (Err) 265 return std::move(Err); 266 return std::move(J); 267 } 268 269protected: 270 SetterImpl &impl() { return static_cast<SetterImpl &>(*this); } 271}; 272 273/// Constructs LLJIT instances. 274class LLJITBuilder 275 : public LLJITBuilderState, 276 public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {}; 277 278class LLLazyJITBuilderState : public LLJITBuilderState { 279 friend class LLLazyJIT; 280 281public: 282 using IndirectStubsManagerBuilderFunction = 283 std::function<std::unique_ptr<IndirectStubsManager>()>; 284 285 Triple TT; 286 JITTargetAddress LazyCompileFailureAddr = 0; 287 std::unique_ptr<LazyCallThroughManager> LCTMgr; 288 IndirectStubsManagerBuilderFunction ISMBuilder; 289 290 Error prepareForConstruction(); 291}; 292 293template <typename JITType, typename SetterImpl, typename State> 294class LLLazyJITBuilderSetters 295 : public LLJITBuilderSetters<JITType, SetterImpl, State> { 296public: 297 /// Set the address in the target address to call if a lazy compile fails. 298 /// 299 /// If this method is not called then the value will default to 0. 300 SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) { 301 this->impl().LazyCompileFailureAddr = Addr; 302 return this->impl(); 303 } 304 305 /// Set the lazy-callthrough manager. 306 /// 307 /// If this method is not called then a default, in-process lazy callthrough 308 /// manager for the host platform will be used. 309 SetterImpl & 310 setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) { 311 this->impl().LCTMgr = std::move(LCTMgr); 312 return this->impl(); 313 } 314 315 /// Set the IndirectStubsManager builder function. 316 /// 317 /// If this method is not called then a default, in-process 318 /// IndirectStubsManager builder for the host platform will be used. 319 SetterImpl &setIndirectStubsManagerBuilder( 320 LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) { 321 this->impl().ISMBuilder = std::move(ISMBuilder); 322 return this->impl(); 323 } 324}; 325 326/// Constructs LLLazyJIT instances. 327class LLLazyJITBuilder 328 : public LLLazyJITBuilderState, 329 public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder, 330 LLLazyJITBuilderState> {}; 331 332} // End namespace orc 333} // End namespace llvm 334 335#endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H 336