xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- IndirectionUtils.h - Utilities for adding indirections ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Contains utilities for adding indirections and breaking up modules.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
14 #define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
15 
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ExecutionEngine/JITSymbol.h"
19 #include "llvm/ExecutionEngine/Orc/Core.h"
20 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
21 #include "llvm/ExecutionEngine/Orc/RedirectionManager.h"
22 #include "llvm/Support/Compiler.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/Memory.h"
25 #include "llvm/Support/Process.h"
26 #include "llvm/Transforms/Utils/ValueMapper.h"
27 #include <algorithm>
28 #include <cassert>
29 #include <cstdint>
30 #include <functional>
31 #include <future>
32 #include <map>
33 #include <memory>
34 #include <system_error>
35 #include <utility>
36 #include <vector>
37 
38 namespace llvm {
39 
40 class Constant;
41 class Function;
42 class FunctionType;
43 class GlobalAlias;
44 class GlobalVariable;
45 class Module;
46 class PointerType;
47 class Triple;
48 class Twine;
49 class Value;
50 class MCDisassembler;
51 class MCInstrAnalysis;
52 
53 namespace jitlink {
54 class LinkGraph;
55 class Symbol;
56 } // namespace jitlink
57 
58 namespace orc {
59 
60 /// Base class for pools of compiler re-entry trampolines.
61 /// These trampolines are callable addresses that save all register state
62 /// before calling a supplied function to return the trampoline landing
63 /// address, then restore all state before jumping to that address. They
64 /// are used by various ORC APIs to support lazy compilation
65 class LLVM_ABI TrampolinePool {
66 public:
67   using NotifyLandingResolvedFunction =
68       unique_function<void(ExecutorAddr) const>;
69 
70   using ResolveLandingFunction = unique_function<void(
71       ExecutorAddr TrampolineAddr,
72       NotifyLandingResolvedFunction OnLandingResolved) const>;
73 
74   virtual ~TrampolinePool();
75 
76   /// Get an available trampoline address.
77   /// Returns an error if no trampoline can be created.
getTrampoline()78   Expected<ExecutorAddr> getTrampoline() {
79     std::lock_guard<std::mutex> Lock(TPMutex);
80     if (AvailableTrampolines.empty()) {
81       if (auto Err = grow())
82         return std::move(Err);
83     }
84     assert(!AvailableTrampolines.empty() && "Failed to grow trampoline pool");
85     auto TrampolineAddr = AvailableTrampolines.back();
86     AvailableTrampolines.pop_back();
87     return TrampolineAddr;
88   }
89 
90   /// Returns the given trampoline to the pool for re-use.
releaseTrampoline(ExecutorAddr TrampolineAddr)91   void releaseTrampoline(ExecutorAddr TrampolineAddr) {
92     std::lock_guard<std::mutex> Lock(TPMutex);
93     AvailableTrampolines.push_back(TrampolineAddr);
94   }
95 
96 protected:
97   virtual Error grow() = 0;
98 
99   std::mutex TPMutex;
100   std::vector<ExecutorAddr> AvailableTrampolines;
101 };
102 
103 /// A trampoline pool for trampolines within the current process.
104 template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool {
105 public:
106   /// Creates a LocalTrampolinePool with the given RunCallback function.
107   /// Returns an error if this function is unable to correctly allocate, write
108   /// and protect the resolver code block.
109   static Expected<std::unique_ptr<LocalTrampolinePool>>
Create(ResolveLandingFunction ResolveLanding)110   Create(ResolveLandingFunction ResolveLanding) {
111     Error Err = Error::success();
112 
113     auto LTP = std::unique_ptr<LocalTrampolinePool>(
114         new LocalTrampolinePool(std::move(ResolveLanding), Err));
115 
116     if (Err)
117       return std::move(Err);
118     return std::move(LTP);
119   }
120 
121 private:
reenter(void * TrampolinePoolPtr,void * TrampolineId)122   static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) {
123     LocalTrampolinePool<ORCABI> *TrampolinePool =
124         static_cast<LocalTrampolinePool *>(TrampolinePoolPtr);
125 
126     std::promise<ExecutorAddr> LandingAddressP;
127     auto LandingAddressF = LandingAddressP.get_future();
128 
129     TrampolinePool->ResolveLanding(ExecutorAddr::fromPtr(TrampolineId),
130                                    [&](ExecutorAddr LandingAddress) {
131                                      LandingAddressP.set_value(LandingAddress);
132                                    });
133     return LandingAddressF.get().getValue();
134   }
135 
LocalTrampolinePool(ResolveLandingFunction ResolveLanding,Error & Err)136   LocalTrampolinePool(ResolveLandingFunction ResolveLanding, Error &Err)
137       : ResolveLanding(std::move(ResolveLanding)) {
138 
139     ErrorAsOutParameter _(Err);
140 
141     /// Try to set up the resolver block.
142     std::error_code EC;
143     ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
144         ORCABI::ResolverCodeSize, nullptr,
145         sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
146     if (EC) {
147       Err = errorCodeToError(EC);
148       return;
149     }
150 
151     ORCABI::writeResolverCode(static_cast<char *>(ResolverBlock.base()),
152                               ExecutorAddr::fromPtr(ResolverBlock.base()),
153                               ExecutorAddr::fromPtr(&reenter),
154                               ExecutorAddr::fromPtr(this));
155 
156     EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
157                                           sys::Memory::MF_READ |
158                                               sys::Memory::MF_EXEC);
159     if (EC) {
160       Err = errorCodeToError(EC);
161       return;
162     }
163   }
164 
grow()165   Error grow() override {
166     assert(AvailableTrampolines.empty() && "Growing prematurely?");
167 
168     std::error_code EC;
169     auto TrampolineBlock =
170         sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
171             sys::Process::getPageSizeEstimate(), nullptr,
172             sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
173     if (EC)
174       return errorCodeToError(EC);
175 
176     unsigned NumTrampolines =
177         (sys::Process::getPageSizeEstimate() - ORCABI::PointerSize) /
178         ORCABI::TrampolineSize;
179 
180     char *TrampolineMem = static_cast<char *>(TrampolineBlock.base());
181     ORCABI::writeTrampolines(
182         TrampolineMem, ExecutorAddr::fromPtr(TrampolineMem),
183         ExecutorAddr::fromPtr(ResolverBlock.base()), NumTrampolines);
184 
185     for (unsigned I = 0; I < NumTrampolines; ++I)
186       AvailableTrampolines.push_back(
187           ExecutorAddr::fromPtr(TrampolineMem + (I * ORCABI::TrampolineSize)));
188 
189     if (auto EC = sys::Memory::protectMappedMemory(
190                     TrampolineBlock.getMemoryBlock(),
191                     sys::Memory::MF_READ | sys::Memory::MF_EXEC))
192       return errorCodeToError(EC);
193 
194     TrampolineBlocks.push_back(std::move(TrampolineBlock));
195     return Error::success();
196   }
197 
198   ResolveLandingFunction ResolveLanding;
199 
200   sys::OwningMemoryBlock ResolverBlock;
201   std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
202 };
203 
204 /// Target-independent base class for compile callback management.
205 class JITCompileCallbackManager {
206 public:
207   using CompileFunction = std::function<ExecutorAddr()>;
208 
209   virtual ~JITCompileCallbackManager() = default;
210 
211   /// Reserve a compile callback.
212   LLVM_ABI Expected<ExecutorAddr> getCompileCallback(CompileFunction Compile);
213 
214   /// Execute the callback for the given trampoline id. Called by the JIT
215   ///        to compile functions on demand.
216   LLVM_ABI ExecutorAddr executeCompileCallback(ExecutorAddr TrampolineAddr);
217 
218 protected:
219   /// Construct a JITCompileCallbackManager.
JITCompileCallbackManager(std::unique_ptr<TrampolinePool> TP,ExecutionSession & ES,ExecutorAddr ErrorHandlerAddress)220   JITCompileCallbackManager(std::unique_ptr<TrampolinePool> TP,
221                             ExecutionSession &ES,
222                             ExecutorAddr ErrorHandlerAddress)
223       : TP(std::move(TP)), ES(ES),
224         CallbacksJD(ES.createBareJITDylib("<Callbacks>")),
225         ErrorHandlerAddress(ErrorHandlerAddress) {}
226 
setTrampolinePool(std::unique_ptr<TrampolinePool> TP)227   void setTrampolinePool(std::unique_ptr<TrampolinePool> TP) {
228     this->TP = std::move(TP);
229   }
230 
231 private:
232   std::mutex CCMgrMutex;
233   std::unique_ptr<TrampolinePool> TP;
234   ExecutionSession &ES;
235   JITDylib &CallbacksJD;
236   ExecutorAddr ErrorHandlerAddress;
237   std::map<ExecutorAddr, SymbolStringPtr> AddrToSymbol;
238   size_t NextCallbackId = 0;
239 };
240 
241 /// Manage compile callbacks for in-process JITs.
242 template <typename ORCABI>
243 class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
244 public:
245   /// Create a new LocalJITCompileCallbackManager.
246   static Expected<std::unique_ptr<LocalJITCompileCallbackManager>>
Create(ExecutionSession & ES,ExecutorAddr ErrorHandlerAddress)247   Create(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress) {
248     Error Err = Error::success();
249     auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
250         new LocalJITCompileCallbackManager(ES, ErrorHandlerAddress, Err));
251     if (Err)
252       return std::move(Err);
253     return std::move(CCMgr);
254   }
255 
256 private:
257   /// Construct a InProcessJITCompileCallbackManager.
258   /// @param ErrorHandlerAddress The address of an error handler in the target
259   ///                            process to be used if a compile callback fails.
LocalJITCompileCallbackManager(ExecutionSession & ES,ExecutorAddr ErrorHandlerAddress,Error & Err)260   LocalJITCompileCallbackManager(ExecutionSession &ES,
261                                  ExecutorAddr ErrorHandlerAddress, Error &Err)
262       : JITCompileCallbackManager(nullptr, ES, ErrorHandlerAddress) {
263     using NotifyLandingResolvedFunction =
264         TrampolinePool::NotifyLandingResolvedFunction;
265 
266     ErrorAsOutParameter _(Err);
267     auto TP = LocalTrampolinePool<ORCABI>::Create(
268         [this](ExecutorAddr TrampolineAddr,
269                NotifyLandingResolvedFunction NotifyLandingResolved) {
270           NotifyLandingResolved(executeCompileCallback(TrampolineAddr));
271         });
272 
273     if (!TP) {
274       Err = TP.takeError();
275       return;
276     }
277 
278     setTrampolinePool(std::move(*TP));
279   }
280 };
281 
282 /// Base class for managing collections of named indirect stubs.
283 class LLVM_ABI IndirectStubsManager : public RedirectableSymbolManager {
284 public:
285   /// Map type for initializing the manager. See init.
286   using StubInitsMap = StringMap<std::pair<ExecutorAddr, JITSymbolFlags>>;
287 
288   virtual ~IndirectStubsManager() = default;
289 
290   /// Create a single stub with the given name, target address and flags.
291   virtual Error createStub(StringRef StubName, ExecutorAddr StubAddr,
292                            JITSymbolFlags StubFlags) = 0;
293 
294   /// Create StubInits.size() stubs with the given names, target
295   ///        addresses, and flags.
296   virtual Error createStubs(const StubInitsMap &StubInits) = 0;
297 
298   /// Find the stub with the given name. If ExportedStubsOnly is true,
299   ///        this will only return a result if the stub's flags indicate that it
300   ///        is exported.
301   virtual ExecutorSymbolDef findStub(StringRef Name,
302                                      bool ExportedStubsOnly) = 0;
303 
304   /// Find the implementation-pointer for the stub.
305   virtual ExecutorSymbolDef findPointer(StringRef Name) = 0;
306 
307   /// Change the value of the implementation pointer for the stub.
308   virtual Error updatePointer(StringRef Name, ExecutorAddr NewAddr) = 0;
309 
310   /// --- RedirectableSymbolManager implementation ---
311   Error redirect(JITDylib &JD, const SymbolMap &NewDests) override;
312 
313   void
314   emitRedirectableSymbols(std::unique_ptr<MaterializationResponsibility> MR,
315                           SymbolMap InitialDests) override;
316 
317 private:
318   void anchor() override;
319 };
320 
321 template <typename ORCABI> class LocalIndirectStubsInfo {
322 public:
LocalIndirectStubsInfo(unsigned NumStubs,sys::OwningMemoryBlock StubsMem)323   LocalIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
324       : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
325 
create(unsigned MinStubs,unsigned PageSize)326   static Expected<LocalIndirectStubsInfo> create(unsigned MinStubs,
327                                                  unsigned PageSize) {
328     auto ISAS = getIndirectStubsBlockSizes<ORCABI>(MinStubs, PageSize);
329 
330     assert((ISAS.StubBytes % PageSize == 0) &&
331            "StubBytes is not a page size multiple");
332     uint64_t PointerAlloc = alignTo(ISAS.PointerBytes, PageSize);
333 
334     // Allocate memory for stubs and pointers in one call.
335     std::error_code EC;
336     auto StubsAndPtrsMem =
337         sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
338             ISAS.StubBytes + PointerAlloc, nullptr,
339             sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
340     if (EC)
341       return errorCodeToError(EC);
342 
343     sys::MemoryBlock StubsBlock(StubsAndPtrsMem.base(), ISAS.StubBytes);
344     auto StubsBlockMem = static_cast<char *>(StubsAndPtrsMem.base());
345     auto PtrBlockAddress =
346         ExecutorAddr::fromPtr(StubsBlockMem) + ISAS.StubBytes;
347 
348     ORCABI::writeIndirectStubsBlock(StubsBlockMem,
349                                     ExecutorAddr::fromPtr(StubsBlockMem),
350                                     PtrBlockAddress, ISAS.NumStubs);
351 
352     if (auto EC = sys::Memory::protectMappedMemory(
353             StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC))
354       return errorCodeToError(EC);
355 
356     return LocalIndirectStubsInfo(ISAS.NumStubs, std::move(StubsAndPtrsMem));
357   }
358 
getNumStubs()359   unsigned getNumStubs() const { return NumStubs; }
360 
getStub(unsigned Idx)361   void *getStub(unsigned Idx) const {
362     return static_cast<char *>(StubsMem.base()) + Idx * ORCABI::StubSize;
363   }
364 
getPtr(unsigned Idx)365   void **getPtr(unsigned Idx) const {
366     char *PtrsBase =
367         static_cast<char *>(StubsMem.base()) + NumStubs * ORCABI::StubSize;
368     return reinterpret_cast<void **>(PtrsBase) + Idx;
369   }
370 
371 private:
372   unsigned NumStubs = 0;
373   sys::OwningMemoryBlock StubsMem;
374 };
375 
376 /// IndirectStubsManager implementation for the host architecture, e.g.
377 ///        OrcX86_64. (See OrcArchitectureSupport.h).
378 template <typename TargetT>
379 class LocalIndirectStubsManager : public IndirectStubsManager {
380 public:
createStub(StringRef StubName,ExecutorAddr StubAddr,JITSymbolFlags StubFlags)381   Error createStub(StringRef StubName, ExecutorAddr StubAddr,
382                    JITSymbolFlags StubFlags) override {
383     std::lock_guard<std::mutex> Lock(StubsMutex);
384     if (auto Err = reserveStubs(1))
385       return Err;
386 
387     createStubInternal(StubName, StubAddr, StubFlags);
388 
389     return Error::success();
390   }
391 
createStubs(const StubInitsMap & StubInits)392   Error createStubs(const StubInitsMap &StubInits) override {
393     std::lock_guard<std::mutex> Lock(StubsMutex);
394     if (auto Err = reserveStubs(StubInits.size()))
395       return Err;
396 
397     for (const auto &Entry : StubInits)
398       createStubInternal(Entry.first(), Entry.second.first,
399                          Entry.second.second);
400 
401     return Error::success();
402   }
403 
findStub(StringRef Name,bool ExportedStubsOnly)404   ExecutorSymbolDef findStub(StringRef Name, bool ExportedStubsOnly) override {
405     std::lock_guard<std::mutex> Lock(StubsMutex);
406     auto I = StubIndexes.find(Name);
407     if (I == StubIndexes.end())
408       return ExecutorSymbolDef();
409     auto Key = I->second.first;
410     void *StubPtr = IndirectStubsInfos[Key.first].getStub(Key.second);
411     assert(StubPtr && "Missing stub address");
412     auto StubAddr = ExecutorAddr::fromPtr(StubPtr);
413     auto StubSymbol = ExecutorSymbolDef(StubAddr, I->second.second);
414     if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
415       return ExecutorSymbolDef();
416     return StubSymbol;
417   }
418 
findPointer(StringRef Name)419   ExecutorSymbolDef findPointer(StringRef Name) override {
420     std::lock_guard<std::mutex> Lock(StubsMutex);
421     auto I = StubIndexes.find(Name);
422     if (I == StubIndexes.end())
423       return ExecutorSymbolDef();
424     auto Key = I->second.first;
425     void *PtrPtr = IndirectStubsInfos[Key.first].getPtr(Key.second);
426     assert(PtrPtr && "Missing pointer address");
427     auto PtrAddr = ExecutorAddr::fromPtr(PtrPtr);
428     return ExecutorSymbolDef(PtrAddr, I->second.second);
429   }
430 
updatePointer(StringRef Name,ExecutorAddr NewAddr)431   Error updatePointer(StringRef Name, ExecutorAddr NewAddr) override {
432     using AtomicIntPtr = std::atomic<uintptr_t>;
433 
434     std::lock_guard<std::mutex> Lock(StubsMutex);
435     auto I = StubIndexes.find(Name);
436     assert(I != StubIndexes.end() && "No stub pointer for symbol");
437     auto Key = I->second.first;
438     AtomicIntPtr *AtomicStubPtr = reinterpret_cast<AtomicIntPtr *>(
439         IndirectStubsInfos[Key.first].getPtr(Key.second));
440     *AtomicStubPtr = static_cast<uintptr_t>(NewAddr.getValue());
441     return Error::success();
442   }
443 
444 private:
reserveStubs(unsigned NumStubs)445   Error reserveStubs(unsigned NumStubs) {
446     if (NumStubs <= FreeStubs.size())
447       return Error::success();
448 
449     unsigned NewStubsRequired = NumStubs - FreeStubs.size();
450     unsigned NewBlockId = IndirectStubsInfos.size();
451     auto ISI =
452         LocalIndirectStubsInfo<TargetT>::create(NewStubsRequired, PageSize);
453     if (!ISI)
454       return ISI.takeError();
455     for (unsigned I = 0; I < ISI->getNumStubs(); ++I)
456       FreeStubs.push_back(std::make_pair(NewBlockId, I));
457     IndirectStubsInfos.push_back(std::move(*ISI));
458     return Error::success();
459   }
460 
createStubInternal(StringRef StubName,ExecutorAddr InitAddr,JITSymbolFlags StubFlags)461   void createStubInternal(StringRef StubName, ExecutorAddr InitAddr,
462                           JITSymbolFlags StubFlags) {
463     auto Key = FreeStubs.back();
464     FreeStubs.pop_back();
465     *IndirectStubsInfos[Key.first].getPtr(Key.second) =
466         InitAddr.toPtr<void *>();
467     StubIndexes[StubName] = std::make_pair(Key, StubFlags);
468   }
469 
470   unsigned PageSize = sys::Process::getPageSizeEstimate();
471   std::mutex StubsMutex;
472   std::vector<LocalIndirectStubsInfo<TargetT>> IndirectStubsInfos;
473   using StubKey = std::pair<uint16_t, uint16_t>;
474   std::vector<StubKey> FreeStubs;
475   StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
476 };
477 
478 /// Create a local compile callback manager.
479 ///
480 /// The given target triple will determine the ABI, and the given
481 /// ErrorHandlerAddress will be used by the resulting compile callback
482 /// manager if a compile callback fails.
483 LLVM_ABI Expected<std::unique_ptr<JITCompileCallbackManager>>
484 createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
485                                   ExecutorAddr ErrorHandlerAddress);
486 
487 /// Create a local indirect stubs manager builder.
488 ///
489 /// The given target triple will determine the ABI.
490 LLVM_ABI std::function<std::unique_ptr<IndirectStubsManager>()>
491 createLocalIndirectStubsManagerBuilder(const Triple &T);
492 
493 /// Build a function pointer of FunctionType with the given constant
494 ///        address.
495 ///
496 ///   Usage example: Turn a trampoline address into a function pointer constant
497 /// for use in a stub.
498 LLVM_ABI Constant *createIRTypedAddress(FunctionType &FT, ExecutorAddr Addr);
499 
500 /// Create a function pointer with the given type, name, and initializer
501 ///        in the given Module.
502 LLVM_ABI GlobalVariable *createImplPointer(PointerType &PT, Module &M,
503                                            const Twine &Name,
504                                            Constant *Initializer);
505 
506 /// Turn a function declaration into a stub function that makes an
507 ///        indirect call using the given function pointer.
508 LLVM_ABI void makeStub(Function &F, Value &ImplPointer);
509 
510 /// Promotes private symbols to global hidden, and renames to prevent clashes
511 /// with other promoted symbols. The same SymbolPromoter instance should be
512 /// used for all symbols to be added to a single JITDylib.
513 class SymbolLinkagePromoter {
514 public:
515   /// Promote symbols in the given module. Returns the set of global values
516   /// that have been renamed/promoted.
517   LLVM_ABI std::vector<GlobalValue *> operator()(Module &M);
518 
519 private:
520   unsigned NextId = 0;
521 };
522 
523 /// Clone a function declaration into a new module.
524 ///
525 ///   This function can be used as the first step towards creating a callback
526 /// stub (see makeStub).
527 ///
528 ///   If the VMap argument is non-null, a mapping will be added between F and
529 /// the new declaration, and between each of F's arguments and the new
530 /// declaration's arguments. This map can then be passed in to moveFunction to
531 /// move the function body if required. Note: When moving functions between
532 /// modules with these utilities, all decls should be cloned (and added to a
533 /// single VMap) before any bodies are moved. This will ensure that references
534 /// between functions all refer to the versions in the new module.
535 LLVM_ABI Function *cloneFunctionDecl(Module &Dst, const Function &F,
536                                      ValueToValueMapTy *VMap = nullptr);
537 
538 /// Clone a global variable declaration into a new module.
539 LLVM_ABI GlobalVariable *
540 cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
541                         ValueToValueMapTy *VMap = nullptr);
542 
543 /// Clone a global alias declaration into a new module.
544 LLVM_ABI GlobalAlias *cloneGlobalAliasDecl(Module &Dst,
545                                            const GlobalAlias &OrigA,
546                                            ValueToValueMapTy &VMap);
547 
548 /// Introduce relocations to \p Sym in its own definition if there are any
549 /// pointers formed via PC-relative address that do not already have a
550 /// relocation.
551 ///
552 /// This is useful when introducing indirection via a stub function at link time
553 /// without compiler support. If a function pointer is formed without a
554 /// relocation, e.g. in the definition of \c foo
555 ///
556 /// \code
557 /// _foo:
558 ///   leaq -7(%rip), rax # form pointer to _foo without relocation
559 /// _bar:
560 ///   leaq (%rip), %rax  # uses X86_64_RELOC_SIGNED to '_foo'
561 /// \endcode
562 ///
563 /// the pointer to \c _foo computed by \c _foo and \c _bar may differ if we
564 /// introduce a stub for _foo. If the pointer is used as a key, this may be
565 /// observable to the program. This pass will attempt to introduce the missing
566 /// "self-relocation" on the leaq instruction.
567 ///
568 /// This is based on disassembly and should be considered "best effort". It may
569 /// silently fail to add relocations.
570 LLVM_ABI Error addFunctionPointerRelocationsToCurrentSymbol(
571     jitlink::Symbol &Sym, jitlink::LinkGraph &G, MCDisassembler &Disassembler,
572     MCInstrAnalysis &MIA);
573 
574 } // end namespace orc
575 
576 } // end namespace llvm
577 
578 #endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
579