LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine - JITSymbol.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 35 39 89.7 %
Date: 2017-09-14 15:23:50 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "llvm/Support/Error.h"
      25             : 
      26             : namespace llvm {
      27             : 
      28             : class GlobalValue;
      29             : 
      30             : namespace object {
      31             : 
      32             : class BasicSymbolRef;
      33             : 
      34             : } // end namespace object
      35             : 
      36             : /// @brief Represents an address in the target process's address space.
      37             : using JITTargetAddress = uint64_t;
      38             : 
      39             : /// @brief Flags for symbols in the JIT.
      40             : class JITSymbolFlags {
      41             : public:
      42             :   using UnderlyingType = uint8_t;
      43             :   using TargetFlagsType = uint64_t;
      44             : 
      45             :   enum FlagNames : UnderlyingType {
      46             :     None = 0,
      47             :     HasError = 1U << 0,
      48             :     Weak = 1U << 1,
      49             :     Common = 1U << 2,
      50             :     Absolute = 1U << 3,
      51             :     Exported = 1U << 4
      52             :   };
      53             : 
      54             :   /// @brief Default-construct a JITSymbolFlags instance.
      55        1420 :   JITSymbolFlags() = default;
      56             : 
      57             :   /// @brief Construct a JITSymbolFlags instance from the given flags.
      58        3112 :   JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
      59             : 
      60             :   /// @brief Construct a JITSymbolFlags instance from the given flags and target
      61             :   ///        flags.
      62             :   JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
      63             :     : Flags(Flags), TargetFlags(TargetFlags) {}
      64             : 
      65             :   /// @brief Return true if there was an error retrieving this symbol.
      66             :   bool hasError() const {
      67             :     return (Flags & HasError) == HasError;
      68             :   }
      69             : 
      70             :   /// @brief Returns true if the Weak flag is set.
      71             :   bool isWeak() const {
      72             :     return (Flags & Weak) == Weak;
      73             :   }
      74             : 
      75             :   /// @brief Returns true if the Common flag is set.
      76             :   bool isCommon() const {
      77             :     return (Flags & Common) == Common;
      78             :   }
      79             : 
      80             :   /// @brief Returns true if the symbol isn't weak or common.
      81             :   bool isStrongDefinition() const {
      82           4 :     return !isWeak() && !isCommon();
      83             :   }
      84             : 
      85             :   /// @brief Returns true if the Exported flag is set.
      86             :   bool isExported() const {
      87             :     return (Flags & Exported) == Exported;
      88             :   }
      89             : 
      90             :   /// @brief Implicitly convert to the underlying flags type.
      91             :   operator UnderlyingType&() { return Flags; }
      92             : 
      93             :   /// @brief Implicitly convert to the underlying flags type.
      94             :   operator const UnderlyingType&() const { return Flags; }
      95             : 
      96             :   /// @brief Return a reference to the target-specific flags.
      97             :   TargetFlagsType& getTargetFlags() { return TargetFlags; }
      98             : 
      99             :   /// @brief Return a reference to the target-specific flags.
     100           3 :   const TargetFlagsType& getTargetFlags() const { return TargetFlags; }
     101             : 
     102             :   /// Construct a JITSymbolFlags value based on the flags of the given global
     103             :   /// value.
     104             :   static JITSymbolFlags fromGlobalValue(const GlobalValue &GV);
     105             : 
     106             :   /// Construct a JITSymbolFlags value based on the flags of the given libobject
     107             :   /// symbol.
     108             :   static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol);
     109             : 
     110             : private:
     111             :   UnderlyingType Flags = None;
     112             :   TargetFlagsType TargetFlags = 0;
     113             : };
     114             : 
     115             : /// @brief ARM-specific JIT symbol flags.
     116             : /// FIXME: This should be moved into a target-specific header.
     117             : class ARMJITSymbolFlags {
     118             : public:
     119             :   ARMJITSymbolFlags() = default;
     120             : 
     121             :   enum FlagNames {
     122             :     None = 0,
     123             :     Thumb = 1 << 0
     124             :   };
     125             : 
     126             :   operator JITSymbolFlags::TargetFlagsType&() { return Flags; }
     127             : 
     128             :   static ARMJITSymbolFlags fromObjectSymbol(
     129             :                                            const object::BasicSymbolRef &Symbol);
     130             : private:
     131             :   JITSymbolFlags::TargetFlagsType Flags = 0;
     132             : };
     133             : 
     134             : /// @brief Represents a symbol that has been evaluated to an address already.
     135             : class JITEvaluatedSymbol {
     136             : public:
     137             :   /// @brief Create a 'null' symbol.
     138         874 :   JITEvaluatedSymbol(std::nullptr_t) {}
     139             : 
     140             :   /// @brief Create a symbol for the given address and flags.
     141             :   JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
     142        1060 :       : Address(Address), Flags(Flags) {}
     143             : 
     144             :   /// @brief An evaluated symbol converts to 'true' if its address is non-zero.
     145             :   explicit operator bool() const { return Address != 0; }
     146             : 
     147             :   /// @brief Return the address of this symbol.
     148             :   JITTargetAddress getAddress() const { return Address; }
     149             : 
     150             :   /// @brief Return the flags for this symbol.
     151             :   JITSymbolFlags getFlags() const { return Flags; }
     152             : 
     153             : private:
     154             :   JITTargetAddress Address = 0;
     155             :   JITSymbolFlags Flags;
     156             : };
     157             : 
     158             : /// @brief Represents a symbol in the JIT.
     159             : class JITSymbol {
     160             : public:
     161             :   using GetAddressFtor = std::function<Expected<JITTargetAddress>()>;
     162             : 
     163             :   /// @brief Create a 'null' symbol, used to represent a "symbol not found"
     164             :   ///        result from a successful (non-erroneous) lookup.
     165             :   JITSymbol(std::nullptr_t)
     166        2949 :       : CachedAddr(0) {}
     167             : 
     168             :   /// @brief Create a JITSymbol representing an error in the symbol lookup
     169             :   ///        process (e.g. a network failure during a remote lookup).
     170             :   JITSymbol(Error Err)
     171          20 :     : Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
     172             : 
     173             :   /// @brief Create a symbol for a definition with a known address.
     174             :   JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
     175         694 :       : CachedAddr(Addr), Flags(Flags) {}
     176             : 
     177             :   /// @brief Construct a JITSymbol from a JITEvaluatedSymbol.
     178             :   JITSymbol(JITEvaluatedSymbol Sym)
     179         964 :       : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
     180             : 
     181             :   /// @brief Create a symbol for a definition that doesn't have a known address
     182             :   ///        yet.
     183             :   /// @param GetAddress A functor to materialize a definition (fixing the
     184             :   ///        address) on demand.
     185             :   ///
     186             :   ///   This constructor allows a JIT layer to provide a reference to a symbol
     187             :   /// definition without actually materializing the definition up front. The
     188             :   /// user can materialize the definition at any time by calling the getAddress
     189             :   /// method.
     190             :   JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
     191         462 :       : GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {}
     192             : 
     193             :   JITSymbol(const JITSymbol&) = delete;
     194             :   JITSymbol& operator=(const JITSymbol&) = delete;
     195             : 
     196         713 :   JITSymbol(JITSymbol &&Other)
     197        1426 :     : GetAddress(std::move(Other.GetAddress)), Flags(std::move(Other.Flags)) {
     198         713 :     if (Flags.hasError())
     199           0 :       Err = std::move(Other.Err);
     200             :     else
     201         713 :       CachedAddr = std::move(Other.CachedAddr);
     202         713 :   }
     203             : 
     204          10 :   JITSymbol& operator=(JITSymbol &&Other) {
     205          10 :     GetAddress = std::move(Other.GetAddress);
     206          10 :     Flags = std::move(Other.Flags);
     207          10 :     if (Flags.hasError())
     208           0 :       Err = std::move(Other.Err);
     209             :     else
     210          10 :       CachedAddr = std::move(Other.CachedAddr);
     211          10 :     return *this;
     212             :   }
     213             : 
     214        8283 :   ~JITSymbol() {
     215        2761 :     if (Flags.hasError())
     216           5 :       Err.~Error();
     217             :     else
     218             :       CachedAddr.~JITTargetAddress();
     219        2761 :   }
     220             : 
     221             :   /// @brief Returns true if the symbol exists, false otherwise.
     222             :   explicit operator bool() const {
     223        3997 :     return !Flags.hasError() && (CachedAddr || GetAddress);
     224             :   }
     225             : 
     226             :   /// @brief Move the error field value out of this JITSymbol.
     227             :   Error takeError() {
     228         129 :     if (Flags.hasError())
     229           5 :       return std::move(Err);
     230           0 :     return Error::success();
     231             :   }
     232             : 
     233             :   /// @brief Get the address of the symbol in the target address space. Returns
     234             :   ///        '0' if the symbol does not exist.
     235         776 :   Expected<JITTargetAddress> getAddress() {
     236             :     assert(!Flags.hasError() && "getAddress called on error value");
     237        1552 :     if (GetAddress) {
     238         920 :       if (auto CachedAddrOrErr = GetAddress()) {
     239         460 :         GetAddress = nullptr;
     240         230 :         CachedAddr = *CachedAddrOrErr;
     241             :         assert(CachedAddr && "Symbol could not be materialized.");
     242             :       } else
     243           0 :         return CachedAddrOrErr.takeError();
     244             :     }
     245         776 :     return CachedAddr;
     246             :   }
     247             : 
     248             :   JITSymbolFlags getFlags() const { return Flags; }
     249             : 
     250             : private:
     251             :   GetAddressFtor GetAddress;
     252             :   union {
     253             :     JITTargetAddress CachedAddr;
     254             :     Error Err;
     255             :   };
     256             :   JITSymbolFlags Flags;
     257             : };
     258             : 
     259             : /// \brief Symbol resolution.
     260             : class JITSymbolResolver {
     261             : public:
     262             :   virtual ~JITSymbolResolver() = default;
     263             : 
     264             :   /// This method returns the address of the specified symbol if it exists
     265             :   /// within the logical dynamic library represented by this JITSymbolResolver.
     266             :   /// Unlike findSymbol, queries through this interface should return addresses
     267             :   /// for hidden symbols.
     268             :   ///
     269             :   /// This is of particular importance for the Orc JIT APIs, which support lazy
     270             :   /// compilation by breaking up modules: Each of those broken out modules
     271             :   /// must be able to resolve hidden symbols provided by the others. Clients
     272             :   /// writing memory managers for MCJIT can usually ignore this method.
     273             :   ///
     274             :   /// This method will be queried by RuntimeDyld when checking for previous
     275             :   /// definitions of common symbols.
     276             :   virtual JITSymbol findSymbolInLogicalDylib(const std::string &Name) = 0;
     277             : 
     278             :   /// This method returns the address of the specified function or variable.
     279             :   /// It is used to resolve symbols during module linking.
     280             :   ///
     281             :   /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will
     282             :   /// skip all relocations for that symbol, and the client will be responsible
     283             :   /// for handling them manually.
     284             :   virtual JITSymbol findSymbol(const std::string &Name) = 0;
     285             : 
     286             : private:
     287             :   virtual void anchor();
     288             : };
     289             : 
     290             : } // end namespace llvm
     291             : 
     292             : #endif // LLVM_EXECUTIONENGINE_JITSYMBOL_H

Generated by: LCOV version 1.13