Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- OrcABISupport.h - ABI support code -----------------------*- 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. // ABI specific code for Orc, e.g. callback assembly.
  10. //
  11. // ABI classes should be part of the JIT *target* process, not the host
  12. // process (except where you're doing hosted JITing and the two are one and the
  13. // same).
  14. //
  15. //===----------------------------------------------------------------------===//
  16.  
  17. #ifndef LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
  18. #define LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
  19.  
  20. #include "llvm/ExecutionEngine/JITSymbol.h"
  21. #include "llvm/Support/Error.h"
  22. #include "llvm/Support/ErrorHandling.h"
  23. #include "llvm/Support/MathExtras.h"
  24. #include <cstdint>
  25.  
  26. namespace llvm {
  27. namespace orc {
  28.  
  29. struct IndirectStubsAllocationSizes {
  30.   uint64_t StubBytes = 0;
  31.   uint64_t PointerBytes = 0;
  32.   unsigned NumStubs = 0;
  33. };
  34.  
  35. template <typename ORCABI>
  36. IndirectStubsAllocationSizes
  37. getIndirectStubsBlockSizes(unsigned MinStubs, unsigned RoundToMultipleOf = 0) {
  38.   assert(
  39.       (RoundToMultipleOf == 0 || (RoundToMultipleOf % ORCABI::StubSize == 0)) &&
  40.       "RoundToMultipleOf is not a multiple of stub size");
  41.   uint64_t StubBytes = MinStubs * ORCABI::StubSize;
  42.   if (RoundToMultipleOf)
  43.     StubBytes = alignTo(StubBytes, RoundToMultipleOf);
  44.   unsigned NumStubs = StubBytes / ORCABI::StubSize;
  45.   uint64_t PointerBytes = NumStubs * ORCABI::PointerSize;
  46.   return {StubBytes, PointerBytes, NumStubs};
  47. }
  48.  
  49. /// Generic ORC ABI support.
  50. ///
  51. /// This class can be substituted as the target architecture support class for
  52. /// ORC templates that require one (e.g. IndirectStubsManagers). It does not
  53. /// support lazy JITing however, and any attempt to use that functionality
  54. /// will result in execution of an llvm_unreachable.
  55. class OrcGenericABI {
  56. public:
  57.   static constexpr unsigned PointerSize = sizeof(uintptr_t);
  58.   static constexpr unsigned TrampolineSize = 1;
  59.   static constexpr unsigned StubSize = 1;
  60.   static constexpr unsigned StubToPointerMaxDisplacement = 1;
  61.   static constexpr unsigned ResolverCodeSize = 1;
  62.  
  63.   static void writeResolverCode(char *ResolveWorkingMem,
  64.                                 JITTargetAddress ResolverTargetAddr,
  65.                                 JITTargetAddress ReentryFnAddr,
  66.                                 JITTargetAddress ReentryCtxAddr) {
  67.     llvm_unreachable("writeResolverCode is not supported by the generic host "
  68.                      "support class");
  69.   }
  70.  
  71.   static void writeTrampolines(char *TrampolineBlockWorkingMem,
  72.                                JITTargetAddress TrampolineBlockTargetAddr,
  73.                                JITTargetAddress ResolverAddr,
  74.                                unsigned NumTrampolines) {
  75.     llvm_unreachable("writeTrampolines is not supported by the generic host "
  76.                      "support class");
  77.   }
  78.  
  79.   static void writeIndirectStubsBlock(
  80.       char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
  81.       JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) {
  82.     llvm_unreachable(
  83.         "writeIndirectStubsBlock is not supported by the generic host "
  84.         "support class");
  85.   }
  86. };
  87.  
  88. class OrcAArch64 {
  89. public:
  90.   static constexpr unsigned PointerSize = 8;
  91.   static constexpr unsigned TrampolineSize = 12;
  92.   static constexpr unsigned StubSize = 8;
  93.   static constexpr unsigned StubToPointerMaxDisplacement = 1U << 27;
  94.   static constexpr unsigned ResolverCodeSize = 0x120;
  95.  
  96.   /// Write the resolver code into the given memory. The user is
  97.   /// responsible for allocating the memory and setting permissions.
  98.   ///
  99.   /// ReentryFnAddr should be the address of a function whose signature matches
  100.   /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
  101.   /// argument of writeResolverCode will be passed as the second argument to
  102.   /// the function at ReentryFnAddr.
  103.   static void writeResolverCode(char *ResolverWorkingMem,
  104.                                 JITTargetAddress ResolverTargetAddress,
  105.                                 JITTargetAddress ReentryFnAddr,
  106.                                 JITTargetAddress RentryCtxAddr);
  107.  
  108.   /// Write the requested number of trampolines into the given memory,
  109.   /// which must be big enough to hold 1 pointer, plus NumTrampolines
  110.   /// trampolines.
  111.   static void writeTrampolines(char *TrampolineBlockWorkingMem,
  112.                                JITTargetAddress TrampolineBlockTargetAddress,
  113.                                JITTargetAddress ResolverAddr,
  114.                                unsigned NumTrampolines);
  115.  
  116.   /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
  117.   /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
  118.   /// Nth stub using the Nth pointer in memory starting at
  119.   /// PointersBlockTargetAddress.
  120.   static void writeIndirectStubsBlock(
  121.       char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
  122.       JITTargetAddress PointersBlockTargetAddress, unsigned MinStubs);
  123. };
  124.  
  125. /// X86_64 code that's common to all ABIs.
  126. ///
  127. /// X86_64 supports lazy JITing.
  128. class OrcX86_64_Base {
  129. public:
  130.   static constexpr unsigned PointerSize = 8;
  131.   static constexpr unsigned TrampolineSize = 8;
  132.   static constexpr unsigned StubSize = 8;
  133.   static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
  134.  
  135.   /// Write the requested number of trampolines into the given memory,
  136.   /// which must be big enough to hold 1 pointer, plus NumTrampolines
  137.   /// trampolines.
  138.   static void writeTrampolines(char *TrampolineBlockWorkingMem,
  139.                                JITTargetAddress TrampolineBlockTargetAddress,
  140.                                JITTargetAddress ResolverAddr,
  141.                                unsigned NumTrampolines);
  142.  
  143.   /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
  144.   /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
  145.   /// Nth stub using the Nth pointer in memory starting at
  146.   /// PointersBlockTargetAddress.
  147.   static void writeIndirectStubsBlock(
  148.       char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
  149.       JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
  150. };
  151.  
  152. /// X86_64 support for SysV ABI (Linux, MacOSX).
  153. ///
  154. /// X86_64_SysV supports lazy JITing.
  155. class OrcX86_64_SysV : public OrcX86_64_Base {
  156. public:
  157.   static constexpr unsigned ResolverCodeSize = 0x6C;
  158.  
  159.   /// Write the resolver code into the given memory. The user is
  160.   /// responsible for allocating the memory and setting permissions.
  161.   ///
  162.   /// ReentryFnAddr should be the address of a function whose signature matches
  163.   /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
  164.   /// argument of writeResolverCode will be passed as the second argument to
  165.   /// the function at ReentryFnAddr.
  166.   static void writeResolverCode(char *ResolverWorkingMem,
  167.                                 JITTargetAddress ResolverTargetAddress,
  168.                                 JITTargetAddress ReentryFnAddr,
  169.                                 JITTargetAddress ReentryCtxAddr);
  170. };
  171.  
  172. /// X86_64 support for Win32.
  173. ///
  174. /// X86_64_Win32 supports lazy JITing.
  175. class OrcX86_64_Win32 : public OrcX86_64_Base {
  176. public:
  177.   static constexpr unsigned ResolverCodeSize = 0x74;
  178.  
  179.   /// Write the resolver code into the given memory. The user is
  180.   /// responsible for allocating the memory and setting permissions.
  181.   ///
  182.   /// ReentryFnAddr should be the address of a function whose signature matches
  183.   /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
  184.   /// argument of writeResolverCode will be passed as the second argument to
  185.   /// the function at ReentryFnAddr.
  186.   static void writeResolverCode(char *ResolverWorkingMem,
  187.                                 JITTargetAddress ResolverTargetAddress,
  188.                                 JITTargetAddress ReentryFnAddr,
  189.                                 JITTargetAddress ReentryCtxAddr);
  190. };
  191.  
  192. /// I386 support.
  193. ///
  194. /// I386 supports lazy JITing.
  195. class OrcI386 {
  196. public:
  197.   static constexpr unsigned PointerSize = 4;
  198.   static constexpr unsigned TrampolineSize = 8;
  199.   static constexpr unsigned StubSize = 8;
  200.   static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
  201.   static constexpr unsigned ResolverCodeSize = 0x4a;
  202.  
  203.   /// Write the resolver code into the given memory. The user is
  204.   /// responsible for allocating the memory and setting permissions.
  205.   ///
  206.   /// ReentryFnAddr should be the address of a function whose signature matches
  207.   /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
  208.   /// argument of writeResolverCode will be passed as the second argument to
  209.   /// the function at ReentryFnAddr.
  210.   static void writeResolverCode(char *ResolverWorkingMem,
  211.                                 JITTargetAddress ResolverTargetAddress,
  212.                                 JITTargetAddress ReentryFnAddr,
  213.                                 JITTargetAddress ReentryCtxAddr);
  214.  
  215.   /// Write the requested number of trampolines into the given memory,
  216.   /// which must be big enough to hold 1 pointer, plus NumTrampolines
  217.   /// trampolines.
  218.   static void writeTrampolines(char *TrampolineBlockWorkingMem,
  219.                                JITTargetAddress TrampolineBlockTargetAddress,
  220.                                JITTargetAddress ResolverAddr,
  221.                                unsigned NumTrampolines);
  222.  
  223.   /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
  224.   /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
  225.   /// Nth stub using the Nth pointer in memory starting at
  226.   /// PointersBlockTargetAddress.
  227.   static void writeIndirectStubsBlock(
  228.       char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
  229.       JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
  230. };
  231.  
  232. // @brief Mips32 support.
  233. //
  234. // Mips32 supports lazy JITing.
  235. class OrcMips32_Base {
  236. public:
  237.   static constexpr unsigned PointerSize = 4;
  238.   static constexpr unsigned TrampolineSize = 20;
  239.   static constexpr unsigned StubSize = 8;
  240.   static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
  241.   static constexpr unsigned ResolverCodeSize = 0xfc;
  242.  
  243.   /// Write the requested number of trampolines into the given memory,
  244.   /// which must be big enough to hold 1 pointer, plus NumTrampolines
  245.   /// trampolines.
  246.   static void writeTrampolines(char *TrampolineBlockWorkingMem,
  247.                                JITTargetAddress TrampolineBlockTargetAddress,
  248.                                JITTargetAddress ResolverAddr,
  249.                                unsigned NumTrampolines);
  250.  
  251.   /// Write the resolver code into the given memory. The user is
  252.   /// responsible for allocating the memory and setting permissions.
  253.   ///
  254.   /// ReentryFnAddr should be the address of a function whose signature matches
  255.   /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
  256.   /// argument of writeResolverCode will be passed as the second argument to
  257.   /// the function at ReentryFnAddr.
  258.   static void writeResolverCode(char *ResolverBlockWorkingMem,
  259.                                 JITTargetAddress ResolverBlockTargetAddress,
  260.                                 JITTargetAddress ReentryFnAddr,
  261.                                 JITTargetAddress ReentryCtxAddr,
  262.                                 bool isBigEndian);
  263.   /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
  264.   /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
  265.   /// Nth stub using the Nth pointer in memory starting at
  266.   /// PointersBlockTargetAddress.
  267.   static void writeIndirectStubsBlock(
  268.       char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
  269.       JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
  270. };
  271.  
  272. class OrcMips32Le : public OrcMips32_Base {
  273. public:
  274.   static void writeResolverCode(char *ResolverWorkingMem,
  275.                                 JITTargetAddress ResolverTargetAddress,
  276.                                 JITTargetAddress ReentryFnAddr,
  277.                                 JITTargetAddress ReentryCtxAddr) {
  278.     OrcMips32_Base::writeResolverCode(ResolverWorkingMem, ResolverTargetAddress,
  279.                                       ReentryFnAddr, ReentryCtxAddr, false);
  280.   }
  281. };
  282.  
  283. class OrcMips32Be : public OrcMips32_Base {
  284. public:
  285.   static void writeResolverCode(char *ResolverWorkingMem,
  286.                                 JITTargetAddress ResolverTargetAddress,
  287.                                 JITTargetAddress ReentryFnAddr,
  288.                                 JITTargetAddress ReentryCtxAddr) {
  289.     OrcMips32_Base::writeResolverCode(ResolverWorkingMem, ResolverTargetAddress,
  290.                                       ReentryFnAddr, ReentryCtxAddr, true);
  291.   }
  292. };
  293.  
  294. // @brief Mips64 support.
  295. //
  296. // Mips64 supports lazy JITing.
  297. class OrcMips64 {
  298. public:
  299.   static constexpr unsigned PointerSize = 8;
  300.   static constexpr unsigned TrampolineSize = 40;
  301.   static constexpr unsigned StubSize = 32;
  302.   static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
  303.   static constexpr unsigned ResolverCodeSize = 0x120;
  304.  
  305.   /// Write the resolver code into the given memory. The user is
  306.   /// responsible for allocating the memory and setting permissions.
  307.   ///
  308.   /// ReentryFnAddr should be the address of a function whose signature matches
  309.   /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
  310.   /// argument of writeResolverCode will be passed as the second argument to
  311.   /// the function at ReentryFnAddr.
  312.   static void writeResolverCode(char *ResolverWorkingMem,
  313.                                 JITTargetAddress ResolverTargetAddress,
  314.                                 JITTargetAddress ReentryFnAddr,
  315.                                 JITTargetAddress ReentryCtxAddr);
  316.  
  317.   /// Write the requested number of trampolines into the given memory,
  318.   /// which must be big enough to hold 1 pointer, plus NumTrampolines
  319.   /// trampolines.
  320.   static void writeTrampolines(char *TrampolineBlockWorkingMem,
  321.                                JITTargetAddress TrampolineBlockTargetAddress,
  322.                                JITTargetAddress ResolverFnAddr,
  323.                                unsigned NumTrampolines);
  324.   /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
  325.   /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
  326.   /// Nth stub using the Nth pointer in memory starting at
  327.   /// PointersBlockTargetAddress.
  328.   static void writeIndirectStubsBlock(
  329.       char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
  330.       JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
  331. };
  332.  
  333. // @brief riscv64 support.
  334. //
  335. // RISC-V 64 supports lazy JITing.
  336. class OrcRiscv64 {
  337. public:
  338.   static constexpr unsigned PointerSize = 8;
  339.   static constexpr unsigned TrampolineSize = 16;
  340.   static constexpr unsigned StubSize = 16;
  341.   static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
  342.   static constexpr unsigned ResolverCodeSize = 0x148;
  343.  
  344.   /// Write the resolver code into the given memory. The user is
  345.   /// responsible for allocating the memory and setting permissions.
  346.   ///
  347.   /// ReentryFnAddr should be the address of a function whose signature matches
  348.   /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
  349.   /// argument of writeResolverCode will be passed as the second argument to
  350.   /// the function at ReentryFnAddr.
  351.   static void writeResolverCode(char *ResolverWorkingMem,
  352.                                 JITTargetAddress ResolverTargetAddress,
  353.                                 JITTargetAddress ReentryFnAddr,
  354.                                 JITTargetAddress ReentryCtxAddr);
  355.  
  356.   /// Write the requested number of trampolines into the given memory,
  357.   /// which must be big enough to hold 1 pointer, plus NumTrampolines
  358.   /// trampolines.
  359.   static void writeTrampolines(char *TrampolineBlockWorkingMem,
  360.                                JITTargetAddress TrampolineBlockTargetAddress,
  361.                                JITTargetAddress ResolverFnAddr,
  362.                                unsigned NumTrampolines);
  363.   /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
  364.   /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
  365.   /// Nth stub using the Nth pointer in memory starting at
  366.   /// PointersBlockTargetAddress.
  367.   static void writeIndirectStubsBlock(
  368.       char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
  369.       JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
  370. };
  371.  
  372. // @brief loongarch64 support.
  373. //
  374. // LoongArch 64 supports lazy JITing.
  375. class OrcLoongArch64 {
  376. public:
  377.   static constexpr unsigned PointerSize = 8;
  378.   static constexpr unsigned TrampolineSize = 16;
  379.   static constexpr unsigned StubSize = 16;
  380.   static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31;
  381.   static constexpr unsigned ResolverCodeSize = 0xc8;
  382.  
  383.   /// Write the resolver code into the given memory. The user is
  384.   /// responsible for allocating the memory and setting permissions.
  385.   ///
  386.   /// ReentryFnAddr should be the address of a function whose signature matches
  387.   /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr
  388.   /// argument of writeResolverCode will be passed as the second argument to
  389.   /// the function at ReentryFnAddr.
  390.   static void writeResolverCode(char *ResolverWorkingMem,
  391.                                 JITTargetAddress ResolverTargetAddress,
  392.                                 JITTargetAddress ReentryFnAddr,
  393.                                 JITTargetAddress ReentryCtxAddr);
  394.  
  395.   /// Write the requested number of trampolines into the given memory,
  396.   /// which must be big enough to hold 1 pointer, plus NumTrampolines
  397.   /// trampolines.
  398.   static void writeTrampolines(char *TrampolineBlockWorkingMem,
  399.                                JITTargetAddress TrampolineBlockTargetAddress,
  400.                                JITTargetAddress ResolverFnAddr,
  401.                                unsigned NumTrampolines);
  402.  
  403.   /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
  404.   /// Stubs will be written as if linked at StubsBlockTargetAddress, with the
  405.   /// Nth stub using the Nth pointer in memory starting at
  406.   /// PointersBlockTargetAddress.
  407.   static void writeIndirectStubsBlock(
  408.       char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress,
  409.       JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs);
  410. };
  411.  
  412. } // end namespace orc
  413. } // end namespace llvm
  414.  
  415. #endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H
  416.