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