1 //===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for 3Bdetails.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // An ORC-based JIT for compiling LLVM IR.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
15 #define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
16 
17 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
18 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
19 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
20 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
21 #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
22 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
23 #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
24 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
25 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
26 #include "llvm/Support/ThreadPool.h"
27 
28 namespace llvm {
29 namespace orc {
30 
31 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
32 class LLJIT {
33 public:
34 
35   /// Destruct this instance. If a multi-threaded instance, waits for all
36   /// compile threads to complete.
37   ~LLJIT();
38 
39   /// Create an LLJIT instance.
40   /// If NumCompileThreads is not equal to zero, creates a multi-threaded
41   /// LLJIT with the given number of compile threads.
42   static Expected<std::unique_ptr<LLJIT>>
43   Create(JITTargetMachineBuilder JTMB, DataLayout DL,
44          unsigned NumCompileThreads = 0);
45 
46   /// Returns the ExecutionSession for this instance.
getExecutionSession()47   ExecutionSession &getExecutionSession() { return *ES; }
48 
49   /// Returns a reference to the JITDylib representing the JIT'd main program.
getMainJITDylib()50   JITDylib &getMainJITDylib() { return Main; }
51 
52   /// Create a new JITDylib with the given name and return a reference to it.
createJITDylib(std::string Name)53   JITDylib &createJITDylib(std::string Name) {
54     return ES->createJITDylib(std::move(Name));
55   }
56 
57   /// Convenience method for defining an absolute symbol.
58   Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
59 
60   /// Convenience method for defining an
61 
62   /// Adds an IR module to the given JITDylib.
63   Error addIRModule(JITDylib &JD, ThreadSafeModule TSM);
64 
65   /// Adds an IR module to the Main JITDylib.
addIRModule(ThreadSafeModule TSM)66   Error addIRModule(ThreadSafeModule TSM) {
67     return addIRModule(Main, std::move(TSM));
68   }
69 
70   /// Adds an object file to the given JITDylib.
71   Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj);
72 
73   /// Adds an object file to the given JITDylib.
addObjectFile(std::unique_ptr<MemoryBuffer> Obj)74   Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) {
75     return addObjectFile(Main, std::move(Obj));
76   }
77 
78   /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
79   /// look up symbols based on their IR name use the lookup function instead).
80   Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
81                                                    StringRef Name);
82 
83   /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name
84   /// (to look up symbols based on their IR name use the lookup function
85   /// instead).
lookupLinkerMangled(StringRef Name)86   Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
87     return lookupLinkerMangled(Main, Name);
88   }
89 
90   /// Look up a symbol in JITDylib JD based on its IR symbol name.
lookup(JITDylib & JD,StringRef UnmangledName)91   Expected<JITEvaluatedSymbol> lookup(JITDylib &JD, StringRef UnmangledName) {
92     return lookupLinkerMangled(JD, mangle(UnmangledName));
93   }
94 
95   /// Look up a symbol in the main JITDylib based on its IR symbol name.
lookup(StringRef UnmangledName)96   Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
97     return lookup(Main, UnmangledName);
98   }
99 
100   /// Runs all not-yet-run static constructors.
runConstructors()101   Error runConstructors() { return CtorRunner.run(); }
102 
103   /// Runs all not-yet-run static destructors.
runDestructors()104   Error runDestructors() { return DtorRunner.run(); }
105 
106   /// Returns a reference to the ObjLinkingLayer
getObjLinkingLayer()107   RTDyldObjectLinkingLayer &getObjLinkingLayer() { return ObjLinkingLayer; }
108 
109 protected:
110 
111   /// Create an LLJIT instance with a single compile thread.
112   LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
113         DataLayout DL);
114 
115   /// Create an LLJIT instance with multiple compile threads.
116   LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
117         DataLayout DL, unsigned NumCompileThreads);
118 
119   std::string mangle(StringRef UnmangledName);
120 
121   Error applyDataLayout(Module &M);
122 
123   void recordCtorDtors(Module &M);
124 
125   std::unique_ptr<ExecutionSession> ES;
126   JITDylib &Main;
127 
128   DataLayout DL;
129   std::unique_ptr<ThreadPool> CompileThreads;
130 
131   RTDyldObjectLinkingLayer ObjLinkingLayer;
132   IRCompileLayer CompileLayer;
133 
134   CtorDtorRunner CtorRunner, DtorRunner;
135 };
136 
137 /// An extended version of LLJIT that supports lazy function-at-a-time
138 /// compilation of LLVM IR.
139 class LLLazyJIT : public LLJIT {
140 public:
141 
142   /// Create an LLLazyJIT instance.
143   /// If NumCompileThreads is not equal to zero, creates a multi-threaded
144   /// LLLazyJIT with the given number of compile threads.
145   static Expected<std::unique_ptr<LLLazyJIT>>
146   Create(JITTargetMachineBuilder JTMB, DataLayout DL,
147          JITTargetAddress ErrorAddr, unsigned NumCompileThreads = 0);
148 
149   /// Set an IR transform (e.g. pass manager pipeline) to run on each function
150   /// when it is compiled.
setLazyCompileTransform(IRTransformLayer::TransformFunction Transform)151   void setLazyCompileTransform(IRTransformLayer::TransformFunction Transform) {
152     TransformLayer.setTransform(std::move(Transform));
153   }
154 
155   /// Sets the partition function.
156   void
setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition)157   setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) {
158     CODLayer.setPartitionFunction(std::move(Partition));
159   }
160 
161   /// Add a module to be lazily compiled to JITDylib JD.
162   Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M);
163 
164   /// Add a module to be lazily compiled to the main JITDylib.
addLazyIRModule(ThreadSafeModule M)165   Error addLazyIRModule(ThreadSafeModule M) {
166     return addLazyIRModule(Main, std::move(M));
167   }
168 
169 private:
170 
171   // Create a single-threaded LLLazyJIT instance.
172   LLLazyJIT(std::unique_ptr<ExecutionSession> ES,
173             std::unique_ptr<TargetMachine> TM, DataLayout DL,
174             std::unique_ptr<LazyCallThroughManager> LCTMgr,
175             std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
176 
177   // Create a multi-threaded LLLazyJIT instance.
178   LLLazyJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
179             DataLayout DL, unsigned NumCompileThreads,
180             std::unique_ptr<LazyCallThroughManager> LCTMgr,
181             std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
182 
183   std::unique_ptr<LazyCallThroughManager> LCTMgr;
184   std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder;
185 
186   IRTransformLayer TransformLayer;
187   CompileOnDemandLayer CODLayer;
188 };
189 
190 } // End namespace orc
191 } // End namespace llvm
192 
193 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H
194