asmjit 0.2.0 → 0.2.1

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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/asmjit.gemspec +1 -1
  4. data/ext/asmjit/asmjit/.editorconfig +10 -0
  5. data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
  6. data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
  7. data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
  8. data/ext/asmjit/asmjit/.gitignore +6 -0
  9. data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
  10. data/ext/asmjit/asmjit/LICENSE.md +17 -0
  11. data/ext/asmjit/asmjit/README.md +69 -0
  12. data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
  13. data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
  14. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
  15. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
  16. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
  17. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
  18. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
  19. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
  20. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
  21. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
  22. data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
  23. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
  24. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
  25. data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
  26. data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
  27. data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
  28. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
  29. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
  30. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
  31. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
  32. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
  33. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
  34. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
  35. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
  36. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
  37. data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
  38. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
  39. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
  40. data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
  41. data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
  42. data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
  43. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
  44. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
  45. data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
  46. data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
  47. data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
  48. data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
  49. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
  50. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
  51. data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
  52. data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
  53. data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
  54. data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
  55. data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
  56. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
  57. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
  58. data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
  59. data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
  60. data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
  61. data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
  62. data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
  63. data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
  64. data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
  65. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
  66. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
  67. data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
  68. data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
  69. data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
  70. data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
  71. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
  72. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
  73. data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
  74. data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
  75. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
  76. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
  77. data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
  78. data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
  79. data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
  80. data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
  81. data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
  82. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
  83. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
  84. data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
  85. data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
  86. data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
  87. data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
  88. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
  89. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
  90. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
  91. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
  92. data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
  93. data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
  94. data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
  95. data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
  96. data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
  97. data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
  98. data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
  99. data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
  100. data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
  101. data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
  102. data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
  103. data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
  104. data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
  105. data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
  106. data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
  107. data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
  108. data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
  109. data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
  110. data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
  111. data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
  112. data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
  113. data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
  114. data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
  115. data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
  116. data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
  117. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
  118. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
  119. data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
  120. data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
  121. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
  122. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
  123. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
  124. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
  125. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
  126. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
  127. data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
  128. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
  129. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
  130. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
  131. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
  132. data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
  133. data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
  134. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
  135. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
  136. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
  137. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
  138. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
  139. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
  140. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
  141. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
  142. data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
  143. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
  144. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
  145. data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
  146. data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
  147. data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
  148. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
  149. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
  150. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
  151. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
  152. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
  153. data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
  154. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
  155. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
  156. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
  157. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
  158. data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
  159. data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
  160. data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
  161. data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
  162. data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
  163. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
  164. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
  165. data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
  166. data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
  167. data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
  168. data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
  169. data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
  170. data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
  171. data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
  172. data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
  173. data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
  174. data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
  175. data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
  176. data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
  177. data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
  178. data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
  179. data/ext/asmjit/asmjit/test/broken.cpp +312 -0
  180. data/ext/asmjit/asmjit/test/broken.h +148 -0
  181. data/ext/asmjit/asmjit/test/cmdline.h +61 -0
  182. data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
  183. data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
  184. data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
  185. data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
  186. data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
  187. data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
  188. data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
  189. data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
  190. data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
  191. data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
  192. data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
  193. data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
  194. data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
  195. data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
  196. data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
  197. data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
  198. data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
  199. data/ext/asmjit/asmjit.cc +18 -0
  200. data/lib/asmjit/version.rb +1 -1
  201. metadata +197 -2
@@ -0,0 +1,323 @@
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
+ #include "../core/archtraits.h"
8
+ #include "../core/emithelper_p.h"
9
+ #include "../core/formatter.h"
10
+ #include "../core/funcargscontext_p.h"
11
+ #include "../core/radefs_p.h"
12
+
13
+ // Can be used for debugging...
14
+ // #define ASMJIT_DUMP_ARGS_ASSIGNMENT
15
+
16
+ ASMJIT_BEGIN_NAMESPACE
17
+
18
+ // BaseEmitHelper - Formatting
19
+ // ===========================
20
+
21
+ #ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT
22
+ static void dumpFuncValue(String& sb, Arch arch, const FuncValue& value) noexcept {
23
+ Formatter::formatTypeId(sb, value.typeId());
24
+ sb.append('@');
25
+
26
+ if (value.isIndirect())
27
+ sb.append('[');
28
+
29
+ if (value.isReg())
30
+ Formatter::formatRegister(sb, 0, nullptr, arch, value.regType(), value.regId());
31
+ else if (value.isStack())
32
+ sb.appendFormat("[%d]", value.stackOffset());
33
+ else
34
+ sb.append("<none>");
35
+
36
+ if (value.isIndirect())
37
+ sb.append(']');
38
+ }
39
+
40
+ static void dumpAssignment(String& sb, const FuncArgsContext& ctx) noexcept {
41
+ typedef FuncArgsContext::Var Var;
42
+
43
+ Arch arch = ctx.arch();
44
+ uint32_t varCount = ctx.varCount();
45
+
46
+ for (uint32_t i = 0; i < varCount; i++) {
47
+ const Var& var = ctx.var(i);
48
+ const FuncValue& dst = var.out;
49
+ const FuncValue& cur = var.cur;
50
+
51
+ sb.appendFormat("Var%u: ", i);
52
+ dumpFuncValue(sb, arch, dst);
53
+ sb.append(" <- ");
54
+ dumpFuncValue(sb, arch, cur);
55
+
56
+ if (var.isDone())
57
+ sb.append(" {Done}");
58
+
59
+ sb.append('\n');
60
+ }
61
+ }
62
+ #endif
63
+
64
+ // BaseEmitHelper - EmitArgsAssignment
65
+ // ===================================
66
+
67
+ ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
68
+ typedef FuncArgsContext::Var Var;
69
+ typedef FuncArgsContext::WorkData WorkData;
70
+
71
+ enum WorkFlags : uint32_t {
72
+ kWorkNone = 0x00,
73
+ kWorkDidSome = 0x01,
74
+ kWorkPending = 0x02,
75
+ kWorkPostponed = 0x04
76
+ };
77
+
78
+ Arch arch = frame.arch();
79
+ const ArchTraits& archTraits = ArchTraits::byArch(arch);
80
+
81
+ RAConstraints constraints;
82
+ FuncArgsContext ctx;
83
+
84
+ ASMJIT_PROPAGATE(constraints.init(arch));
85
+ ASMJIT_PROPAGATE(ctx.initWorkData(frame, args, &constraints));
86
+
87
+ #ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT
88
+ {
89
+ String sb;
90
+ dumpAssignment(sb, ctx);
91
+ printf("%s\n", sb.data());
92
+ }
93
+ #endif
94
+
95
+ auto& workData = ctx._workData;
96
+ uint32_t varCount = ctx._varCount;
97
+ uint32_t saVarId = ctx._saVarId;
98
+
99
+ BaseReg sp = BaseReg(_emitter->_gpSignature, archTraits.spRegId());
100
+ BaseReg sa = sp;
101
+
102
+ if (frame.hasDynamicAlignment()) {
103
+ if (frame.hasPreservedFP())
104
+ sa.setId(archTraits.fpRegId());
105
+ else
106
+ sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId());
107
+ }
108
+
109
+ // Register to stack and stack to stack moves must be first as now we have
110
+ // the biggest chance of having as many as possible unassigned registers.
111
+
112
+ if (ctx._stackDstMask) {
113
+ // Base address of all arguments passed by stack.
114
+ BaseMem baseArgPtr(sa, int32_t(frame.saOffset(sa.id())));
115
+ BaseMem baseStackPtr(sp, 0);
116
+
117
+ for (uint32_t varId = 0; varId < varCount; varId++) {
118
+ Var& var = ctx._vars[varId];
119
+
120
+ if (!var.out.isStack())
121
+ continue;
122
+
123
+ FuncValue& cur = var.cur;
124
+ FuncValue& out = var.out;
125
+
126
+ ASMJIT_ASSERT(cur.isReg() || cur.isStack());
127
+ BaseReg reg;
128
+
129
+ BaseMem dstStackPtr = baseStackPtr.cloneAdjusted(out.stackOffset());
130
+ BaseMem srcStackPtr = baseArgPtr.cloneAdjusted(cur.stackOffset());
131
+
132
+ if (cur.isIndirect()) {
133
+ if (cur.isStack()) {
134
+ // TODO: Indirect stack.
135
+ return DebugUtils::errored(kErrorInvalidAssignment);
136
+ }
137
+ else {
138
+ srcStackPtr.setBaseId(cur.regId());
139
+ }
140
+ }
141
+
142
+ if (cur.isReg() && !cur.isIndirect()) {
143
+ WorkData& wd = workData[archTraits.regTypeToGroup(cur.regType())];
144
+ uint32_t regId = cur.regId();
145
+
146
+ reg.setSignatureAndId(archTraits.regTypeToSignature(cur.regType()), regId);
147
+ wd.unassign(varId, regId);
148
+ }
149
+ else {
150
+ // Stack to reg move - tricky since we move stack to stack we can decide which register to use. In general
151
+ // we follow the rule that IntToInt moves will use GP regs with possibility to signature or zero extend,
152
+ // and all other moves will either use GP or VEC regs depending on the size of the move.
153
+ OperandSignature signature = getSuitableRegForMemToMemMove(arch, out.typeId(), cur.typeId());
154
+ if (ASMJIT_UNLIKELY(!signature.isValid()))
155
+ return DebugUtils::errored(kErrorInvalidState);
156
+
157
+ WorkData& wd = workData[signature.regGroup()];
158
+ RegMask availableRegs = wd.availableRegs();
159
+ if (ASMJIT_UNLIKELY(!availableRegs))
160
+ return DebugUtils::errored(kErrorInvalidState);
161
+
162
+ uint32_t availableId = Support::ctz(availableRegs);
163
+ reg.setSignatureAndId(signature, availableId);
164
+
165
+ ASMJIT_PROPAGATE(emitArgMove(reg, out.typeId(), srcStackPtr, cur.typeId()));
166
+ }
167
+
168
+ if (cur.isIndirect() && cur.isReg())
169
+ workData[RegGroup::kGp].unassign(varId, cur.regId());
170
+
171
+ // Register to stack move.
172
+ ASMJIT_PROPAGATE(emitRegMove(dstStackPtr, reg, cur.typeId()));
173
+ var.markDone();
174
+ }
175
+ }
176
+
177
+ // Shuffle all registers that are currently assigned accordingly to target assignment.
178
+
179
+ uint32_t workFlags = kWorkNone;
180
+ for (;;) {
181
+ for (uint32_t varId = 0; varId < varCount; varId++) {
182
+ Var& var = ctx._vars[varId];
183
+ if (var.isDone() || !var.cur.isReg())
184
+ continue;
185
+
186
+ FuncValue& cur = var.cur;
187
+ FuncValue& out = var.out;
188
+
189
+ RegGroup curGroup = archTraits.regTypeToGroup(cur.regType());
190
+ RegGroup outGroup = archTraits.regTypeToGroup(out.regType());
191
+
192
+ uint32_t curId = cur.regId();
193
+ uint32_t outId = out.regId();
194
+
195
+ if (curGroup != outGroup) {
196
+ // TODO: Conversion is not supported.
197
+ return DebugUtils::errored(kErrorInvalidAssignment);
198
+ }
199
+ else {
200
+ WorkData& wd = workData[outGroup];
201
+ if (!wd.isAssigned(outId)) {
202
+ EmitMove:
203
+ ASMJIT_PROPAGATE(
204
+ emitArgMove(
205
+ BaseReg(archTraits.regTypeToSignature(out.regType()), outId), out.typeId(),
206
+ BaseReg(archTraits.regTypeToSignature(cur.regType()), curId), cur.typeId()));
207
+
208
+ wd.reassign(varId, outId, curId);
209
+ cur.initReg(out.regType(), outId, out.typeId());
210
+
211
+ if (outId == out.regId())
212
+ var.markDone();
213
+ workFlags |= kWorkDidSome | kWorkPending;
214
+ }
215
+ else {
216
+ uint32_t altId = wd._physToVarId[outId];
217
+ Var& altVar = ctx._vars[altId];
218
+
219
+ if (!altVar.out.isInitialized() || (altVar.out.isReg() && altVar.out.regId() == curId)) {
220
+ // Only few architectures provide swap operations, and only for few register groups.
221
+ if (archTraits.hasInstRegSwap(curGroup)) {
222
+ RegType highestType = Support::max(cur.regType(), altVar.cur.regType());
223
+ if (Support::isBetween(highestType, RegType::kGp8Lo, RegType::kGp16))
224
+ highestType = RegType::kGp32;
225
+
226
+ OperandSignature signature = archTraits.regTypeToSignature(highestType);
227
+ ASMJIT_PROPAGATE(
228
+ emitRegSwap(BaseReg(signature, outId), BaseReg(signature, curId)));
229
+
230
+ wd.swap(varId, curId, altId, outId);
231
+ cur.setRegId(outId);
232
+ var.markDone();
233
+ altVar.cur.setRegId(curId);
234
+
235
+ if (altVar.out.isInitialized())
236
+ altVar.markDone();
237
+ workFlags |= kWorkDidSome;
238
+ }
239
+ else {
240
+ // If there is a scratch register it can be used to perform the swap.
241
+ RegMask availableRegs = wd.availableRegs();
242
+ if (availableRegs) {
243
+ RegMask inOutRegs = wd.dstRegs();
244
+ if (availableRegs & ~inOutRegs)
245
+ availableRegs &= ~inOutRegs;
246
+ outId = Support::ctz(availableRegs);
247
+ goto EmitMove;
248
+ }
249
+ else {
250
+ workFlags |= kWorkPending;
251
+ }
252
+ }
253
+ }
254
+ else {
255
+ workFlags |= kWorkPending;
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ if (!(workFlags & kWorkPending))
262
+ break;
263
+
264
+ // If we did nothing twice it means that something is really broken.
265
+ if ((workFlags & (kWorkDidSome | kWorkPostponed)) == kWorkPostponed)
266
+ return DebugUtils::errored(kErrorInvalidState);
267
+
268
+ workFlags = (workFlags & kWorkDidSome) ? kWorkNone : kWorkPostponed;
269
+ }
270
+
271
+ // Load arguments passed by stack into registers. This is pretty simple and
272
+ // it never requires multiple iterations like the previous phase.
273
+
274
+ if (ctx._hasStackSrc) {
275
+ uint32_t iterCount = 1;
276
+ if (frame.hasDynamicAlignment() && !frame.hasPreservedFP())
277
+ sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId());
278
+
279
+ // Base address of all arguments passed by stack.
280
+ BaseMem baseArgPtr(sa, int32_t(frame.saOffset(sa.id())));
281
+
282
+ for (uint32_t iter = 0; iter < iterCount; iter++) {
283
+ for (uint32_t varId = 0; varId < varCount; varId++) {
284
+ Var& var = ctx._vars[varId];
285
+ if (var.isDone())
286
+ continue;
287
+
288
+ if (var.cur.isStack()) {
289
+ ASMJIT_ASSERT(var.out.isReg());
290
+
291
+ uint32_t outId = var.out.regId();
292
+ RegType outType = var.out.regType();
293
+
294
+ RegGroup group = archTraits.regTypeToGroup(outType);
295
+ WorkData& wd = workData[group];
296
+
297
+ if (outId == sa.id() && group == RegGroup::kGp) {
298
+ // This register will be processed last as we still need `saRegId`.
299
+ if (iterCount == 1) {
300
+ iterCount++;
301
+ continue;
302
+ }
303
+ wd.unassign(wd._physToVarId[outId], outId);
304
+ }
305
+
306
+ BaseReg dstReg = BaseReg(archTraits.regTypeToSignature(outType), outId);
307
+ BaseMem srcMem = baseArgPtr.cloneAdjusted(var.cur.stackOffset());
308
+
309
+ ASMJIT_PROPAGATE(emitArgMove(
310
+ dstReg, var.out.typeId(),
311
+ srcMem, var.cur.typeId()));
312
+
313
+ wd.assign(varId, outId);
314
+ var.cur.initReg(outType, outId, var.cur.typeId(), FuncValue::kFlagIsDone);
315
+ }
316
+ }
317
+ }
318
+ }
319
+
320
+ return kErrorOk;
321
+ }
322
+
323
+ ASMJIT_END_NAMESPACE
@@ -0,0 +1,58 @@
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
+ #ifndef ASMJIT_CORE_EMITHELPER_P_H_INCLUDED
7
+ #define ASMJIT_CORE_EMITHELPER_P_H_INCLUDED
8
+
9
+ #include "../core/emitter.h"
10
+ #include "../core/operand.h"
11
+ #include "../core/type.h"
12
+
13
+ ASMJIT_BEGIN_NAMESPACE
14
+
15
+ //! \cond INTERNAL
16
+ //! \addtogroup asmjit_core
17
+ //! \{
18
+
19
+ //! Helper class that provides utilities for each supported architecture.
20
+ class BaseEmitHelper {
21
+ public:
22
+ BaseEmitter* _emitter;
23
+
24
+ inline explicit BaseEmitHelper(BaseEmitter* emitter = nullptr) noexcept
25
+ : _emitter(emitter) {}
26
+
27
+ inline BaseEmitter* emitter() const noexcept { return _emitter; }
28
+ inline void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; }
29
+
30
+ //! Emits a pure move operation between two registers or the same type or between a register and its home
31
+ //! slot. This function does not handle register conversion.
32
+ virtual Error emitRegMove(
33
+ const Operand_& dst_,
34
+ const Operand_& src_, TypeId typeId, const char* comment = nullptr) = 0;
35
+
36
+ //! Emits swap between two registers.
37
+ virtual Error emitRegSwap(
38
+ const BaseReg& a,
39
+ const BaseReg& b, const char* comment = nullptr) = 0;
40
+
41
+ //! Emits move from a function argument (either register or stack) to a register.
42
+ //!
43
+ //! This function can handle the necessary conversion from one argument to another, and from one register type
44
+ //! to another, if it's possible. Any attempt of conversion that requires third register of a different group
45
+ //! (for example conversion from K to MMX on X86/X64) will fail.
46
+ virtual Error emitArgMove(
47
+ const BaseReg& dst_, TypeId dstTypeId,
48
+ const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr) = 0;
49
+
50
+ Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args);
51
+ };
52
+
53
+ //! \}
54
+ //! \endcond
55
+
56
+ ASMJIT_END_NAMESPACE
57
+
58
+ #endif // ASMJIT_CORE_EMITHELPER_P_H_INCLUDED
@@ -0,0 +1,333 @@
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
+ #include "../core/emitterutils_p.h"
8
+ #include "../core/errorhandler.h"
9
+ #include "../core/logger.h"
10
+ #include "../core/support.h"
11
+
12
+ ASMJIT_BEGIN_NAMESPACE
13
+
14
+ // BaseEmitter - Construction & Destruction
15
+ // ========================================
16
+
17
+ BaseEmitter::BaseEmitter(EmitterType emitterType) noexcept
18
+ : _emitterType(emitterType) {}
19
+
20
+ BaseEmitter::~BaseEmitter() noexcept {
21
+ if (_code) {
22
+ _addEmitterFlags(EmitterFlags::kDestroyed);
23
+ _code->detach(this);
24
+ }
25
+ }
26
+
27
+ // BaseEmitter - Finalize
28
+ // ======================
29
+
30
+ Error BaseEmitter::finalize() {
31
+ // Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`.
32
+ return kErrorOk;
33
+ }
34
+
35
+ // BaseEmitter - Internals
36
+ // =======================
37
+
38
+ static constexpr EmitterFlags kEmitterPreservedFlags = EmitterFlags::kOwnLogger | EmitterFlags::kOwnErrorHandler;
39
+
40
+ static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept {
41
+ bool emitComments = false;
42
+ bool hasDiagnosticOptions = false;
43
+
44
+ if (self->emitterType() == EmitterType::kAssembler) {
45
+ // Assembler: Don't emit comments if logger is not attached.
46
+ emitComments = self->_code != nullptr && self->_logger != nullptr;
47
+ hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateAssembler);
48
+ }
49
+ else {
50
+ // Builder/Compiler: Always emit comments, we cannot assume they won't be used.
51
+ emitComments = self->_code != nullptr;
52
+ hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateIntermediate);
53
+ }
54
+
55
+ if (emitComments)
56
+ self->_addEmitterFlags(EmitterFlags::kLogComments);
57
+ else
58
+ self->_clearEmitterFlags(EmitterFlags::kLogComments);
59
+
60
+ // The reserved option tells emitter (Assembler/Builder/Compiler) that there may be either a border
61
+ // case (CodeHolder not attached, for example) or that logging or validation is required.
62
+ if (self->_code == nullptr || self->_logger || hasDiagnosticOptions)
63
+ self->_forcedInstOptions |= InstOptions::kReserved;
64
+ else
65
+ self->_forcedInstOptions &= ~InstOptions::kReserved;
66
+ }
67
+
68
+ // BaseEmitter - Diagnostic Options
69
+ // ================================
70
+
71
+ void BaseEmitter::addDiagnosticOptions(DiagnosticOptions options) noexcept {
72
+ _diagnosticOptions |= options;
73
+ BaseEmitter_updateForcedOptions(this);
74
+ }
75
+
76
+ void BaseEmitter::clearDiagnosticOptions(DiagnosticOptions options) noexcept {
77
+ _diagnosticOptions &= ~options;
78
+ BaseEmitter_updateForcedOptions(this);
79
+ }
80
+
81
+ // BaseEmitter - Logging
82
+ // =====================
83
+
84
+ void BaseEmitter::setLogger(Logger* logger) noexcept {
85
+ #ifndef ASMJIT_NO_LOGGING
86
+ if (logger) {
87
+ _logger = logger;
88
+ _addEmitterFlags(EmitterFlags::kOwnLogger);
89
+ }
90
+ else {
91
+ _logger = nullptr;
92
+ _clearEmitterFlags(EmitterFlags::kOwnLogger);
93
+ if (_code)
94
+ _logger = _code->logger();
95
+ }
96
+ BaseEmitter_updateForcedOptions(this);
97
+ #else
98
+ DebugUtils::unused(logger);
99
+ #endif
100
+ }
101
+
102
+ // BaseEmitter - Error Handling
103
+ // ============================
104
+
105
+ void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept {
106
+ if (errorHandler) {
107
+ _errorHandler = errorHandler;
108
+ _addEmitterFlags(EmitterFlags::kOwnErrorHandler);
109
+ }
110
+ else {
111
+ _errorHandler = nullptr;
112
+ _clearEmitterFlags(EmitterFlags::kOwnErrorHandler);
113
+ if (_code)
114
+ _errorHandler = _code->errorHandler();
115
+ }
116
+ }
117
+
118
+ Error BaseEmitter::reportError(Error err, const char* message) {
119
+ ErrorHandler* eh = _errorHandler;
120
+ if (eh) {
121
+ if (!message)
122
+ message = DebugUtils::errorAsString(err);
123
+ eh->handleError(err, message, this);
124
+ }
125
+ return err;
126
+ }
127
+
128
+ // BaseEmitter - Labels
129
+ // ====================
130
+
131
+ Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept {
132
+ return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : Globals::kInvalidId);
133
+ }
134
+
135
+ bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept {
136
+ return _code && labelId < _code->labelCount();
137
+ }
138
+
139
+ // BaseEmitter - Emit (Low-Level)
140
+ // ==============================
141
+
142
+ using EmitterUtils::noExt;
143
+
144
+ Error BaseEmitter::_emitI(InstId instId) {
145
+ return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
146
+ }
147
+
148
+ Error BaseEmitter::_emitI(InstId instId, const Operand_& o0) {
149
+ return _emit(instId, o0, noExt[1], noExt[2], noExt);
150
+ }
151
+
152
+ Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1) {
153
+ return _emit(instId, o0, o1, noExt[2], noExt);
154
+ }
155
+
156
+ Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) {
157
+ return _emit(instId, o0, o1, o2, noExt);
158
+ }
159
+
160
+ Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) {
161
+ Operand_ opExt[3] = { o3 };
162
+ return _emit(instId, o0, o1, o2, opExt);
163
+ }
164
+
165
+ Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) {
166
+ Operand_ opExt[3] = { o3, o4 };
167
+ return _emit(instId, o0, o1, o2, opExt);
168
+ }
169
+
170
+ Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) {
171
+ Operand_ opExt[3] = { o3, o4, o5 };
172
+ return _emit(instId, o0, o1, o2, opExt);
173
+ }
174
+
175
+ Error BaseEmitter::_emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
176
+ const Operand_* op = operands;
177
+ Operand_ opExt[3];
178
+
179
+ switch (opCount) {
180
+ case 0:
181
+ return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
182
+
183
+ case 1:
184
+ return _emit(instId, op[0], noExt[1], noExt[2], noExt);
185
+
186
+ case 2:
187
+ return _emit(instId, op[0], op[1], noExt[2], noExt);
188
+
189
+ case 3:
190
+ return _emit(instId, op[0], op[1], op[2], noExt);
191
+
192
+ case 4:
193
+ opExt[0] = op[3];
194
+ opExt[1].reset();
195
+ opExt[2].reset();
196
+ return _emit(instId, op[0], op[1], op[2], opExt);
197
+
198
+ case 5:
199
+ opExt[0] = op[3];
200
+ opExt[1] = op[4];
201
+ opExt[2].reset();
202
+ return _emit(instId, op[0], op[1], op[2], opExt);
203
+
204
+ case 6:
205
+ return _emit(instId, op[0], op[1], op[2], op + 3);
206
+
207
+ default:
208
+ return DebugUtils::errored(kErrorInvalidArgument);
209
+ }
210
+ }
211
+
212
+ // BaseEmitter - Emit Utilities
213
+ // ============================
214
+
215
+ Error BaseEmitter::emitProlog(const FuncFrame& frame) {
216
+ if (ASMJIT_UNLIKELY(!_code))
217
+ return DebugUtils::errored(kErrorNotInitialized);
218
+
219
+ return _funcs.emitProlog(this, frame);
220
+ }
221
+
222
+ Error BaseEmitter::emitEpilog(const FuncFrame& frame) {
223
+ if (ASMJIT_UNLIKELY(!_code))
224
+ return DebugUtils::errored(kErrorNotInitialized);
225
+
226
+ return _funcs.emitEpilog(this, frame);
227
+ }
228
+
229
+ Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
230
+ if (ASMJIT_UNLIKELY(!_code))
231
+ return DebugUtils::errored(kErrorNotInitialized);
232
+
233
+ return _funcs.emitArgsAssignment(this, frame, args);
234
+ }
235
+
236
+ // BaseEmitter - Comment
237
+ // =====================
238
+
239
+ Error BaseEmitter::commentf(const char* fmt, ...) {
240
+ if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
241
+ if (!hasEmitterFlag(EmitterFlags::kAttached))
242
+ return reportError(DebugUtils::errored(kErrorNotInitialized));
243
+ return kErrorOk;
244
+ }
245
+
246
+ #ifndef ASMJIT_NO_LOGGING
247
+ StringTmp<1024> sb;
248
+
249
+ va_list ap;
250
+ va_start(ap, fmt);
251
+ Error err = sb.appendVFormat(fmt, ap);
252
+ va_end(ap);
253
+
254
+ ASMJIT_PROPAGATE(err);
255
+ return comment(sb.data(), sb.size());
256
+ #else
257
+ DebugUtils::unused(fmt);
258
+ return kErrorOk;
259
+ #endif
260
+ }
261
+
262
+ Error BaseEmitter::commentv(const char* fmt, va_list ap) {
263
+ if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
264
+ if (!hasEmitterFlag(EmitterFlags::kAttached))
265
+ return reportError(DebugUtils::errored(kErrorNotInitialized));
266
+ return kErrorOk;
267
+ }
268
+
269
+ #ifndef ASMJIT_NO_LOGGING
270
+ StringTmp<1024> sb;
271
+ Error err = sb.appendVFormat(fmt, ap);
272
+
273
+ ASMJIT_PROPAGATE(err);
274
+ return comment(sb.data(), sb.size());
275
+ #else
276
+ DebugUtils::unused(fmt, ap);
277
+ return kErrorOk;
278
+ #endif
279
+ }
280
+
281
+ // BaseEmitter - Events
282
+ // ====================
283
+
284
+ Error BaseEmitter::onAttach(CodeHolder* code) noexcept {
285
+ _code = code;
286
+ _environment = code->environment();
287
+ _addEmitterFlags(EmitterFlags::kAttached);
288
+
289
+ const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
290
+ RegType nativeRegType = Environment::is32Bit(code->arch()) ? RegType::kGp32 : RegType::kGp64;
291
+ _gpSignature = archTraits.regTypeToSignature(nativeRegType);
292
+
293
+ onSettingsUpdated();
294
+ return kErrorOk;
295
+ }
296
+
297
+ Error BaseEmitter::onDetach(CodeHolder* code) noexcept {
298
+ DebugUtils::unused(code);
299
+
300
+ if (!hasOwnLogger())
301
+ _logger = nullptr;
302
+
303
+ if (!hasOwnErrorHandler())
304
+ _errorHandler = nullptr;
305
+
306
+ _clearEmitterFlags(~kEmitterPreservedFlags);
307
+ _forcedInstOptions = InstOptions::kReserved;
308
+ _privateData = 0;
309
+
310
+ _environment.reset();
311
+ _gpSignature.reset();
312
+
313
+ _instOptions = InstOptions::kNone;
314
+ _extraReg.reset();
315
+ _inlineComment = nullptr;
316
+
317
+ return kErrorOk;
318
+ }
319
+
320
+ void BaseEmitter::onSettingsUpdated() noexcept {
321
+ // Only called when attached to CodeHolder by CodeHolder.
322
+ ASMJIT_ASSERT(_code != nullptr);
323
+
324
+ if (!hasOwnLogger())
325
+ _logger = _code->logger();
326
+
327
+ if (!hasOwnErrorHandler())
328
+ _errorHandler = _code->errorHandler();
329
+
330
+ BaseEmitter_updateForcedOptions(this);
331
+ }
332
+
333
+ ASMJIT_END_NAMESPACE