OrcABISupport.h 18 KB

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