//===- IndirectionUtils.h - Utilities for adding indirections ---*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Contains utilities for adding indirections and breaking up modules. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H #define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/OrcABISupport.h" #include "llvm/Support/Error.h" #include "llvm/Support/Memory.h" #include "llvm/Support/Process.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include <algorithm> #include <cassert> #include <cstdint> #include <functional> #include <future> #include <map> #include <memory> #include <system_error> #include <utility> #include <vector> namespace llvm { class Constant; class Function; class FunctionType; class GlobalAlias; class GlobalVariable; class Module; class PointerType; class Triple; class Twine; class Value; class MCDisassembler; class MCInstrAnalysis; namespace jitlink { class LinkGraph; class Symbol; } // namespace jitlink namespace orc { /// Base class for pools of compiler re-entry trampolines. /// These trampolines are callable addresses that save all register state /// before calling a supplied function to return the trampoline landing /// address, then restore all state before jumping to that address. They /// are used by various ORC APIs to support lazy compilation class TrampolinePool { … }; /// A trampoline pool for trampolines within the current process. template <typename ORCABI> class LocalTrampolinePool : public TrampolinePool { … }; /// Target-independent base class for compile callback management. class JITCompileCallbackManager { … }; /// Manage compile callbacks for in-process JITs. template <typename ORCABI> class LocalJITCompileCallbackManager : public JITCompileCallbackManager { … }; /// Base class for managing collections of named indirect stubs. class IndirectStubsManager { … }; template <typename ORCABI> class LocalIndirectStubsInfo { … }; /// IndirectStubsManager implementation for the host architecture, e.g. /// OrcX86_64. (See OrcArchitectureSupport.h). template <typename TargetT> class LocalIndirectStubsManager : public IndirectStubsManager { … }; /// Create a local compile callback manager. /// /// The given target triple will determine the ABI, and the given /// ErrorHandlerAddress will be used by the resulting compile callback /// manager if a compile callback fails. Expected<std::unique_ptr<JITCompileCallbackManager>> createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress); /// Create a local indirect stubs manager builder. /// /// The given target triple will determine the ABI. std::function<std::unique_ptr<IndirectStubsManager>()> createLocalIndirectStubsManagerBuilder(const Triple &T); /// Build a function pointer of FunctionType with the given constant /// address. /// /// Usage example: Turn a trampoline address into a function pointer constant /// for use in a stub. Constant *createIRTypedAddress(FunctionType &FT, ExecutorAddr Addr); /// Create a function pointer with the given type, name, and initializer /// in the given Module. GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name, Constant *Initializer); /// Turn a function declaration into a stub function that makes an /// indirect call using the given function pointer. void makeStub(Function &F, Value &ImplPointer); /// Promotes private symbols to global hidden, and renames to prevent clashes /// with other promoted symbols. The same SymbolPromoter instance should be /// used for all symbols to be added to a single JITDylib. class SymbolLinkagePromoter { … }; /// Clone a function declaration into a new module. /// /// This function can be used as the first step towards creating a callback /// stub (see makeStub). /// /// If the VMap argument is non-null, a mapping will be added between F and /// the new declaration, and between each of F's arguments and the new /// declaration's arguments. This map can then be passed in to moveFunction to /// move the function body if required. Note: When moving functions between /// modules with these utilities, all decls should be cloned (and added to a /// single VMap) before any bodies are moved. This will ensure that references /// between functions all refer to the versions in the new module. Function *cloneFunctionDecl(Module &Dst, const Function &F, ValueToValueMapTy *VMap = nullptr); /// Clone a global variable declaration into a new module. GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, ValueToValueMapTy *VMap = nullptr); /// Clone a global alias declaration into a new module. GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA, ValueToValueMapTy &VMap); /// Introduce relocations to \p Sym in its own definition if there are any /// pointers formed via PC-relative address that do not already have a /// relocation. /// /// This is useful when introducing indirection via a stub function at link time /// without compiler support. If a function pointer is formed without a /// relocation, e.g. in the definition of \c foo /// /// \code /// _foo: /// leaq -7(%rip), rax # form pointer to _foo without relocation /// _bar: /// leaq (%rip), %rax # uses X86_64_RELOC_SIGNED to '_foo' /// \endcode /// /// the pointer to \c _foo computed by \c _foo and \c _bar may differ if we /// introduce a stub for _foo. If the pointer is used as a key, this may be /// observable to the program. This pass will attempt to introduce the missing /// "self-relocation" on the leaq instruction. /// /// This is based on disassembly and should be considered "best effort". It may /// silently fail to add relocations. Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym, jitlink::LinkGraph &G, MCDisassembler &Disassembler, MCInstrAnalysis &MIA); } // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H