[Orc] Rename IndirectStubsManagerBase to IndirectStubsManager.
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / IndirectionUtils.h
1 //===-- IndirectionUtils.h - Utilities for adding indirections --*- 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 details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Contains utilities for adding indirections and breaking up modules.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
15 #define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
16
17 #include "JITSymbol.h"
18 #include "LambdaResolver.h"
19 #include "llvm/ADT/DenseSet.h"
20 #include "llvm/ExecutionEngine/RuntimeDyld.h"
21 #include "llvm/IR/IRBuilder.h"
22 #include "llvm/IR/Mangler.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/Transforms/Utils/ValueMapper.h"
25 #include <sstream>
26
27 namespace llvm {
28 namespace orc {
29
30 /// @brief Target-independent base class for compile callback management.
31 class JITCompileCallbackManager {
32 public:
33
34   typedef std::function<TargetAddress()> CompileFtor;
35
36   /// @brief Handle to a newly created compile callback. Can be used to get an
37   ///        IR constant representing the address of the trampoline, and to set
38   ///        the compile action for the callback.
39   class CompileCallbackInfo {
40   public:
41     CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile)
42       : Addr(Addr), Compile(Compile) {}
43
44     TargetAddress getAddress() const { return Addr; }
45     void setCompileAction(CompileFtor Compile) {
46       this->Compile = std::move(Compile);
47     }
48   private:
49     TargetAddress Addr;
50     CompileFtor &Compile;
51   };
52
53   /// @brief Construct a JITCompileCallbackManager.
54   /// @param ErrorHandlerAddress The address of an error handler in the target
55   ///                            process to be used if a compile callback fails.
56   JITCompileCallbackManager(TargetAddress ErrorHandlerAddress)
57     : ErrorHandlerAddress(ErrorHandlerAddress) {}
58
59   virtual ~JITCompileCallbackManager() {}
60
61   /// @brief Execute the callback for the given trampoline id. Called by the JIT
62   ///        to compile functions on demand.
63   TargetAddress executeCompileCallback(TargetAddress TrampolineAddr) {
64     auto I = ActiveTrampolines.find(TrampolineAddr);
65     // FIXME: Also raise an error in the Orc error-handler when we finally have
66     //        one.
67     if (I == ActiveTrampolines.end())
68       return ErrorHandlerAddress;
69
70     // Found a callback handler. Yank this trampoline out of the active list and
71     // put it back in the available trampolines list, then try to run the
72     // handler's compile and update actions.
73     // Moving the trampoline ID back to the available list first means there's at
74     // least one available trampoline if the compile action triggers a request for
75     // a new one.
76     auto Compile = std::move(I->second);
77     ActiveTrampolines.erase(I);
78     AvailableTrampolines.push_back(TrampolineAddr);
79
80     if (auto Addr = Compile())
81       return Addr;
82
83     return ErrorHandlerAddress;
84   }
85
86   /// @brief Reserve a compile callback.
87   CompileCallbackInfo getCompileCallback() {
88     TargetAddress TrampolineAddr = getAvailableTrampolineAddr();
89     auto &Compile = this->ActiveTrampolines[TrampolineAddr];
90     return CompileCallbackInfo(TrampolineAddr, Compile);
91   }
92
93   /// @brief Get a CompileCallbackInfo for an existing callback.
94   CompileCallbackInfo getCompileCallbackInfo(TargetAddress TrampolineAddr) {
95     auto I = ActiveTrampolines.find(TrampolineAddr);
96     assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
97     return CompileCallbackInfo(I->first, I->second);
98   }
99
100   /// @brief Release a compile callback.
101   ///
102   ///   Note: Callbacks are auto-released after they execute. This method should
103   /// only be called to manually release a callback that is not going to
104   /// execute.
105   void releaseCompileCallback(TargetAddress TrampolineAddr) {
106     auto I = ActiveTrampolines.find(TrampolineAddr);
107     assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
108     ActiveTrampolines.erase(I);
109     AvailableTrampolines.push_back(TrampolineAddr);
110   }
111
112 protected:
113   TargetAddress ErrorHandlerAddress;
114
115   typedef std::map<TargetAddress, CompileFtor> TrampolineMapT;
116   TrampolineMapT ActiveTrampolines;
117   std::vector<TargetAddress> AvailableTrampolines;
118
119 private:
120
121   TargetAddress getAvailableTrampolineAddr() {
122     if (this->AvailableTrampolines.empty())
123       grow();
124     assert(!this->AvailableTrampolines.empty() &&
125            "Failed to grow available trampolines.");
126     TargetAddress TrampolineAddr = this->AvailableTrampolines.back();
127     this->AvailableTrampolines.pop_back();
128     return TrampolineAddr;
129   }
130
131   // Create new trampolines - to be implemented in subclasses.
132   virtual void grow() = 0;
133
134   virtual void anchor();
135 };
136
137 /// @brief Manage compile callbacks for in-process JITs.
138 template <typename TargetT>
139 class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
140 public:
141
142   /// @brief Construct a InProcessJITCompileCallbackManager.
143   /// @param ErrorHandlerAddress The address of an error handler in the target
144   ///                            process to be used if a compile callback fails.
145   LocalJITCompileCallbackManager(TargetAddress ErrorHandlerAddress)
146     : JITCompileCallbackManager(ErrorHandlerAddress) {
147
148     /// Set up the resolver block.
149     std::error_code EC;
150     ResolverBlock =
151       sys::OwningMemoryBlock(
152         sys::Memory::allocateMappedMemory(TargetT::ResolverCodeSize, nullptr,
153                                           sys::Memory::MF_READ |
154                                           sys::Memory::MF_WRITE, EC));
155     assert(!EC && "Failed to allocate resolver block");
156
157     TargetT::writeResolverCode(static_cast<uint8_t*>(ResolverBlock.base()),
158                                &reenter, this);
159
160     EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
161                                           sys::Memory::MF_READ |
162                                           sys::Memory::MF_EXEC);
163     assert(!EC && "Failed to mprotect resolver block");
164   }
165
166 private:
167
168   static TargetAddress reenter(void *CCMgr, void *TrampolineId) {
169     JITCompileCallbackManager *Mgr =
170       static_cast<JITCompileCallbackManager*>(CCMgr);
171     return Mgr->executeCompileCallback(
172              static_cast<TargetAddress>(
173                reinterpret_cast<uintptr_t>(TrampolineId)));
174   }
175
176   void grow() override {
177     assert(this->AvailableTrampolines.empty() && "Growing prematurely?");
178
179     std::error_code EC;
180     auto TrampolineBlock =
181       sys::OwningMemoryBlock(
182         sys::Memory::allocateMappedMemory(TargetT::PageSize, nullptr,
183                                           sys::Memory::MF_READ |
184                                           sys::Memory::MF_WRITE, EC));
185     assert(!EC && "Failed to allocate trampoline block");
186
187
188     unsigned NumTrampolines =
189       (TargetT::PageSize - TargetT::PointerSize) / TargetT::TrampolineSize;
190
191     uint8_t *TrampolineMem = static_cast<uint8_t*>(TrampolineBlock.base());
192     TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(),
193                               NumTrampolines);
194
195     for (unsigned I = 0; I < NumTrampolines; ++I)
196       this->AvailableTrampolines.push_back(
197         static_cast<TargetAddress>(
198           reinterpret_cast<uintptr_t>(
199                                       TrampolineMem + (I * TargetT::TrampolineSize))));
200
201     EC = sys::Memory::protectMappedMemory(TrampolineBlock.getMemoryBlock(),
202                                           sys::Memory::MF_READ |
203                                           sys::Memory::MF_EXEC);
204     assert(!EC && "Failed to mprotect trampoline block");
205
206     TrampolineBlocks.push_back(std::move(TrampolineBlock));
207   }
208
209   sys::OwningMemoryBlock ResolverBlock;
210   std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
211 };
212
213 /// @brief Base class for managing collections of named indirect stubs.
214 class IndirectStubsManager {
215 public:
216
217   /// @brief Map type for initializing the manager. See init.
218   typedef StringMap<std::pair<TargetAddress, JITSymbolFlags>> StubInitsMap;
219
220   virtual ~IndirectStubsManager() {}
221
222   /// @brief Create a single stub with the given name, target address and flags.
223   virtual std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
224                                      JITSymbolFlags StubFlags) = 0;
225
226   /// @brief Create StubInits.size() stubs with the given names, target
227   ///        addresses, and flags.
228   virtual std::error_code createStubs(const StubInitsMap &StubInits) = 0;
229
230   /// @brief Find the stub with the given name. If ExportedStubsOnly is true,
231   ///        this will only return a result if the stub's flags indicate that it
232   ///        is exported.
233   virtual JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
234
235   /// @brief Find the implementation-pointer for the stub.
236   virtual JITSymbol findPointer(StringRef Name) = 0;
237
238   /// @brief Change the value of the implementation pointer for the stub.
239   virtual std::error_code updatePointer(StringRef Name, TargetAddress NewAddr) = 0;
240 private:
241   virtual void anchor();
242 };
243
244 /// @brief IndirectStubsManager implementation for a concrete target, e.g.
245 ///        OrcX86_64. (See OrcTargetSupport.h).
246 template <typename TargetT>
247 class LocalIndirectStubsManager : public IndirectStubsManager {
248 public:
249
250   std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
251                              JITSymbolFlags StubFlags) override {
252     if (auto EC = reserveStubs(1))
253       return EC;
254
255     createStubInternal(StubName, StubAddr, StubFlags);
256
257     return std::error_code();
258   }
259
260   std::error_code createStubs(const StubInitsMap &StubInits) override {
261     if (auto EC = reserveStubs(StubInits.size()))
262       return EC;
263
264     for (auto &Entry : StubInits)
265       createStubInternal(Entry.first(), Entry.second.first,
266                          Entry.second.second);
267
268     return std::error_code();
269   }
270
271   JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
272     auto I = StubIndexes.find(Name);
273     if (I == StubIndexes.end())
274       return nullptr;
275     auto Key = I->second.first;
276     void *StubAddr = IndirectStubsInfos[Key.first].getStub(Key.second);
277     assert(StubAddr && "Missing stub address");
278     auto StubTargetAddr =
279       static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
280     auto StubSymbol = JITSymbol(StubTargetAddr, I->second.second);
281     if (ExportedStubsOnly && !StubSymbol.isExported())
282       return nullptr;
283     return StubSymbol;
284   }
285
286   JITSymbol findPointer(StringRef Name) override {
287     auto I = StubIndexes.find(Name);
288     if (I == StubIndexes.end())
289       return nullptr;
290     auto Key = I->second.first;
291     void *PtrAddr = IndirectStubsInfos[Key.first].getPtr(Key.second);
292     assert(PtrAddr && "Missing pointer address");
293     auto PtrTargetAddr =
294       static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
295     return JITSymbol(PtrTargetAddr, I->second.second);
296   }
297
298   std::error_code updatePointer(StringRef Name, TargetAddress NewAddr) override {
299     auto I = StubIndexes.find(Name);
300     assert(I != StubIndexes.end() && "No stub pointer for symbol");
301     auto Key = I->second.first;
302     *IndirectStubsInfos[Key.first].getPtr(Key.second) =
303       reinterpret_cast<void*>(static_cast<uintptr_t>(NewAddr));
304     return std::error_code();
305   }
306
307 private:
308
309   std::error_code reserveStubs(unsigned NumStubs) {
310     if (NumStubs <= FreeStubs.size())
311       return std::error_code();
312
313     unsigned NewStubsRequired = NumStubs - FreeStubs.size();
314     unsigned NewBlockId = IndirectStubsInfos.size();
315     typename TargetT::IndirectStubsInfo ISI;
316     if (auto EC = TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired,
317                                                   nullptr))
318       return EC;
319     for (unsigned I = 0; I < ISI.getNumStubs(); ++I)
320       FreeStubs.push_back(std::make_pair(NewBlockId, I));
321     IndirectStubsInfos.push_back(std::move(ISI));
322     return std::error_code();
323   }
324
325   void createStubInternal(StringRef StubName, TargetAddress InitAddr,
326                           JITSymbolFlags StubFlags) {
327     auto Key = FreeStubs.back();
328     FreeStubs.pop_back();
329     *IndirectStubsInfos[Key.first].getPtr(Key.second) =
330       reinterpret_cast<void*>(static_cast<uintptr_t>(InitAddr));
331     StubIndexes[StubName] = std::make_pair(Key, StubFlags);
332   }
333
334   std::vector<typename TargetT::IndirectStubsInfo> IndirectStubsInfos;
335   typedef std::pair<uint16_t, uint16_t> StubKey;
336   std::vector<StubKey> FreeStubs;
337   StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
338 };
339
340 /// @brief Build a function pointer of FunctionType with the given constant
341 ///        address.
342 ///
343 ///   Usage example: Turn a trampoline address into a function pointer constant
344 /// for use in a stub.
345 Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr);
346
347 /// @brief Create a function pointer with the given type, name, and initializer
348 ///        in the given Module.
349 GlobalVariable* createImplPointer(PointerType &PT, Module &M,
350                                   const Twine &Name, Constant *Initializer);
351
352 /// @brief Turn a function declaration into a stub function that makes an
353 ///        indirect call using the given function pointer.
354 void makeStub(Function &F, Value &ImplPointer);
355
356 /// @brief Raise linkage types and rename as necessary to ensure that all
357 ///        symbols are accessible for other modules.
358 ///
359 ///   This should be called before partitioning a module to ensure that the
360 /// partitions retain access to each other's symbols.
361 void makeAllSymbolsExternallyAccessible(Module &M);
362
363 /// @brief Clone a function declaration into a new module.
364 ///
365 ///   This function can be used as the first step towards creating a callback
366 /// stub (see makeStub), or moving a function body (see moveFunctionBody).
367 ///
368 ///   If the VMap argument is non-null, a mapping will be added between F and
369 /// the new declaration, and between each of F's arguments and the new
370 /// declaration's arguments. This map can then be passed in to moveFunction to
371 /// move the function body if required. Note: When moving functions between
372 /// modules with these utilities, all decls should be cloned (and added to a
373 /// single VMap) before any bodies are moved. This will ensure that references
374 /// between functions all refer to the versions in the new module.
375 Function* cloneFunctionDecl(Module &Dst, const Function &F,
376                             ValueToValueMapTy *VMap = nullptr);
377
378 /// @brief Move the body of function 'F' to a cloned function declaration in a
379 ///        different module (See related cloneFunctionDecl).
380 ///
381 ///   If the target function declaration is not supplied via the NewF parameter
382 /// then it will be looked up via the VMap.
383 ///
384 ///   This will delete the body of function 'F' from its original parent module,
385 /// but leave its declaration.
386 void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
387                       ValueMaterializer *Materializer = nullptr,
388                       Function *NewF = nullptr);
389
390 /// @brief Clone a global variable declaration into a new module.
391 GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
392                                         ValueToValueMapTy *VMap = nullptr);
393
394 /// @brief Move global variable GV from its parent module to cloned global
395 ///        declaration in a different module.
396 ///
397 ///   If the target global declaration is not supplied via the NewGV parameter
398 /// then it will be looked up via the VMap.
399 ///
400 ///   This will delete the initializer of GV from its original parent module,
401 /// but leave its declaration.
402 void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
403                                    ValueToValueMapTy &VMap,
404                                    ValueMaterializer *Materializer = nullptr,
405                                    GlobalVariable *NewGV = nullptr);
406
407 /// @brief Clone
408 GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
409                                   ValueToValueMapTy &VMap);
410
411 } // End namespace orc.
412 } // End namespace llvm.
413
414 #endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H