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