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