Home | History | Annotate | Download | only in ExecutionEngine
      1 //===----------- JITSymbol.h - JIT symbol abstraction -----------*- 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 // Abstraction for target process addresses.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_EXECUTIONENGINE_JITSYMBOL_H
     15 #define LLVM_EXECUTIONENGINE_JITSYMBOL_H
     16 
     17 #include <algorithm>
     18 #include <cassert>
     19 #include <cstddef>
     20 #include <cstdint>
     21 #include <functional>
     22 #include <string>
     23 
     24 namespace llvm {
     25 
     26 class GlobalValue;
     27 
     28 namespace object {
     29   class BasicSymbolRef;
     30 } // end namespace object
     31 
     32 /// @brief Represents an address in the target process's address space.
     33 typedef uint64_t JITTargetAddress;
     34 
     35 /// @brief Flags for symbols in the JIT.
     36 class JITSymbolFlags {
     37 public:
     38   typedef uint8_t UnderlyingType;
     39 
     40   enum FlagNames : UnderlyingType {
     41     None = 0,
     42     Weak = 1U << 0,
     43     Common = 1U << 1,
     44     Absolute = 1U << 2,
     45     Exported = 1U << 3
     46   };
     47 
     48   /// @brief Default-construct a JITSymbolFlags instance.
     49   JITSymbolFlags() : Flags(None) {}
     50 
     51   /// @brief Construct a JITSymbolFlags instance from the given flags.
     52   JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
     53 
     54   /// @brief Returns true is the Weak flag is set.
     55   bool isWeak() const {
     56     return (Flags & Weak) == Weak;
     57   }
     58 
     59   /// @brief Returns true is the Weak flag is set.
     60   bool isCommon() const {
     61     return (Flags & Common) == Common;
     62   }
     63 
     64   bool isStrongDefinition() const {
     65     return !isWeak() && !isCommon();
     66   }
     67 
     68   /// @brief Returns true is the Weak flag is set.
     69   bool isExported() const {
     70     return (Flags & Exported) == Exported;
     71   }
     72 
     73   operator UnderlyingType&() { return Flags; }
     74 
     75   /// Construct a JITSymbolFlags value based on the flags of the given global
     76   /// value.
     77   static JITSymbolFlags fromGlobalValue(const GlobalValue &GV);
     78 
     79   /// Construct a JITSymbolFlags value based on the flags of the given libobject
     80   /// symbol.
     81   static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol);
     82 
     83 private:
     84   UnderlyingType Flags;
     85 };
     86 
     87 /// @brief Represents a symbol that has been evaluated to an address already.
     88 class JITEvaluatedSymbol {
     89 public:
     90   /// @brief Create a 'null' symbol.
     91   JITEvaluatedSymbol(std::nullptr_t)
     92       : Address(0) {}
     93 
     94   /// @brief Create a symbol for the given address and flags.
     95   JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
     96       : Address(Address), Flags(Flags) {}
     97 
     98   /// @brief An evaluated symbol converts to 'true' if its address is non-zero.
     99   explicit operator bool() const { return Address != 0; }
    100 
    101   /// @brief Return the address of this symbol.
    102   JITTargetAddress getAddress() const { return Address; }
    103 
    104   /// @brief Return the flags for this symbol.
    105   JITSymbolFlags getFlags() const { return Flags; }
    106 
    107 private:
    108   JITTargetAddress Address;
    109   JITSymbolFlags Flags;
    110 };
    111 
    112 /// @brief Represents a symbol in the JIT.
    113 class JITSymbol {
    114 public:
    115   typedef std::function<JITTargetAddress()> GetAddressFtor;
    116 
    117   /// @brief Create a 'null' symbol that represents failure to find a symbol
    118   ///        definition.
    119   JITSymbol(std::nullptr_t)
    120       : CachedAddr(0) {}
    121 
    122   /// @brief Create a symbol for a definition with a known address.
    123   JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
    124       : CachedAddr(Addr), Flags(Flags) {}
    125 
    126   /// @brief Construct a JITSymbol from a JITEvaluatedSymbol.
    127   JITSymbol(JITEvaluatedSymbol Sym)
    128       : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
    129 
    130   /// @brief Create a symbol for a definition that doesn't have a known address
    131   ///        yet.
    132   /// @param GetAddress A functor to materialize a definition (fixing the
    133   ///        address) on demand.
    134   ///
    135   ///   This constructor allows a JIT layer to provide a reference to a symbol
    136   /// definition without actually materializing the definition up front. The
    137   /// user can materialize the definition at any time by calling the getAddress
    138   /// method.
    139   JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
    140       : GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {}
    141 
    142   /// @brief Returns true if the symbol exists, false otherwise.
    143   explicit operator bool() const { return CachedAddr || GetAddress; }
    144 
    145   /// @brief Get the address of the symbol in the target address space. Returns
    146   ///        '0' if the symbol does not exist.
    147   JITTargetAddress getAddress() {
    148     if (GetAddress) {
    149       CachedAddr = GetAddress();
    150       assert(CachedAddr && "Symbol could not be materialized.");
    151       GetAddress = nullptr;
    152     }
    153     return CachedAddr;
    154   }
    155 
    156   JITSymbolFlags getFlags() const { return Flags; }
    157 
    158 private:
    159   GetAddressFtor GetAddress;
    160   JITTargetAddress CachedAddr;
    161   JITSymbolFlags Flags;
    162 };
    163 
    164 /// \brief Symbol resolution.
    165 class JITSymbolResolver {
    166 public:
    167   virtual ~JITSymbolResolver() = default;
    168 
    169   /// This method returns the address of the specified symbol if it exists
    170   /// within the logical dynamic library represented by this JITSymbolResolver.
    171   /// Unlike findSymbol, queries through this interface should return addresses
    172   /// for hidden symbols.
    173   ///
    174   /// This is of particular importance for the Orc JIT APIs, which support lazy
    175   /// compilation by breaking up modules: Each of those broken out modules
    176   /// must be able to resolve hidden symbols provided by the others. Clients
    177   /// writing memory managers for MCJIT can usually ignore this method.
    178   ///
    179   /// This method will be queried by RuntimeDyld when checking for previous
    180   /// definitions of common symbols.
    181   virtual JITSymbol findSymbolInLogicalDylib(const std::string &Name) = 0;
    182 
    183   /// This method returns the address of the specified function or variable.
    184   /// It is used to resolve symbols during module linking.
    185   ///
    186   /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will
    187   /// skip all relocations for that symbol, and the client will be responsible
    188   /// for handling them manually.
    189   virtual JITSymbol findSymbol(const std::string &Name) = 0;
    190 
    191 private:
    192   virtual void anchor();
    193 };
    194 
    195 } // end namespace llvm
    196 
    197 #endif // LLVM_EXECUTIONENGINE_JITSYMBOL_H
    198