Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 1 | //===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 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 |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 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" |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 21 | #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 22 | #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 23 | #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" |
| 24 | #include "llvm/Support/ThreadPool.h" |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 25 | |
| 26 | namespace llvm { |
| 27 | namespace orc { |
| 28 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 29 | class LLJITBuilderState; |
| 30 | class LLLazyJITBuilderState; |
| 31 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 32 | /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 33 | /// |
| 34 | /// Create instances using LLJITBuilder. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 35 | class LLJIT { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 36 | template <typename, typename, typename> friend class LLJITBuilderSetters; |
| 37 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 38 | public: |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 39 | static Expected<std::unique_ptr<LLJIT>> Create(LLJITBuilderState &S); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 40 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 41 | /// Destruct this instance. If a multi-threaded instance, waits for all |
| 42 | /// compile threads to complete. |
| 43 | ~LLJIT(); |
| 44 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 45 | /// Returns the ExecutionSession for this instance. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 46 | ExecutionSession &getExecutionSession() { return *ES; } |
| 47 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 48 | /// Returns a reference to the DataLayout for this instance. |
| 49 | const DataLayout &getDataLayout() const { return DL; } |
| 50 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 51 | /// Returns a reference to the JITDylib representing the JIT'd main program. |
| 52 | JITDylib &getMainJITDylib() { return Main; } |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 53 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 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 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 60 | /// Create a new JITDylib with the given name and return a reference to it. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 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. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 66 | JITDylib &createJITDylib(std::string Name) { |
| 67 | return ES->createJITDylib(std::move(Name)); |
| 68 | } |
| 69 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 70 | /// Convenience method for defining an absolute symbol. |
| 71 | Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address); |
| 72 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 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)); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 79 | } |
| 80 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 81 | /// Adds an object file to the given JITDylib. |
| 82 | Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 83 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 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 |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 90 | /// look up symbols based on their IR name use the lookup function instead). |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 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). |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 97 | Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) { |
| 98 | return lookupLinkerMangled(Main, Name); |
| 99 | } |
| 100 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 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)); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 104 | } |
| 105 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 106 | /// Look up a symbol in the main JITDylib based on its IR symbol name. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 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 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 117 | /// Returns a reference to the ObjLinkingLayer |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 118 | ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; } |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 119 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 120 | protected: |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 121 | static std::unique_ptr<ObjectLayer> |
| 122 | createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES); |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 123 | |
| 124 | /// Create an LLJIT instance with a single compile thread. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 125 | LLJIT(LLJITBuilderState &S, Error &Err); |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 126 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 127 | std::string mangle(StringRef UnmangledName); |
| 128 | |
| 129 | Error applyDataLayout(Module &M); |
| 130 | |
| 131 | void recordCtorDtors(Module &M); |
| 132 | |
| 133 | std::unique_ptr<ExecutionSession> ES; |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 134 | JITDylib &Main; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 135 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 136 | DataLayout DL; |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 137 | std::unique_ptr<ThreadPool> CompileThreads; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 138 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 139 | std::unique_ptr<ObjectLayer> ObjLinkingLayer; |
| 140 | std::unique_ptr<IRCompileLayer> CompileLayer; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 141 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 142 | CtorDtorRunner CtorRunner, DtorRunner; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 143 | }; |
| 144 | |
| 145 | /// An extended version of LLJIT that supports lazy function-at-a-time |
| 146 | /// compilation of LLVM IR. |
| 147 | class LLLazyJIT : public LLJIT { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 148 | template <typename, typename, typename> friend class LLJITBuilderSetters; |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 149 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 150 | public: |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 151 | |
| 152 | /// Set an IR transform (e.g. pass manager pipeline) to run on each function |
| 153 | /// when it is compiled. |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 154 | void setLazyCompileTransform(IRTransformLayer::TransformFunction Transform) { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 155 | TransformLayer->setTransform(std::move(Transform)); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 156 | } |
| 157 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 158 | /// Sets the partition function. |
| 159 | void |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 160 | setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 161 | CODLayer->setPartitionFunction(std::move(Partition)); |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 162 | } |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 163 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 164 | /// Add a module to be lazily compiled to JITDylib JD. |
| 165 | Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M); |
| 166 | |
| 167 | /// Add a module to be lazily compiled to the main JITDylib. |
| 168 | Error addLazyIRModule(ThreadSafeModule M) { |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 169 | return addLazyIRModule(Main, std::move(M)); |
| 170 | } |
| 171 | |
| 172 | private: |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 173 | |
| 174 | // Create a single-threaded LLLazyJIT instance. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 175 | LLLazyJIT(LLLazyJITBuilderState &S, Error &Err); |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 176 | |
| 177 | std::unique_ptr<LazyCallThroughManager> LCTMgr; |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 178 | std::unique_ptr<IRTransformLayer> TransformLayer; |
| 179 | std::unique_ptr<CompileOnDemandLayer> CODLayer; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 180 | }; |
| 181 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 182 | class LLJITBuilderState { |
| 183 | public: |
| 184 | using CreateObjectLinkingLayerFunction = |
| 185 | std::function<std::unique_ptr<ObjectLayer>(ExecutionSession &)>; |
| 186 | |
| 187 | std::unique_ptr<ExecutionSession> ES; |
| 188 | Optional<JITTargetMachineBuilder> JTMB; |
| 189 | CreateObjectLinkingLayerFunction CreateObjectLinkingLayer; |
| 190 | unsigned NumCompileThreads = 0; |
| 191 | |
| 192 | /// Called prior to JIT class construcion to fix up defaults. |
| 193 | Error prepareForConstruction(); |
| 194 | }; |
| 195 | |
| 196 | template <typename JITType, typename SetterImpl, typename State> |
| 197 | class LLJITBuilderSetters { |
| 198 | public: |
| 199 | /// Set the JITTargetMachineBuilder for this instance. |
| 200 | /// |
| 201 | /// If this method is not called, JITTargetMachineBuilder::detectHost will be |
| 202 | /// used to construct a default target machine builder for the host platform. |
| 203 | SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) { |
| 204 | impl().JTMB = std::move(JTMB); |
| 205 | return impl(); |
| 206 | } |
| 207 | |
| 208 | /// Return a reference to the JITTargetMachineBuilder. |
| 209 | /// |
| 210 | Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() { |
| 211 | return impl().JTMB; |
| 212 | } |
| 213 | |
| 214 | /// Set an ObjectLinkingLayer creation function. |
| 215 | /// |
| 216 | /// If this method is not called, a default creation function will be used |
| 217 | /// that will construct an RTDyldObjectLinkingLayer. |
| 218 | SetterImpl &setCreateObjectLinkingLayer( |
| 219 | LLJITBuilderState::CreateObjectLinkingLayerFunction |
| 220 | CreateObjectLinkingLayer) { |
| 221 | impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer); |
| 222 | return impl(); |
| 223 | } |
| 224 | |
| 225 | /// Set the number of compile threads to use. |
| 226 | /// |
| 227 | /// If set to zero, compilation will be performed on the execution thread when |
| 228 | /// JITing in-process. If set to any other number N, a thread pool of N |
| 229 | /// threads will be created for compilation. |
| 230 | /// |
| 231 | /// If this method is not called, behavior will be as if it were called with |
| 232 | /// a zero argument. |
| 233 | SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) { |
| 234 | impl().NumCompileThreads = NumCompileThreads; |
| 235 | return impl(); |
| 236 | } |
| 237 | |
| 238 | /// Create an instance of the JIT. |
| 239 | Expected<std::unique_ptr<JITType>> create() { |
| 240 | if (auto Err = impl().prepareForConstruction()) |
| 241 | return std::move(Err); |
| 242 | |
| 243 | Error Err = Error::success(); |
| 244 | std::unique_ptr<JITType> J(new JITType(impl(), Err)); |
| 245 | if (Err) |
| 246 | return std::move(Err); |
| 247 | return std::move(J); |
| 248 | } |
| 249 | |
| 250 | protected: |
| 251 | SetterImpl &impl() { return static_cast<SetterImpl &>(*this); } |
| 252 | }; |
| 253 | |
| 254 | /// Constructs LLJIT instances. |
| 255 | class LLJITBuilder |
| 256 | : public LLJITBuilderState, |
| 257 | public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {}; |
| 258 | |
| 259 | class LLLazyJITBuilderState : public LLJITBuilderState { |
| 260 | friend class LLLazyJIT; |
| 261 | |
| 262 | public: |
| 263 | using IndirectStubsManagerBuilderFunction = |
| 264 | std::function<std::unique_ptr<IndirectStubsManager>()>; |
| 265 | |
| 266 | Triple TT; |
| 267 | JITTargetAddress LazyCompileFailureAddr = 0; |
| 268 | std::unique_ptr<LazyCallThroughManager> LCTMgr; |
| 269 | IndirectStubsManagerBuilderFunction ISMBuilder; |
| 270 | |
| 271 | Error prepareForConstruction(); |
| 272 | }; |
| 273 | |
| 274 | template <typename JITType, typename SetterImpl, typename State> |
| 275 | class LLLazyJITBuilderSetters |
| 276 | : public LLJITBuilderSetters<JITType, SetterImpl, State> { |
| 277 | public: |
| 278 | /// Set the address in the target address to call if a lazy compile fails. |
| 279 | /// |
| 280 | /// If this method is not called then the value will default to 0. |
| 281 | SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) { |
| 282 | this->impl().LazyCompileFailureAddr = Addr; |
| 283 | return this->impl(); |
| 284 | } |
| 285 | |
| 286 | /// Set the lazy-callthrough manager. |
| 287 | /// |
| 288 | /// If this method is not called then a default, in-process lazy callthrough |
| 289 | /// manager for the host platform will be used. |
| 290 | SetterImpl & |
| 291 | setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) { |
| 292 | this->impl().LCTMgr = std::move(LCTMgr); |
| 293 | return this->impl(); |
| 294 | } |
| 295 | |
| 296 | /// Set the IndirectStubsManager builder function. |
| 297 | /// |
| 298 | /// If this method is not called then a default, in-process |
| 299 | /// IndirectStubsManager builder for the host platform will be used. |
| 300 | SetterImpl &setIndirectStubsManagerBuilder( |
| 301 | LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) { |
| 302 | this->impl().ISMBuilder = std::move(ISMBuilder); |
| 303 | return this->impl(); |
| 304 | } |
| 305 | }; |
| 306 | |
| 307 | /// Constructs LLLazyJIT instances. |
| 308 | class LLLazyJITBuilder |
| 309 | : public LLLazyJITBuilderState, |
| 310 | public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder, |
| 311 | LLLazyJITBuilderState> {}; |
| 312 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 313 | } // End namespace orc |
| 314 | } // End namespace llvm |
| 315 | |
| 316 | #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H |