LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - OrcABISupport.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 11 19 57.9 %
Date: 2018-10-20 13:21:21 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- OrcABISupport.h - ABI support code -----------------------*- 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             : // ABI specific code for Orc, e.g. callback assembly.
      11             : //
      12             : // ABI classes should be part of the JIT *target* process, not the host
      13             : // process (except where you're doing hosted JITing and the two are one and the
      14             : // same).
      15             : //
      16             : //===----------------------------------------------------------------------===//
      17             : 
      18             : #ifndef LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
      19             : #define LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
      20             : 
      21             : #include "llvm/ExecutionEngine/JITSymbol.h"
      22             : #include "llvm/Support/Error.h"
      23             : #include "llvm/Support/ErrorHandling.h"
      24             : #include "llvm/Support/Memory.h"
      25             : #include <algorithm>
      26             : #include <cstdint>
      27             : 
      28             : namespace llvm {
      29             : namespace orc {
      30             : 
      31             : /// Generic ORC ABI support.
      32             : ///
      33             : /// This class can be substituted as the target architecure support class for
      34             : /// ORC templates that require one (e.g. IndirectStubsManagers). It does not
      35             : /// support lazy JITing however, and any attempt to use that functionality
      36             : /// will result in execution of an llvm_unreachable.
      37             : class OrcGenericABI {
      38             : public:
      39             :   static const unsigned PointerSize = sizeof(uintptr_t);
      40             :   static const unsigned TrampolineSize = 1;
      41             :   static const unsigned ResolverCodeSize = 1;
      42             : 
      43             :   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
      44             :                                             void *TrampolineId);
      45             : 
      46             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
      47             :                                 void *CallbackMgr) {
      48             :     llvm_unreachable("writeResolverCode is not supported by the generic host "
      49             :                      "support class");
      50             :   }
      51             : 
      52             :   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
      53             :                                unsigned NumTrampolines) {
      54             :     llvm_unreachable("writeTrampolines is not supported by the generic host "
      55             :                      "support class");
      56             :   }
      57             : 
      58             :   class IndirectStubsInfo {
      59             :   public:
      60             :     const static unsigned StubSize = 1;
      61             : 
      62           0 :     unsigned getNumStubs() const { llvm_unreachable("Not supported"); }
      63           0 :     void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); }
      64           0 :     void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
      65             :   };
      66             : 
      67           0 :   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
      68             :                                       unsigned MinStubs, void *InitialPtrVal) {
      69           0 :     llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
      70             :                      "host support class");
      71             :   }
      72             : };
      73             : 
      74             : /// Provide information about stub blocks generated by the
      75             : ///        makeIndirectStubsBlock function.
      76          14 : template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
      77             : public:
      78             :   const static unsigned StubSize = StubSizeVal;
      79             : 
      80          14 :   GenericIndirectStubsInfo() = default;
      81          14 :   GenericIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
      82             :       : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
      83          14 :   GenericIndirectStubsInfo(GenericIndirectStubsInfo &&Other)
      84          14 :       : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
      85          14 :     Other.NumStubs = 0;
      86             :   }
      87             : 
      88             :   GenericIndirectStubsInfo &operator=(GenericIndirectStubsInfo &&Other) {
      89          14 :     NumStubs = Other.NumStubs;
      90          14 :     Other.NumStubs = 0;
      91             :     StubsMem = std::move(Other.StubsMem);
      92             :     return *this;
      93             :   }
      94             : 
      95             :   /// Number of stubs in this block.
      96           0 :   unsigned getNumStubs() const { return NumStubs; }
      97             : 
      98             :   /// Get a pointer to the stub at the given index, which must be in
      99             :   ///        the range 0 .. getNumStubs() - 1.
     100             :   void *getStub(unsigned Idx) const {
     101          21 :     return static_cast<char *>(StubsMem.base()) + Idx * StubSize;
     102             :   }
     103             : 
     104             :   /// Get a pointer to the implementation-pointer at the given index,
     105             :   ///        which must be in the range 0 .. getNumStubs() - 1.
     106             :   void **getPtr(unsigned Idx) const {
     107          41 :     char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
     108          41 :     return reinterpret_cast<void **>(PtrsBase) + Idx;
     109             :   }
     110             : 
     111             : private:
     112             :   unsigned NumStubs = 0;
     113             :   sys::OwningMemoryBlock StubsMem;
     114             : };
     115             : 
     116             : class OrcAArch64 {
     117             : public:
     118             :   static const unsigned PointerSize = 8;
     119             :   static const unsigned TrampolineSize = 12;
     120             :   static const unsigned ResolverCodeSize = 0x120;
     121             : 
     122             :   using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
     123             : 
     124             :   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
     125             :                                             void *TrampolineId);
     126             : 
     127             :   /// Write the resolver code into the given memory. The user is be
     128             :   ///        responsible for allocating the memory and setting permissions.
     129             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
     130             :                                 void *CallbackMgr);
     131             : 
     132             :   /// Write the requsted number of trampolines into the given memory,
     133             :   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
     134             :   ///        trampolines.
     135             :   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
     136             :                                unsigned NumTrampolines);
     137             : 
     138             :   /// Emit at least MinStubs worth of indirect call stubs, rounded out to
     139             :   ///        the nearest page size.
     140             :   ///
     141             :   ///   E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
     142             :   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
     143             :   /// will return a block of 1024 (2-pages worth).
     144             :   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
     145             :                                       unsigned MinStubs, void *InitialPtrVal);
     146             : };
     147             : 
     148             : /// X86_64 code that's common to all ABIs.
     149             : ///
     150             : /// X86_64 supports lazy JITing.
     151             : class OrcX86_64_Base {
     152             : public:
     153             :   static const unsigned PointerSize = 8;
     154             :   static const unsigned TrampolineSize = 8;
     155             : 
     156             :   using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
     157             : 
     158             :   /// Write the requsted number of trampolines into the given memory,
     159             :   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
     160             :   ///        trampolines.
     161             :   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
     162             :                                unsigned NumTrampolines);
     163             : 
     164             :   /// Emit at least MinStubs worth of indirect call stubs, rounded out to
     165             :   ///        the nearest page size.
     166             :   ///
     167             :   ///   E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
     168             :   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
     169             :   /// will return a block of 1024 (2-pages worth).
     170             :   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
     171             :                                       unsigned MinStubs, void *InitialPtrVal);
     172             : };
     173             : 
     174             : /// X86_64 support for SysV ABI (Linux, MacOSX).
     175             : ///
     176             : /// X86_64_SysV supports lazy JITing.
     177             : class OrcX86_64_SysV : public OrcX86_64_Base {
     178             : public:
     179             :   static const unsigned ResolverCodeSize = 0x6C;
     180             : 
     181             :   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
     182             :                                             void *TrampolineId);
     183             : 
     184             :   /// Write the resolver code into the given memory. The user is be
     185             :   ///        responsible for allocating the memory and setting permissions.
     186             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
     187             :                                 void *CallbackMgr);
     188             : };
     189             : 
     190             : /// X86_64 support for Win32.
     191             : ///
     192             : /// X86_64_Win32 supports lazy JITing.
     193             : class OrcX86_64_Win32 : public OrcX86_64_Base {
     194             : public:
     195             :   static const unsigned ResolverCodeSize = 0x74;
     196             : 
     197             :   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
     198             :                                             void *TrampolineId);
     199             : 
     200             :   /// Write the resolver code into the given memory. The user is be
     201             :   ///        responsible for allocating the memory and setting permissions.
     202             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
     203             :                                 void *CallbackMgr);
     204             : };
     205             : 
     206             : /// I386 support.
     207             : ///
     208             : /// I386 supports lazy JITing.
     209             : class OrcI386 {
     210             : public:
     211             :   static const unsigned PointerSize = 4;
     212             :   static const unsigned TrampolineSize = 8;
     213             :   static const unsigned ResolverCodeSize = 0x4a;
     214             : 
     215             :   using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
     216             : 
     217             :   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
     218             :                                             void *TrampolineId);
     219             : 
     220             :   /// Write the resolver code into the given memory. The user is be
     221             :   ///        responsible for allocating the memory and setting permissions.
     222             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
     223             :                                 void *CallbackMgr);
     224             : 
     225             :   /// Write the requsted number of trampolines into the given memory,
     226             :   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
     227             :   ///        trampolines.
     228             :   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
     229             :                                unsigned NumTrampolines);
     230             : 
     231             :   /// Emit at least MinStubs worth of indirect call stubs, rounded out to
     232             :   ///        the nearest page size.
     233             :   ///
     234             :   ///   E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
     235             :   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
     236             :   /// will return a block of 1024 (2-pages worth).
     237             :   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
     238             :                                       unsigned MinStubs, void *InitialPtrVal);
     239             : };
     240             : 
     241             : // @brief Mips32 support.
     242             : //
     243             : // Mips32 supports lazy JITing.
     244             : class OrcMips32_Base {
     245             : public:
     246             :   static const unsigned PointerSize = 4;
     247             :   static const unsigned TrampolineSize = 20;
     248             :   static const unsigned ResolverCodeSize = 0xfc;
     249             :   using IndirectStubsInfo = GenericIndirectStubsInfo<16>;
     250             : 
     251             :   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
     252             :                                             void *TrampolineId);
     253             :   /// @brief Write the requsted number of trampolines into the given memory,
     254             :   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
     255             :   ///        trampolines.
     256             :   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
     257             : 
     258             :   /// @brief Write the resolver code into the given memory. The user is be
     259             :   ///        responsible for allocating the memory and setting permissions.
     260             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr, bool isBigEndian);
     261             :   /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
     262             :   ///        the nearest page size.
     263             :   ///
     264             :   ///   E.g. Asking for 4 stubs on Mips32, where stubs are 8-bytes, with 4k
     265             :   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
     266             :   /// will return a block of 1024 (2-pages worth).
     267             :   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
     268             : };
     269             : 
     270             : 
     271             : class OrcMips32Le : public OrcMips32_Base {
     272             : public:
     273             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
     274           0 :   { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, false); }
     275             : };
     276             : 
     277             : class OrcMips32Be : public OrcMips32_Base {
     278             : public:
     279             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
     280           0 :   { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, true); }
     281             : };
     282             : 
     283             : // @brief Mips64 support.
     284             : //
     285             : // Mips64 supports lazy JITing.
     286             : class OrcMips64 {
     287             : public:
     288             :   static const unsigned PointerSize = 8;
     289             :   static const unsigned TrampolineSize = 40;
     290             :   static const unsigned ResolverCodeSize = 0x11C;
     291             : 
     292             :   using IndirectStubsInfo = GenericIndirectStubsInfo<32>;
     293             :   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
     294             :                                             void *TrampolineId);
     295             :   /// @brief Write the resolver code into the given memory. The user is be
     296             :   ///        responsible for allocating the memory and setting permissions.
     297             :   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr);
     298             : 
     299             :   /// @brief Write the requsted number of trampolines into the given memory,
     300             :   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
     301             :   ///        trampolines.
     302             :   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
     303             : 
     304             :   /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
     305             :   ///        the nearest page size.
     306             :   ///
     307             :   ///   E.g. Asking for 4 stubs on Mips64, where stubs are 8-bytes, with 4k
     308             :   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
     309             :   /// will return a block of 1024 (2-pages worth).
     310             :   static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
     311             : };
     312             : 
     313             :  } // end namespace orc
     314             :  } // end namespace llvm
     315             : #endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H

Generated by: LCOV version 1.13