]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[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 /// Base class for pools of compiler re-entry trampolines.
51 /// These trampolines are callable addresses that save all register state
52 /// before calling a supplied function to return the trampoline landing
53 /// address, then restore all state before jumping to that address. They
54 /// are used by various ORC APIs to support lazy compilation
55 class TrampolinePool {
56 public:
57   virtual ~TrampolinePool() {}
58
59   /// Get an available trampoline address.
60   /// Returns an error if no trampoline can be created.
61   virtual Expected<JITTargetAddress> getTrampoline() = 0;
62
63 private:
64   virtual void anchor();
65 };
66
67 /// A trampoline pool for trampolines within the current process.
68 template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool {
69 public:
70   using GetTrampolineLandingFunction =
71       std::function<JITTargetAddress(JITTargetAddress TrampolineAddr)>;
72
73   /// Creates a LocalTrampolinePool with the given RunCallback function.
74   /// Returns an error if this function is unable to correctly allocate, write
75   /// and protect the resolver code block.
76   static Expected<std::unique_ptr<LocalTrampolinePool>>
77   Create(GetTrampolineLandingFunction GetTrampolineLanding) {
78     Error Err = Error::success();
79
80     auto LTP = std::unique_ptr<LocalTrampolinePool>(
81         new LocalTrampolinePool(std::move(GetTrampolineLanding), Err));
82
83     if (Err)
84       return std::move(Err);
85     return std::move(LTP);
86   }
87
88   /// Get a free trampoline. Returns an error if one can not be provide (e.g.
89   /// because the pool is empty and can not be grown).
90   Expected<JITTargetAddress> getTrampoline() override {
91     std::lock_guard<std::mutex> Lock(LTPMutex);
92     if (AvailableTrampolines.empty()) {
93       if (auto Err = grow())
94         return std::move(Err);
95     }
96     assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
97     auto TrampolineAddr = AvailableTrampolines.back();
98     AvailableTrampolines.pop_back();
99     return TrampolineAddr;
100   }
101
102   /// Returns the given trampoline to the pool for re-use.
103   void releaseTrampoline(JITTargetAddress TrampolineAddr) {
104     std::lock_guard<std::mutex> Lock(LTPMutex);
105     AvailableTrampolines.push_back(TrampolineAddr);
106   }
107
108 private:
109   static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) {
110     LocalTrampolinePool<ORCABI> *TrampolinePool =
111         static_cast<LocalTrampolinePool *>(TrampolinePoolPtr);
112     return TrampolinePool->GetTrampolineLanding(static_cast<JITTargetAddress>(
113         reinterpret_cast<uintptr_t>(TrampolineId)));
114   }
115
116   LocalTrampolinePool(GetTrampolineLandingFunction GetTrampolineLanding,
117                       Error &Err)
118       : GetTrampolineLanding(std::move(GetTrampolineLanding)) {
119
120     ErrorAsOutParameter _(&Err);
121
122     /// Try to set up the resolver block.
123     std::error_code EC;
124     ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
125         ORCABI::ResolverCodeSize, nullptr,
126         sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
127     if (EC) {
128       Err = errorCodeToError(EC);
129       return;
130     }
131
132     ORCABI::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
133                               &reenter, this);
134
135     EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
136                                           sys::Memory::MF_READ |
137                                               sys::Memory::MF_EXEC);
138     if (EC) {
139       Err = errorCodeToError(EC);
140       return;
141     }
142   }
143
144   Error grow() {
145     assert(this->AvailableTrampolines.empty() && "Growing prematurely?");
146
147     std::error_code EC;
148     auto TrampolineBlock =
149         sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
150             sys::Process::getPageSize(), nullptr,
151             sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
152     if (EC)
153       return errorCodeToError(EC);
154
155     unsigned NumTrampolines =
156         (sys::Process::getPageSize() - ORCABI::PointerSize) /
157         ORCABI::TrampolineSize;
158
159     uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
160     ORCABI::writeTrampolines(TrampolineMem, ResolverBlock.base(),
161                              NumTrampolines);
162
163     for (unsigned I = 0; I < NumTrampolines; ++I)
164       this->AvailableTrampolines.push_back(
165           static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(
166               TrampolineMem + (I * ORCABI::TrampolineSize))));
167
168     if (auto EC = sys::Memory::protectMappedMemory(
169                     TrampolineBlock.getMemoryBlock(),
170                     sys::Memory::MF_READ | sys::Memory::MF_EXEC))
171       return errorCodeToError(EC);
172
173     TrampolineBlocks.push_back(std::move(TrampolineBlock));
174     return Error::success();
175   }
176
177   GetTrampolineLandingFunction GetTrampolineLanding;
178
179   std::mutex LTPMutex;
180   sys::OwningMemoryBlock ResolverBlock;
181   std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
182   std::vector<JITTargetAddress> AvailableTrampolines;
183 };
184
185 /// Target-independent base class for compile callback management.
186 class JITCompileCallbackManager {
187 public:
188   using CompileFunction = std::function<JITTargetAddress()>;
189
190   virtual ~JITCompileCallbackManager() = default;
191
192   /// Reserve a compile callback.
193   Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
194
195   /// Execute the callback for the given trampoline id. Called by the JIT
196   ///        to compile functions on demand.
197   JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
198
199 protected:
200   /// Construct a JITCompileCallbackManager.
201   JITCompileCallbackManager(std::unique_ptr<TrampolinePool> TP,
202                             ExecutionSession &ES,
203                             JITTargetAddress ErrorHandlerAddress)
204       : TP(std::move(TP)), ES(ES),
205         CallbacksJD(ES.createJITDylib("<Callbacks>")),
206         ErrorHandlerAddress(ErrorHandlerAddress) {}
207
208   void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
209     this->TP = std::move(TP);
210   }
211
212 private:
213   std::mutex CCMgrMutex;
214   std::unique_ptr<TrampolinePool> TP;
215   ExecutionSession &ES;
216   JITDylib &CallbacksJD;
217   JITTargetAddress ErrorHandlerAddress;
218   std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
219   size_t NextCallbackId = 0;
220 };
221
222 /// Manage compile callbacks for in-process JITs.
223 template <typename ORCABI>
224 class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
225 public:
226   /// Create a new LocalJITCompileCallbackManager.
227   static Expected<std::unique_ptr<LocalJITCompileCallbackManager>>
228   Create(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress) {
229     Error Err = Error::success();
230     auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
231         new LocalJITCompileCallbackManager(ES, ErrorHandlerAddress, Err));
232     if (Err)
233       return std::move(Err);
234     return std::move(CCMgr);
235   }
236
237 private:
238   /// Construct a InProcessJITCompileCallbackManager.
239   /// @param ErrorHandlerAddress The address of an error handler in the target
240   ///                            process to be used if a compile callback fails.
241   LocalJITCompileCallbackManager(ExecutionSession &ES,
242                                  JITTargetAddress ErrorHandlerAddress,
243                                  Error &Err)
244       : JITCompileCallbackManager(nullptr, ES, ErrorHandlerAddress) {
245     ErrorAsOutParameter _(&Err);
246     auto TP = LocalTrampolinePool<ORCABI>::Create(
247         [this](JITTargetAddress TrampolineAddr) {
248           return executeCompileCallback(TrampolineAddr);
249         });
250
251     if (!TP) {
252       Err = TP.takeError();
253       return;
254     }
255
256     setTrampolinePool(std::move(*TP));
257   }
258 };
259
260 /// Base class for managing collections of named indirect stubs.
261 class IndirectStubsManager {
262 public:
263   /// Map type for initializing the manager. See init.
264   using StubInitsMap = StringMap<std::pair<JITTargetAddress, JITSymbolFlags>>;
265
266   virtual ~IndirectStubsManager() = default;
267
268   /// Create a single stub with the given name, target address and flags.
269   virtual Error createStub(StringRef StubName, JITTargetAddress StubAddr,
270                            JITSymbolFlags StubFlags) = 0;
271
272   /// Create StubInits.size() stubs with the given names, target
273   ///        addresses, and flags.
274   virtual Error createStubs(const StubInitsMap &StubInits) = 0;
275
276   /// Find the stub with the given name. If ExportedStubsOnly is true,
277   ///        this will only return a result if the stub's flags indicate that it
278   ///        is exported.
279   virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
280
281   /// Find the implementation-pointer for the stub.
282   virtual JITEvaluatedSymbol findPointer(StringRef Name) = 0;
283
284   /// Change the value of the implementation pointer for the stub.
285   virtual Error updatePointer(StringRef Name, JITTargetAddress NewAddr) = 0;
286
287 private:
288   virtual void anchor();
289 };
290
291 /// IndirectStubsManager implementation for the host architecture, e.g.
292 ///        OrcX86_64. (See OrcArchitectureSupport.h).
293 template <typename TargetT>
294 class LocalIndirectStubsManager : public IndirectStubsManager {
295 public:
296   Error createStub(StringRef StubName, JITTargetAddress StubAddr,
297                    JITSymbolFlags StubFlags) override {
298     std::lock_guard<std::mutex> Lock(StubsMutex);
299     if (auto Err = reserveStubs(1))
300       return Err;
301
302     createStubInternal(StubName, StubAddr, StubFlags);
303
304     return Error::success();
305   }
306
307   Error createStubs(const StubInitsMap &StubInits) override {
308     std::lock_guard<std::mutex> Lock(StubsMutex);
309     if (auto Err = reserveStubs(StubInits.size()))
310       return Err;
311
312     for (auto &Entry : StubInits)
313       createStubInternal(Entry.first(), Entry.second.first,
314                          Entry.second.second);
315
316     return Error::success();
317   }
318
319   JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
320     std::lock_guard<std::mutex> Lock(StubsMutex);
321     auto I = StubIndexes.find(Name);
322     if (I == StubIndexes.end())
323       return nullptr;
324     auto Key = I->second.first;
325     void *StubAddr = IndirectStubsInfos[Key.first].getStub(Key.second);
326     assert(StubAddr && "Missing stub address");
327     auto StubTargetAddr =
328         static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
329     auto StubSymbol = JITEvaluatedSymbol(StubTargetAddr, I->second.second);
330     if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
331       return nullptr;
332     return StubSymbol;
333   }
334
335   JITEvaluatedSymbol findPointer(StringRef Name) override {
336     std::lock_guard<std::mutex> Lock(StubsMutex);
337     auto I = StubIndexes.find(Name);
338     if (I == StubIndexes.end())
339       return nullptr;
340     auto Key = I->second.first;
341     void *PtrAddr = IndirectStubsInfos[Key.first].getPtr(Key.second);
342     assert(PtrAddr && "Missing pointer address");
343     auto PtrTargetAddr =
344         static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
345     return JITEvaluatedSymbol(PtrTargetAddr, I->second.second);
346   }
347
348   Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
349     using AtomicIntPtr = std::atomic<uintptr_t>;
350
351     std::lock_guard<std::mutex> Lock(StubsMutex);
352     auto I = StubIndexes.find(Name);
353     assert(I != StubIndexes.end() && "No stub pointer for symbol");
354     auto Key = I->second.first;
355     AtomicIntPtr *AtomicStubPtr = reinterpret_cast<AtomicIntPtr *>(
356         IndirectStubsInfos[Key.first].getPtr(Key.second));
357     *AtomicStubPtr = static_cast<uintptr_t>(NewAddr);
358     return Error::success();
359   }
360
361 private:
362   Error reserveStubs(unsigned NumStubs) {
363     if (NumStubs <= FreeStubs.size())
364       return Error::success();
365
366     unsigned NewStubsRequired = NumStubs - FreeStubs.size();
367     unsigned NewBlockId = IndirectStubsInfos.size();
368     typename TargetT::IndirectStubsInfo ISI;
369     if (auto Err =
370             TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired, nullptr))
371       return Err;
372     for (unsigned I = 0; I < ISI.getNumStubs(); ++I)
373       FreeStubs.push_back(std::make_pair(NewBlockId, I));
374     IndirectStubsInfos.push_back(std::move(ISI));
375     return Error::success();
376   }
377
378   void createStubInternal(StringRef StubName, JITTargetAddress InitAddr,
379                           JITSymbolFlags StubFlags) {
380     auto Key = FreeStubs.back();
381     FreeStubs.pop_back();
382     *IndirectStubsInfos[Key.first].getPtr(Key.second) =
383         reinterpret_cast<void *>(static_cast<uintptr_t>(InitAddr));
384     StubIndexes[StubName] = std::make_pair(Key, StubFlags);
385   }
386
387   std::mutex StubsMutex;
388   std::vector<typename TargetT::IndirectStubsInfo> IndirectStubsInfos;
389   using StubKey = std::pair<uint16_t, uint16_t>;
390   std::vector<StubKey> FreeStubs;
391   StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
392 };
393
394 /// Create a local compile callback manager.
395 ///
396 /// The given target triple will determine the ABI, and the given
397 /// ErrorHandlerAddress will be used by the resulting compile callback
398 /// manager if a compile callback fails.
399 Expected<std::unique_ptr<JITCompileCallbackManager>>
400 createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
401                                   JITTargetAddress ErrorHandlerAddress);
402
403 /// Create a local indriect stubs manager builder.
404 ///
405 /// The given target triple will determine the ABI.
406 std::function<std::unique_ptr<IndirectStubsManager>()>
407 createLocalIndirectStubsManagerBuilder(const Triple &T);
408
409 /// Build a function pointer of FunctionType with the given constant
410 ///        address.
411 ///
412 ///   Usage example: Turn a trampoline address into a function pointer constant
413 /// for use in a stub.
414 Constant *createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr);
415
416 /// Create a function pointer with the given type, name, and initializer
417 ///        in the given Module.
418 GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name,
419                                   Constant *Initializer);
420
421 /// Turn a function declaration into a stub function that makes an
422 ///        indirect call using the given function pointer.
423 void makeStub(Function &F, Value &ImplPointer);
424
425 /// Promotes private symbols to global hidden, and renames to prevent clashes
426 /// with other promoted symbols. The same SymbolPromoter instance should be
427 /// used for all symbols to be added to a single JITDylib.
428 class SymbolLinkagePromoter {
429 public:
430   /// Promote symbols in the given module. Returns the set of global values
431   /// that have been renamed/promoted.
432   std::vector<GlobalValue *> operator()(Module &M);
433
434 private:
435   unsigned NextId = 0;
436 };
437
438 /// Clone a function declaration into a new module.
439 ///
440 ///   This function can be used as the first step towards creating a callback
441 /// stub (see makeStub), or moving a function body (see moveFunctionBody).
442 ///
443 ///   If the VMap argument is non-null, a mapping will be added between F and
444 /// the new declaration, and between each of F's arguments and the new
445 /// declaration's arguments. This map can then be passed in to moveFunction to
446 /// move the function body if required. Note: When moving functions between
447 /// modules with these utilities, all decls should be cloned (and added to a
448 /// single VMap) before any bodies are moved. This will ensure that references
449 /// between functions all refer to the versions in the new module.
450 Function *cloneFunctionDecl(Module &Dst, const Function &F,
451                             ValueToValueMapTy *VMap = nullptr);
452
453 /// Move the body of function 'F' to a cloned function declaration in a
454 ///        different module (See related cloneFunctionDecl).
455 ///
456 ///   If the target function declaration is not supplied via the NewF parameter
457 /// then it will be looked up via the VMap.
458 ///
459 ///   This will delete the body of function 'F' from its original parent module,
460 /// but leave its declaration.
461 void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
462                       ValueMaterializer *Materializer = nullptr,
463                       Function *NewF = nullptr);
464
465 /// Clone a global variable declaration into a new module.
466 GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
467                                         ValueToValueMapTy *VMap = nullptr);
468
469 /// Move global variable GV from its parent module to cloned global
470 ///        declaration in a different module.
471 ///
472 ///   If the target global declaration is not supplied via the NewGV parameter
473 /// then it will be looked up via the VMap.
474 ///
475 ///   This will delete the initializer of GV from its original parent module,
476 /// but leave its declaration.
477 void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
478                                    ValueToValueMapTy &VMap,
479                                    ValueMaterializer *Materializer = nullptr,
480                                    GlobalVariable *NewGV = nullptr);
481
482 /// Clone a global alias declaration into a new module.
483 GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
484                                   ValueToValueMapTy &VMap);
485
486 /// Clone module flags metadata into the destination module.
487 void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
488                               ValueToValueMapTy &VMap);
489
490 } // end namespace orc
491
492 } // end namespace llvm
493
494 #endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H