asmjit 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/Rakefile +5 -3
  4. data/asmjit.gemspec +1 -3
  5. data/ext/asmjit/asmjit/.editorconfig +10 -0
  6. data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
  7. data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
  8. data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
  9. data/ext/asmjit/asmjit/.gitignore +6 -0
  10. data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
  11. data/ext/asmjit/asmjit/LICENSE.md +17 -0
  12. data/ext/asmjit/asmjit/README.md +69 -0
  13. data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
  14. data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
  15. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
  16. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
  17. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
  18. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
  19. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
  20. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
  21. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
  22. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
  23. data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
  24. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
  25. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
  26. data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
  27. data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
  28. data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
  29. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
  30. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
  31. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
  32. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
  33. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
  34. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
  35. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
  36. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
  37. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
  38. data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
  39. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
  40. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
  41. data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
  42. data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
  43. data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
  44. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
  45. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
  46. data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
  47. data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
  48. data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
  49. data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
  50. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
  51. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
  52. data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
  53. data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
  54. data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
  55. data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
  56. data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
  57. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
  58. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
  59. data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
  60. data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
  61. data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
  62. data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
  63. data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
  64. data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
  65. data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
  66. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
  67. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
  68. data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
  69. data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
  70. data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
  71. data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
  72. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
  73. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
  74. data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
  75. data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
  76. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
  77. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
  78. data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
  79. data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
  80. data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
  81. data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
  82. data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
  83. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
  84. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
  85. data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
  86. data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
  87. data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
  88. data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
  89. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
  90. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
  91. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
  92. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
  93. data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
  94. data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
  95. data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
  96. data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
  97. data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
  98. data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
  99. data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
  100. data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
  101. data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
  102. data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
  103. data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
  104. data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
  105. data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
  106. data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
  107. data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
  108. data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
  109. data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
  110. data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
  111. data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
  112. data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
  113. data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
  114. data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
  115. data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
  116. data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
  117. data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
  118. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
  119. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
  120. data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
  121. data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
  122. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
  123. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
  124. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
  125. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
  126. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
  127. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
  128. data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
  129. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
  130. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
  131. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
  132. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
  133. data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
  134. data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
  135. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
  136. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
  137. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
  138. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
  139. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
  140. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
  141. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
  142. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
  143. data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
  144. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
  145. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
  146. data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
  147. data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
  148. data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
  149. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
  150. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
  151. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
  152. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
  153. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
  154. data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
  155. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
  156. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
  157. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
  158. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
  159. data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
  160. data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
  161. data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
  162. data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
  163. data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
  164. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
  165. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
  166. data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
  167. data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
  168. data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
  169. data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
  170. data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
  171. data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
  172. data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
  173. data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
  174. data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
  175. data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
  176. data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
  177. data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
  178. data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
  179. data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
  180. data/ext/asmjit/asmjit/test/broken.cpp +312 -0
  181. data/ext/asmjit/asmjit/test/broken.h +148 -0
  182. data/ext/asmjit/asmjit/test/cmdline.h +61 -0
  183. data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
  184. data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
  185. data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
  186. data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
  187. data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
  188. data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
  189. data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
  190. data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
  191. data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
  192. data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
  193. data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
  194. data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
  195. data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
  196. data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
  197. data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
  198. data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
  199. data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
  200. data/ext/asmjit/asmjit.cc +167 -30
  201. data/ext/asmjit/extconf.rb +9 -9
  202. data/lib/asmjit/version.rb +1 -1
  203. data/lib/asmjit.rb +14 -4
  204. metadata +198 -17
@@ -0,0 +1,852 @@
1
+ // This file is part of AsmJit project <https://asmjit.com>
2
+ //
3
+ // See asmjit.h or LICENSE.md for license and copyright information
4
+ // SPDX-License-Identifier: Zlib
5
+
6
+ #include "../core/api-build_p.h"
7
+ #if !defined(ASMJIT_NO_AARCH64) && !defined(ASMJIT_NO_COMPILER)
8
+
9
+ #include "../core/cpuinfo.h"
10
+ #include "../core/support.h"
11
+ #include "../core/type.h"
12
+ #include "../arm/a64assembler.h"
13
+ #include "../arm/a64compiler.h"
14
+ #include "../arm/a64emithelper_p.h"
15
+ #include "../arm/a64instapi_p.h"
16
+ #include "../arm/a64instdb_p.h"
17
+ #include "../arm/a64rapass_p.h"
18
+
19
+ ASMJIT_BEGIN_SUB_NAMESPACE(a64)
20
+
21
+ // a64::ARMRAPass - Helpers
22
+ // ========================
23
+
24
+ // TODO: [ARM] These should be shared with all backends.
25
+ ASMJIT_MAYBE_UNUSED
26
+ static inline uint64_t raImmMaskFromSize(uint32_t size) noexcept {
27
+ ASMJIT_ASSERT(size > 0 && size < 256);
28
+ static const uint64_t masks[] = {
29
+ 0x00000000000000FFu, // 1
30
+ 0x000000000000FFFFu, // 2
31
+ 0x00000000FFFFFFFFu, // 4
32
+ 0xFFFFFFFFFFFFFFFFu, // 8
33
+ 0x0000000000000000u, // 16
34
+ 0x0000000000000000u, // 32
35
+ 0x0000000000000000u, // 64
36
+ 0x0000000000000000u, // 128
37
+ 0x0000000000000000u // 256
38
+ };
39
+ return masks[Support::ctz(size)];
40
+ }
41
+
42
+ static const RegMask raConsecutiveLeadCountToRegMaskFilter[5] = {
43
+ 0xFFFFFFFFu, // [0] No consecutive.
44
+ 0x00000000u, // [1] Invalid, never used.
45
+ 0x7FFFFFFFu, // [2] 2 consecutive registers.
46
+ 0x3FFFFFFFu, // [3] 3 consecutive registers.
47
+ 0x1FFFFFFFu // [4] 4 consecutive registers.
48
+ };
49
+
50
+ static inline RATiedFlags raUseOutFlagsFromRWFlags(OpRWFlags rwFlags) noexcept {
51
+ static constexpr RATiedFlags map[] = {
52
+ RATiedFlags::kNone,
53
+ RATiedFlags::kRead | RATiedFlags::kUse, // kRead
54
+ RATiedFlags::kWrite | RATiedFlags::kOut, // kWrite
55
+ RATiedFlags::kRW | RATiedFlags::kUse, // kRW
56
+ };
57
+
58
+ return map[uint32_t(rwFlags & OpRWFlags::kRW)];
59
+ }
60
+
61
+ static inline RATiedFlags raRegRwFlags(OpRWFlags flags) noexcept {
62
+ return raUseOutFlagsFromRWFlags(flags);
63
+ }
64
+
65
+ static inline RATiedFlags raMemBaseRwFlags(OpRWFlags flags) noexcept {
66
+ constexpr uint32_t shift = Support::ConstCTZ<uint32_t(OpRWFlags::kMemBaseRW)>::value;
67
+ return raUseOutFlagsFromRWFlags(OpRWFlags(uint32_t(flags) >> shift) & OpRWFlags::kRW);
68
+ }
69
+
70
+ static inline RATiedFlags raMemIndexRwFlags(OpRWFlags flags) noexcept {
71
+ constexpr uint32_t shift = Support::ConstCTZ<uint32_t(OpRWFlags::kMemIndexRW)>::value;
72
+ return raUseOutFlagsFromRWFlags(OpRWFlags(uint32_t(flags) >> shift) & OpRWFlags::kRW);
73
+ }
74
+ // a64::RACFGBuilder
75
+ // =================
76
+
77
+ class RACFGBuilder : public RACFGBuilderT<RACFGBuilder> {
78
+ public:
79
+ Arch _arch;
80
+
81
+ inline RACFGBuilder(ARMRAPass* pass) noexcept
82
+ : RACFGBuilderT<RACFGBuilder>(pass),
83
+ _arch(pass->cc()->arch()) {}
84
+
85
+ inline Compiler* cc() const noexcept { return static_cast<Compiler*>(_cc); }
86
+
87
+ Error onInst(InstNode* inst, InstControlFlow& controlType, RAInstBuilder& ib) noexcept;
88
+
89
+ Error onBeforeInvoke(InvokeNode* invokeNode) noexcept;
90
+ Error onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept;
91
+
92
+ Error moveImmToRegArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_, BaseReg* out) noexcept;
93
+ Error moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_) noexcept;
94
+ Error moveRegToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const BaseReg& reg) noexcept;
95
+
96
+ Error onBeforeRet(FuncRetNode* funcRet) noexcept;
97
+ Error onRet(FuncRetNode* funcRet, RAInstBuilder& ib) noexcept;
98
+ };
99
+
100
+ // a64::RACFGBuilder - OnInst
101
+ // ==========================
102
+
103
+ // TODO: [ARM] This is just a workaround...
104
+ static InstControlFlow getControlFlowType(InstId instId) noexcept {
105
+ switch (BaseInst::extractRealId(instId)) {
106
+ case Inst::kIdB:
107
+ case Inst::kIdBr:
108
+ if (BaseInst::extractARMCondCode(instId) == CondCode::kAL)
109
+ return InstControlFlow::kJump;
110
+ else
111
+ return InstControlFlow::kBranch;
112
+ case Inst::kIdBl:
113
+ case Inst::kIdBlr:
114
+ return InstControlFlow::kCall;
115
+ case Inst::kIdCbz:
116
+ case Inst::kIdCbnz:
117
+ case Inst::kIdTbz:
118
+ case Inst::kIdTbnz:
119
+ return InstControlFlow::kBranch;
120
+ case Inst::kIdRet:
121
+ return InstControlFlow::kReturn;
122
+ default:
123
+ return InstControlFlow::kRegular;
124
+ }
125
+ }
126
+
127
+ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstBuilder& ib) noexcept {
128
+ InstRWInfo rwInfo;
129
+
130
+ if (Inst::isDefinedId(inst->realId())) {
131
+ InstId instId = inst->id();
132
+ uint32_t opCount = inst->opCount();
133
+ const Operand* opArray = inst->operands();
134
+ ASMJIT_PROPAGATE(InstInternal::queryRWInfo(_arch, inst->baseInst(), opArray, opCount, &rwInfo));
135
+
136
+ const InstDB::InstInfo& instInfo = InstDB::infoById(instId);
137
+ uint32_t singleRegOps = 0;
138
+
139
+ ib.addInstRWFlags(rwInfo.instFlags());
140
+
141
+ if (opCount) {
142
+ uint32_t consecutiveOffset = 0xFFFFFFFFu;
143
+ uint32_t consecutiveParent = Globals::kInvalidId;
144
+
145
+ for (uint32_t i = 0; i < opCount; i++) {
146
+ const Operand& op = opArray[i];
147
+ const OpRWInfo& opRwInfo = rwInfo.operand(i);
148
+
149
+ if (op.isReg()) {
150
+ // Register Operand
151
+ // ----------------
152
+ const Reg& reg = op.as<Reg>();
153
+
154
+ RATiedFlags flags = raRegRwFlags(opRwInfo.opFlags());
155
+ uint32_t vIndex = Operand::virtIdToIndex(reg.id());
156
+
157
+ if (vIndex < Operand::kVirtIdCount) {
158
+ RAWorkReg* workReg;
159
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg));
160
+
161
+ // Use RW instead of Write in case that not the whole register is overwritten. This is important for
162
+ // liveness as we cannot kill a register that will be used.
163
+ if ((flags & RATiedFlags::kRW) == RATiedFlags::kWrite) {
164
+ if (workReg->regByteMask() & ~(opRwInfo.writeByteMask() | opRwInfo.extendByteMask())) {
165
+ // Not write-only operation.
166
+ flags = (flags & ~RATiedFlags::kOut) | (RATiedFlags::kRead | RATiedFlags::kUse);
167
+ }
168
+ }
169
+
170
+ RegGroup group = workReg->group();
171
+
172
+ RegMask useRegs = _pass->_availableRegs[group];
173
+ RegMask outRegs = useRegs;
174
+
175
+ uint32_t useId = BaseReg::kIdBad;
176
+ uint32_t outId = BaseReg::kIdBad;
177
+
178
+ uint32_t useRewriteMask = 0;
179
+ uint32_t outRewriteMask = 0;
180
+
181
+ if (opRwInfo.consecutiveLeadCount()) {
182
+ // There must be a single consecutive register lead, otherwise the RW data is invalid.
183
+ if (consecutiveOffset != 0xFFFFFFFFu)
184
+ return DebugUtils::errored(kErrorInvalidState);
185
+
186
+ // A consecutive lead register cannot be used as a consecutive +1/+2/+3 register, the registers must be distinct.
187
+ if (RATiedReg::consecutiveDataFromFlags(flags) != 0)
188
+ return DebugUtils::errored(kErrorNotConsecutiveRegs);
189
+
190
+ flags |= RATiedFlags::kLeadConsecutive | RATiedReg::consecutiveDataToFlags(opRwInfo.consecutiveLeadCount() - 1);
191
+ consecutiveOffset = 0;
192
+
193
+ RegMask filter = raConsecutiveLeadCountToRegMaskFilter[opRwInfo.consecutiveLeadCount()];
194
+ if (Support::test(flags, RATiedFlags::kUse)) {
195
+ flags |= RATiedFlags::kUseConsecutive;
196
+ useRegs &= filter;
197
+ }
198
+ else {
199
+ flags |= RATiedFlags::kOutConsecutive;
200
+ outRegs &= filter;
201
+ }
202
+ }
203
+
204
+ if (Support::test(flags, RATiedFlags::kUse)) {
205
+ useRewriteMask = Support::bitMask(inst->getRewriteIndex(&reg._baseId));
206
+ if (opRwInfo.hasOpFlag(OpRWFlags::kRegPhysId)) {
207
+ useId = opRwInfo.physId();
208
+ flags |= RATiedFlags::kUseFixed;
209
+ }
210
+ else if (opRwInfo.hasOpFlag(OpRWFlags::kConsecutive)) {
211
+ if (consecutiveOffset == 0xFFFFFFFFu)
212
+ return DebugUtils::errored(kErrorInvalidState);
213
+ flags |= RATiedFlags::kUseConsecutive | RATiedReg::consecutiveDataToFlags(++consecutiveOffset);
214
+ }
215
+ }
216
+ else {
217
+ outRewriteMask = Support::bitMask(inst->getRewriteIndex(&reg._baseId));
218
+ if (opRwInfo.hasOpFlag(OpRWFlags::kRegPhysId)) {
219
+ outId = opRwInfo.physId();
220
+ flags |= RATiedFlags::kOutFixed;
221
+ }
222
+ else if (opRwInfo.hasOpFlag(OpRWFlags::kConsecutive)) {
223
+ if (consecutiveOffset == 0xFFFFFFFFu)
224
+ return DebugUtils::errored(kErrorInvalidState);
225
+ flags |= RATiedFlags::kOutConsecutive | RATiedReg::consecutiveDataToFlags(++consecutiveOffset);
226
+ }
227
+ }
228
+
229
+ // Special cases regarding element access.
230
+ if (reg.as<Vec>().hasElementIndex()) {
231
+ // Only the first 0..15 registers can be used if the register uses
232
+ // element accessor that accesses half-words (h[0..7] elements).
233
+ if (instInfo.hasFlag(InstDB::kInstFlagVH0_15) && reg.as<Vec>().elementType() == Vec::kElementTypeH) {
234
+ if (Support::test(flags, RATiedFlags::kUse))
235
+ useId &= 0x0000FFFFu;
236
+ else
237
+ outId &= 0x0000FFFFu;
238
+ }
239
+ }
240
+
241
+ ASMJIT_PROPAGATE(ib.add(workReg, flags, useRegs, useId, useRewriteMask, outRegs, outId, outRewriteMask, opRwInfo.rmSize(), consecutiveParent));
242
+ if (singleRegOps == i)
243
+ singleRegOps++;
244
+
245
+ if (Support::test(flags, RATiedFlags::kLeadConsecutive | RATiedFlags::kUseConsecutive | RATiedFlags::kOutConsecutive))
246
+ consecutiveParent = workReg->workId();
247
+ }
248
+ }
249
+ else if (op.isMem()) {
250
+ // Memory Operand
251
+ // --------------
252
+ const Mem& mem = op.as<Mem>();
253
+
254
+ if (mem.isRegHome()) {
255
+ RAWorkReg* workReg;
256
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(mem.baseId()), &workReg));
257
+ _pass->getOrCreateStackSlot(workReg);
258
+ }
259
+ else if (mem.hasBaseReg()) {
260
+ uint32_t vIndex = Operand::virtIdToIndex(mem.baseId());
261
+ if (vIndex < Operand::kVirtIdCount) {
262
+ RAWorkReg* workReg;
263
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg));
264
+
265
+ RATiedFlags flags = raMemBaseRwFlags(opRwInfo.opFlags());
266
+ RegGroup group = workReg->group();
267
+ RegMask allocable = _pass->_availableRegs[group];
268
+
269
+ // Base registers have never fixed id on ARM.
270
+ const uint32_t useId = BaseReg::kIdBad;
271
+ const uint32_t outId = BaseReg::kIdBad;
272
+
273
+ uint32_t useRewriteMask = 0;
274
+ uint32_t outRewriteMask = 0;
275
+
276
+ if (Support::test(flags, RATiedFlags::kUse))
277
+ useRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._baseId));
278
+ else
279
+ outRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._baseId));
280
+
281
+ ASMJIT_PROPAGATE(ib.add(workReg, flags, allocable, useId, useRewriteMask, allocable, outId, outRewriteMask));
282
+ }
283
+ }
284
+
285
+ if (mem.hasIndexReg()) {
286
+ uint32_t vIndex = Operand::virtIdToIndex(mem.indexId());
287
+ if (vIndex < Operand::kVirtIdCount) {
288
+ RAWorkReg* workReg;
289
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg));
290
+
291
+ RATiedFlags flags = raMemIndexRwFlags(opRwInfo.opFlags());
292
+ RegGroup group = workReg->group();
293
+ RegMask allocable = _pass->_availableRegs[group];
294
+
295
+ // Index registers have never fixed id on ARM.
296
+ const uint32_t useId = BaseReg::kIdBad;
297
+ const uint32_t outId = BaseReg::kIdBad;
298
+
299
+ uint32_t useRewriteMask = 0;
300
+ uint32_t outRewriteMask = 0;
301
+
302
+ if (Support::test(flags, RATiedFlags::kUse))
303
+ useRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._data[Operand::kDataMemIndexId]));
304
+ else
305
+ outRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._data[Operand::kDataMemIndexId]));
306
+
307
+ ASMJIT_PROPAGATE(ib.add(workReg, RATiedFlags::kUse | RATiedFlags::kRead, allocable, useId, useRewriteMask, allocable, outId, outRewriteMask));
308
+ }
309
+ }
310
+ }
311
+ }
312
+ }
313
+
314
+ controlType = getControlFlowType(instId);
315
+ }
316
+
317
+ return kErrorOk;
318
+ }
319
+
320
+ // a64::RACFGBuilder - OnInvoke
321
+ // ============================
322
+
323
+ Error RACFGBuilder::onBeforeInvoke(InvokeNode* invokeNode) noexcept {
324
+ const FuncDetail& fd = invokeNode->detail();
325
+ uint32_t argCount = invokeNode->argCount();
326
+
327
+ cc()->_setCursor(invokeNode->prev());
328
+
329
+ for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) {
330
+ const FuncValuePack& argPack = fd.argPack(argIndex);
331
+ for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) {
332
+ if (!argPack[valueIndex])
333
+ break;
334
+
335
+ const FuncValue& arg = argPack[valueIndex];
336
+ const Operand& op = invokeNode->arg(argIndex, valueIndex);
337
+
338
+ if (op.isNone())
339
+ continue;
340
+
341
+ if (op.isReg()) {
342
+ const Reg& reg = op.as<Reg>();
343
+ RAWorkReg* workReg;
344
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg));
345
+
346
+ if (arg.isReg()) {
347
+ RegGroup regGroup = workReg->group();
348
+ RegGroup argGroup = Reg::groupOf(arg.regType());
349
+
350
+ if (regGroup != argGroup) {
351
+ // TODO: [ARM] Conversion is not supported.
352
+ return DebugUtils::errored(kErrorInvalidAssignment);
353
+ }
354
+ }
355
+ else {
356
+ ASMJIT_PROPAGATE(moveRegToStackArg(invokeNode, arg, reg));
357
+ }
358
+ }
359
+ else if (op.isImm()) {
360
+ if (arg.isReg()) {
361
+ BaseReg reg;
362
+ ASMJIT_PROPAGATE(moveImmToRegArg(invokeNode, arg, op.as<Imm>(), &reg));
363
+ invokeNode->_args[argIndex][valueIndex] = reg;
364
+ }
365
+ else {
366
+ ASMJIT_PROPAGATE(moveImmToStackArg(invokeNode, arg, op.as<Imm>()));
367
+ }
368
+ }
369
+ }
370
+ }
371
+
372
+ cc()->_setCursor(invokeNode);
373
+
374
+ if (fd.hasRet()) {
375
+ for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) {
376
+ const FuncValue& ret = fd.ret(valueIndex);
377
+ if (!ret)
378
+ break;
379
+
380
+ const Operand& op = invokeNode->ret(valueIndex);
381
+ if (op.isReg()) {
382
+ const Reg& reg = op.as<Reg>();
383
+ RAWorkReg* workReg;
384
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg));
385
+
386
+ if (ret.isReg()) {
387
+ RegGroup regGroup = workReg->group();
388
+ RegGroup retGroup = Reg::groupOf(ret.regType());
389
+
390
+ if (regGroup != retGroup) {
391
+ // TODO: [ARM] Conversion is not supported.
392
+ return DebugUtils::errored(kErrorInvalidAssignment);
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }
398
+
399
+ // This block has function call(s).
400
+ _curBlock->addFlags(RABlockFlags::kHasFuncCalls);
401
+ _pass->func()->frame().addAttributes(FuncAttributes::kHasFuncCalls);
402
+ _pass->func()->frame().updateCallStackSize(fd.argStackSize());
403
+
404
+ return kErrorOk;
405
+ }
406
+
407
+ Error RACFGBuilder::onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept {
408
+ uint32_t argCount = invokeNode->argCount();
409
+ const FuncDetail& fd = invokeNode->detail();
410
+
411
+ for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) {
412
+ const FuncValuePack& argPack = fd.argPack(argIndex);
413
+ for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) {
414
+ if (!argPack[valueIndex])
415
+ continue;
416
+
417
+ const FuncValue& arg = argPack[valueIndex];
418
+ const Operand& op = invokeNode->arg(argIndex, valueIndex);
419
+
420
+ if (op.isNone())
421
+ continue;
422
+
423
+ if (op.isReg()) {
424
+ const Reg& reg = op.as<Reg>();
425
+ RAWorkReg* workReg;
426
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg));
427
+
428
+ if (arg.isIndirect()) {
429
+ RegGroup regGroup = workReg->group();
430
+ if (regGroup != RegGroup::kGp)
431
+ return DebugUtils::errored(kErrorInvalidState);
432
+ ASMJIT_PROPAGATE(ib.addCallArg(workReg, arg.regId()));
433
+ }
434
+ else if (arg.isReg()) {
435
+ RegGroup regGroup = workReg->group();
436
+ RegGroup argGroup = Reg::groupOf(arg.regType());
437
+
438
+ if (regGroup == argGroup) {
439
+ ASMJIT_PROPAGATE(ib.addCallArg(workReg, arg.regId()));
440
+ }
441
+ }
442
+ }
443
+ }
444
+ }
445
+
446
+ for (uint32_t retIndex = 0; retIndex < Globals::kMaxValuePack; retIndex++) {
447
+ const FuncValue& ret = fd.ret(retIndex);
448
+ if (!ret)
449
+ break;
450
+
451
+ const Operand& op = invokeNode->ret(retIndex);
452
+ if (op.isReg()) {
453
+ const Reg& reg = op.as<Reg>();
454
+ RAWorkReg* workReg;
455
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg));
456
+
457
+ if (ret.isReg()) {
458
+ RegGroup regGroup = workReg->group();
459
+ RegGroup retGroup = Reg::groupOf(ret.regType());
460
+
461
+ if (regGroup == retGroup) {
462
+ ASMJIT_PROPAGATE(ib.addCallRet(workReg, ret.regId()));
463
+ }
464
+ }
465
+ else {
466
+ return DebugUtils::errored(kErrorInvalidAssignment);
467
+ }
468
+ }
469
+ }
470
+
471
+ // Setup clobbered registers.
472
+ ib._clobbered[0] = Support::lsbMask<RegMask>(_pass->_physRegCount[RegGroup(0)]) & ~fd.preservedRegs(RegGroup(0));
473
+ ib._clobbered[1] = Support::lsbMask<RegMask>(_pass->_physRegCount[RegGroup(1)]) & ~fd.preservedRegs(RegGroup(1));
474
+ ib._clobbered[2] = Support::lsbMask<RegMask>(_pass->_physRegCount[RegGroup(2)]) & ~fd.preservedRegs(RegGroup(2));
475
+ ib._clobbered[3] = Support::lsbMask<RegMask>(_pass->_physRegCount[RegGroup(3)]) & ~fd.preservedRegs(RegGroup(3));
476
+
477
+ return kErrorOk;
478
+ }
479
+
480
+ // a64::RACFGBuilder - MoveImmToRegArg
481
+ // ===================================
482
+
483
+ Error RACFGBuilder::moveImmToRegArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_, BaseReg* out) noexcept {
484
+ DebugUtils::unused(invokeNode);
485
+ ASMJIT_ASSERT(arg.isReg());
486
+
487
+ Imm imm(imm_);
488
+ TypeId typeId = TypeId::kVoid;
489
+
490
+ switch (arg.typeId()) {
491
+ case TypeId::kInt8 : typeId = TypeId::kUInt64; imm.signExtend8Bits(); break;
492
+ case TypeId::kUInt8 : typeId = TypeId::kUInt64; imm.zeroExtend8Bits(); break;
493
+ case TypeId::kInt16 : typeId = TypeId::kUInt64; imm.signExtend16Bits(); break;
494
+ case TypeId::kUInt16: typeId = TypeId::kUInt64; imm.zeroExtend16Bits(); break;
495
+ case TypeId::kInt32 : typeId = TypeId::kUInt64; imm.signExtend32Bits(); break;
496
+ case TypeId::kUInt32: typeId = TypeId::kUInt64; imm.zeroExtend32Bits(); break;
497
+ case TypeId::kInt64 : typeId = TypeId::kUInt64; break;
498
+ case TypeId::kUInt64: typeId = TypeId::kUInt64; break;
499
+
500
+ default:
501
+ return DebugUtils::errored(kErrorInvalidAssignment);
502
+ }
503
+
504
+ ASMJIT_PROPAGATE(cc()->_newReg(out, typeId, nullptr));
505
+ cc()->virtRegById(out->id())->setWeight(BaseRAPass::kCallArgWeight);
506
+ return cc()->mov(out->as<Gp>(), imm);
507
+ }
508
+
509
+ // a64::RACFGBuilder - MoveImmToStackArg
510
+ // =====================================
511
+
512
+ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_) noexcept {
513
+ BaseReg reg;
514
+
515
+ ASMJIT_PROPAGATE(moveImmToRegArg(invokeNode, arg, imm_, &reg));
516
+ ASMJIT_PROPAGATE(moveRegToStackArg(invokeNode, arg, reg));
517
+
518
+ return kErrorOk;
519
+ }
520
+
521
+ // a64::RACFGBuilder - MoveRegToStackArg
522
+ // =====================================
523
+
524
+ Error RACFGBuilder::moveRegToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const BaseReg& reg) noexcept {
525
+ DebugUtils::unused(invokeNode);
526
+ Mem stackPtr = ptr(_pass->_sp.as<Gp>(), arg.stackOffset());
527
+
528
+ if (reg.isGp())
529
+ return cc()->str(reg.as<Gp>(), stackPtr);
530
+
531
+ if (reg.isVec())
532
+ return cc()->str(reg.as<Vec>(), stackPtr);
533
+
534
+ return DebugUtils::errored(kErrorInvalidState);
535
+ }
536
+
537
+ // a64::RACFGBuilder - OnReg
538
+ // =========================
539
+
540
+ Error RACFGBuilder::onBeforeRet(FuncRetNode* funcRet) noexcept {
541
+ DebugUtils::unused(funcRet);
542
+ return kErrorOk;
543
+ }
544
+
545
+ Error RACFGBuilder::onRet(FuncRetNode* funcRet, RAInstBuilder& ib) noexcept {
546
+ const FuncDetail& funcDetail = _pass->func()->detail();
547
+ const Operand* opArray = funcRet->operands();
548
+ uint32_t opCount = funcRet->opCount();
549
+
550
+ for (uint32_t i = 0; i < opCount; i++) {
551
+ const Operand& op = opArray[i];
552
+ if (op.isNone()) continue;
553
+
554
+ const FuncValue& ret = funcDetail.ret(i);
555
+ if (ASMJIT_UNLIKELY(!ret.isReg()))
556
+ return DebugUtils::errored(kErrorInvalidAssignment);
557
+
558
+ if (op.isReg()) {
559
+ // Register return value.
560
+ const Reg& reg = op.as<Reg>();
561
+ uint32_t vIndex = Operand::virtIdToIndex(reg.id());
562
+
563
+ if (vIndex < Operand::kVirtIdCount) {
564
+ RAWorkReg* workReg;
565
+ ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg));
566
+
567
+ RegGroup group = workReg->group();
568
+ RegMask allocable = _pass->_availableRegs[group];
569
+ ASMJIT_PROPAGATE(ib.add(workReg, RATiedFlags::kUse | RATiedFlags::kRead, allocable, ret.regId(), 0, 0, BaseReg::kIdBad, 0));
570
+ }
571
+ }
572
+ else {
573
+ return DebugUtils::errored(kErrorInvalidAssignment);
574
+ }
575
+ }
576
+
577
+ return kErrorOk;
578
+ }
579
+
580
+ // a64::ARMRAPass - Construction & Destruction
581
+ // ===========================================
582
+
583
+ ARMRAPass::ARMRAPass() noexcept
584
+ : BaseRAPass() { _iEmitHelper = &_emitHelper; }
585
+ ARMRAPass::~ARMRAPass() noexcept {}
586
+
587
+ // a64::ARMRAPass - OnInit / OnDone
588
+ // ================================
589
+
590
+ void ARMRAPass::onInit() noexcept {
591
+ Arch arch = cc()->arch();
592
+
593
+ _emitHelper._emitter = _cb;
594
+
595
+ _archTraits = &ArchTraits::byArch(arch);
596
+ _physRegCount.set(RegGroup::kGp, 32);
597
+ _physRegCount.set(RegGroup::kVec, 32);
598
+ _physRegCount.set(RegGroup::kExtraVirt2, 0);
599
+ _physRegCount.set(RegGroup::kExtraVirt3, 0);
600
+ _buildPhysIndex();
601
+
602
+ _availableRegCount = _physRegCount;
603
+ _availableRegs[RegGroup::kGp] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kGp));
604
+ _availableRegs[RegGroup::kVec] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kVec));
605
+ _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt2));
606
+ _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt3));
607
+
608
+ _scratchRegIndexes[0] = uint8_t(27);
609
+ _scratchRegIndexes[1] = uint8_t(28);
610
+
611
+ // The architecture specific setup makes implicitly all registers available. So
612
+ // make unavailable all registers that are special and cannot be used in general.
613
+ bool hasFP = _func->frame().hasPreservedFP();
614
+
615
+ if (hasFP)
616
+ makeUnavailable(RegGroup::kGp, Gp::kIdFp);
617
+
618
+ makeUnavailable(RegGroup::kGp, Gp::kIdSp);
619
+ makeUnavailable(RegGroup::kGp, Gp::kIdOs); // OS-specific use, usually TLS.
620
+
621
+ _sp = sp;
622
+ _fp = x29;
623
+ }
624
+
625
+ void ARMRAPass::onDone() noexcept {}
626
+
627
+ // a64::ARMRAPass - BuildCFG
628
+ // =========================
629
+
630
+ Error ARMRAPass::buildCFG() noexcept {
631
+ return RACFGBuilder(this).run();
632
+ }
633
+
634
+ // a64::ARMRAPass - Rewrite
635
+ // ========================
636
+
637
+ ASMJIT_FAVOR_SPEED Error ARMRAPass::_rewrite(BaseNode* first, BaseNode* stop) noexcept {
638
+ uint32_t virtCount = cc()->_vRegArray.size();
639
+
640
+ BaseNode* node = first;
641
+ while (node != stop) {
642
+ BaseNode* next = node->next();
643
+ if (node->isInst()) {
644
+ InstNode* inst = node->as<InstNode>();
645
+ RAInst* raInst = node->passData<RAInst>();
646
+
647
+ Operand* operands = inst->operands();
648
+ uint32_t opCount = inst->opCount();
649
+
650
+ uint32_t i;
651
+
652
+ // Rewrite virtual registers into physical registers.
653
+ if (raInst) {
654
+ // If the instruction contains pass data (raInst) then it was a subject
655
+ // for register allocation and must be rewritten to use physical regs.
656
+ RATiedReg* tiedRegs = raInst->tiedRegs();
657
+ uint32_t tiedCount = raInst->tiedCount();
658
+
659
+ for (i = 0; i < tiedCount; i++) {
660
+ RATiedReg* tiedReg = &tiedRegs[i];
661
+
662
+ Support::BitWordIterator<uint32_t> useIt(tiedReg->useRewriteMask());
663
+ uint32_t useId = tiedReg->useId();
664
+ while (useIt.hasNext())
665
+ inst->rewriteIdAtIndex(useIt.next(), useId);
666
+
667
+ Support::BitWordIterator<uint32_t> outIt(tiedReg->outRewriteMask());
668
+ uint32_t outId = tiedReg->outId();
669
+ while (outIt.hasNext())
670
+ inst->rewriteIdAtIndex(outIt.next(), outId);
671
+ }
672
+
673
+ // This data is allocated by Zone passed to `runOnFunction()`, which
674
+ // will be reset after the RA pass finishes. So reset this data to
675
+ // prevent having a dead pointer after the RA pass is complete.
676
+ node->resetPassData();
677
+
678
+ if (ASMJIT_UNLIKELY(node->type() != NodeType::kInst)) {
679
+ // FuncRet terminates the flow, it must either be removed if the exit
680
+ // label is next to it (optimization) or patched to an architecture
681
+ // dependent jump instruction that jumps to the function's exit before
682
+ // the epilog.
683
+ if (node->type() == NodeType::kFuncRet) {
684
+ RABlock* block = raInst->block();
685
+ if (!isNextTo(node, _func->exitNode())) {
686
+ cc()->_setCursor(node->prev());
687
+ ASMJIT_PROPAGATE(emitJump(_func->exitNode()->label()));
688
+ }
689
+
690
+ BaseNode* prev = node->prev();
691
+ cc()->removeNode(node);
692
+ block->setLast(prev);
693
+ }
694
+ }
695
+ }
696
+
697
+ // Rewrite stack slot addresses.
698
+ for (i = 0; i < opCount; i++) {
699
+ Operand& op = operands[i];
700
+ if (op.isMem()) {
701
+ BaseMem& mem = op.as<BaseMem>();
702
+ if (mem.isRegHome()) {
703
+ uint32_t virtIndex = Operand::virtIdToIndex(mem.baseId());
704
+ if (ASMJIT_UNLIKELY(virtIndex >= virtCount))
705
+ return DebugUtils::errored(kErrorInvalidVirtId);
706
+
707
+ VirtReg* virtReg = cc()->virtRegByIndex(virtIndex);
708
+ RAWorkReg* workReg = virtReg->workReg();
709
+ ASMJIT_ASSERT(workReg != nullptr);
710
+
711
+ RAStackSlot* slot = workReg->stackSlot();
712
+ int32_t offset = slot->offset();
713
+
714
+ mem._setBase(_sp.type(), slot->baseRegId());
715
+ mem.clearRegHome();
716
+ mem.addOffsetLo32(offset);
717
+ }
718
+ }
719
+ }
720
+
721
+ // Rewrite `loadAddressOf()` construct.
722
+ if (inst->realId() == Inst::kIdAdr && inst->opCount() == 2 && inst->op(1).isMem()) {
723
+ BaseMem mem = inst->op(1).as<BaseMem>();
724
+ int64_t offset = mem.offset();
725
+
726
+ if (!mem.hasBaseOrIndex()) {
727
+ inst->setId(Inst::kIdMov);
728
+ inst->setOp(1, Imm(offset));
729
+ }
730
+ else {
731
+ if (mem.hasIndex())
732
+ return DebugUtils::errored(kErrorInvalidAddressIndex);
733
+
734
+ GpX dst(inst->op(0).as<Gp>().id());
735
+ GpX base(mem.baseId());
736
+
737
+ InstId arithInstId = offset < 0 ? Inst::kIdSub : Inst::kIdAdd;
738
+ uint64_t absOffset = offset < 0 ? Support::neg(uint64_t(offset)) : uint64_t(offset);
739
+
740
+ inst->setId(arithInstId);
741
+ inst->setOpCount(3);
742
+ inst->setOp(1, base);
743
+ inst->setOp(2, Imm(absOffset));
744
+
745
+ // Use two operations if the offset cannot be encoded with ADD/SUB.
746
+ if (absOffset > 0xFFFu && (absOffset & ~uint64_t(0xFFF000u)) != 0) {
747
+ if (absOffset <= 0xFFFFFFu) {
748
+ cc()->_setCursor(inst->prev());
749
+ ASMJIT_PROPAGATE(cc()->emit(arithInstId, dst, base, Imm(absOffset & 0xFFFu)));
750
+
751
+ inst->setOp(1, dst);
752
+ inst->setOp(2, Imm(absOffset & 0xFFF000u));
753
+ }
754
+ else {
755
+ cc()->_setCursor(inst->prev());
756
+ ASMJIT_PROPAGATE(cc()->emit(Inst::kIdMov, inst->op(0), Imm(absOffset)));
757
+
758
+ inst->setOp(1, base);
759
+ inst->setOp(2, dst);
760
+ }
761
+ }
762
+ }
763
+ }
764
+ }
765
+
766
+ node = next;
767
+ }
768
+
769
+ return kErrorOk;
770
+ }
771
+
772
+ // a64::ARMRAPass - Prolog & Epilog
773
+ // ================================
774
+
775
+ Error ARMRAPass::updateStackFrame() noexcept {
776
+ if (_func->frame().hasFuncCalls())
777
+ _func->frame().addDirtyRegs(RegGroup::kGp, Support::bitMask(Gp::kIdLr));
778
+
779
+ return BaseRAPass::updateStackFrame();
780
+ }
781
+
782
+ // a64::ARMRAPass - OnEmit
783
+ // =======================
784
+
785
+ Error ARMRAPass::emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept {
786
+ RAWorkReg* wReg = workRegById(workId);
787
+ BaseReg dst(wReg->signature(), dstPhysId);
788
+ BaseReg src(wReg->signature(), srcPhysId);
789
+
790
+ const char* comment = nullptr;
791
+
792
+ #ifndef ASMJIT_NO_LOGGING
793
+ if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) {
794
+ _tmpString.assignFormat("<MOVE> %s", workRegById(workId)->name());
795
+ comment = _tmpString.data();
796
+ }
797
+ #endif
798
+
799
+ return _emitHelper.emitRegMove(dst, src, wReg->typeId(), comment);
800
+ }
801
+
802
+ Error ARMRAPass::emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept {
803
+ DebugUtils::unused(aWorkId, aPhysId, bWorkId, bPhysId);
804
+ return DebugUtils::errored(kErrorInvalidState);
805
+ }
806
+
807
+ Error ARMRAPass::emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept {
808
+ RAWorkReg* wReg = workRegById(workId);
809
+ BaseReg dstReg(wReg->signature(), dstPhysId);
810
+ BaseMem srcMem(workRegAsMem(wReg));
811
+
812
+ const char* comment = nullptr;
813
+
814
+ #ifndef ASMJIT_NO_LOGGING
815
+ if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) {
816
+ _tmpString.assignFormat("<LOAD> %s", workRegById(workId)->name());
817
+ comment = _tmpString.data();
818
+ }
819
+ #endif
820
+
821
+ return _emitHelper.emitRegMove(dstReg, srcMem, wReg->typeId(), comment);
822
+ }
823
+
824
+ Error ARMRAPass::emitSave(uint32_t workId, uint32_t srcPhysId) noexcept {
825
+ RAWorkReg* wReg = workRegById(workId);
826
+ BaseMem dstMem(workRegAsMem(wReg));
827
+ BaseReg srcReg(wReg->signature(), srcPhysId);
828
+
829
+ const char* comment = nullptr;
830
+
831
+ #ifndef ASMJIT_NO_LOGGING
832
+ if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) {
833
+ _tmpString.assignFormat("<SAVE> %s", workRegById(workId)->name());
834
+ comment = _tmpString.data();
835
+ }
836
+ #endif
837
+
838
+ return _emitHelper.emitRegMove(dstMem, srcReg, wReg->typeId(), comment);
839
+ }
840
+
841
+ Error ARMRAPass::emitJump(const Label& label) noexcept {
842
+ return cc()->b(label);
843
+ }
844
+
845
+ Error ARMRAPass::emitPreCall(InvokeNode* invokeNode) noexcept {
846
+ DebugUtils::unused(invokeNode);
847
+ return kErrorOk;
848
+ }
849
+
850
+ ASMJIT_END_SUB_NAMESPACE
851
+
852
+ #endif // !ASMJIT_NO_AARCH64 && !ASMJIT_NO_COMPILER