asmjit 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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