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,52 @@
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_X86) && !defined(ASMJIT_NO_BUILDER)
8
+
9
+ #include "../x86/x86assembler.h"
10
+ #include "../x86/x86builder.h"
11
+ #include "../x86/x86emithelper_p.h"
12
+
13
+ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
14
+
15
+ // x86::Builder - Construction & Destruction
16
+ // =========================================
17
+
18
+ Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() {
19
+ _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) |
20
+ (uint64_t(1) << uint32_t(Arch::kX64)) ;
21
+ assignEmitterFuncs(this);
22
+
23
+ if (code)
24
+ code->attach(this);
25
+ }
26
+ Builder::~Builder() noexcept {}
27
+
28
+ // x86::Builder - Events
29
+ // =====================
30
+
31
+ Error Builder::onAttach(CodeHolder* code) noexcept {
32
+ return Base::onAttach(code);
33
+ }
34
+
35
+ Error Builder::onDetach(CodeHolder* code) noexcept {
36
+ return Base::onDetach(code);
37
+ }
38
+
39
+ // x86::Builder - Finalize
40
+ // =======================
41
+
42
+ Error Builder::finalize() {
43
+ ASMJIT_PROPAGATE(runPasses());
44
+ Assembler a(_code);
45
+ a.addEncodingOptions(encodingOptions());
46
+ a.addDiagnosticOptions(diagnosticOptions());
47
+ return serializeTo(&a);
48
+ }
49
+
50
+ ASMJIT_END_SUB_NAMESPACE
51
+
52
+ #endif // !ASMJIT_NO_X86 && !ASMJIT_NO_BUILDER
@@ -0,0 +1,351 @@
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_X86_X86BUILDER_H_INCLUDED
7
+ #define ASMJIT_X86_X86BUILDER_H_INCLUDED
8
+
9
+ #include "../core/api-config.h"
10
+ #ifndef ASMJIT_NO_BUILDER
11
+
12
+ #include "../core/builder.h"
13
+ #include "../x86/x86emitter.h"
14
+
15
+ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
16
+
17
+ //! \addtogroup asmjit_x86
18
+ //! \{
19
+
20
+ //! X86/X64 builder implementation.
21
+ //!
22
+ //! The code representation used by \ref BaseBuilder is compatible with everything AsmJit provides. Each instruction
23
+ //! is stored as \ref InstNode, which contains instruction id, options, and operands. Each instruction emitted will
24
+ //! create a new \ref InstNode instance and add it to the current cursor in the double-linked list of nodes. Since
25
+ //! the instruction stream used by \ref BaseBuilder can be manipulated, we can rewrite the SumInts example from
26
+ //! \ref asmjit_assembler into the following:
27
+ //!
28
+ //! ```
29
+ //! #include <asmjit/x86.h>
30
+ //! #include <stdio.h>
31
+ //!
32
+ //! using namespace asmjit;
33
+ //!
34
+ //! typedef void (*SumIntsFunc)(int* dst, const int* a, const int* b);
35
+ //!
36
+ //! // Small helper function to print the current content of `cb`.
37
+ //! static void dumpCode(BaseBuilder& builder, const char* phase) {
38
+ //! String sb;
39
+ //! builder.dump(sb);
40
+ //! printf("%s:\n%s\n", phase, sb.data());
41
+ //! }
42
+ //!
43
+ //! int main() {
44
+ //! JitRuntime rt; // Create JIT Runtime.
45
+ //! CodeHolder code; // Create a CodeHolder.
46
+ //!
47
+ //! code.init(rt.environment()); // Initialize code to match the JIT environment.
48
+ //! x86::Builder cb(&code); // Create and attach x86::Builder to `code`.
49
+ //!
50
+ //! // Decide which registers will be mapped to function arguments. Try changing registers
51
+ //! // of `dst`, `srcA`, and `srcB` and see what happens in function's prolog and epilog.
52
+ //! x86::Gp dst = cb.zax();
53
+ //! x86::Gp srcA = cb.zcx();
54
+ //! x86::Gp srcB = cb.zdx();
55
+ //!
56
+ //! X86::Xmm vec0 = x86::xmm0;
57
+ //! X86::Xmm vec1 = x86::xmm1;
58
+ //!
59
+ //! // Create and initialize `FuncDetail`.
60
+ //! FuncDetail func;
61
+ //! func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConvId::kHost));
62
+ //!
63
+ //! // Remember prolog insertion point.
64
+ //! BaseNode* prologInsertionPoint = cb.cursor();
65
+ //!
66
+ //! // Emit function body:
67
+ //! cb.movdqu(vec0, x86::ptr(srcA)); // Load 4 ints from [srcA] to XMM0.
68
+ //! cb.movdqu(vec1, x86::ptr(srcB)); // Load 4 ints from [srcB] to XMM1.
69
+ //! cb.paddd(vec0, vec1); // Add 4 ints in XMM1 to XMM0.
70
+ //! cb.movdqu(x86::ptr(dst), vec0); // Store the result to [dst].
71
+ //!
72
+ //! // Remember epilog insertion point.
73
+ //! BaseNode* epilogInsertionPoint = cb.cursor();
74
+ //!
75
+ //! // Let's see what we have now.
76
+ //! dumpCode(cb, "Raw Function");
77
+ //!
78
+ //! // Now, after we emitted the function body, we can insert the prolog, arguments
79
+ //! // allocation, and epilog. This is not possible with using pure x86::Assembler.
80
+ //! FuncFrame frame;
81
+ //! frame.init(func);
82
+ //!
83
+ //! // Make XMM0 and XMM1 dirty; RegGroup::kVec describes XMM|YMM|ZMM registers.
84
+ //! frame.setDirtyRegs(RegGroup::kVec, IntUtils::mask(0, 1));
85
+ //!
86
+ //! FuncArgsAssignment args(&func); // Create arguments assignment context.
87
+ //! args.assignAll(dst, srcA, srcB); // Assign our registers to arguments.
88
+ //! args.updateFrame(frame); // Reflect our args in FuncFrame.
89
+ //! frame.finalize(); // Finalize the FuncFrame (updates it).
90
+ //!
91
+ //! // Insert function prolog and allocate arguments to registers.
92
+ //! cb.setCursor(prologInsertionPoint);
93
+ //! cb.emitProlog(frame);
94
+ //! cb.emitArgsAssignment(frame, args);
95
+ //!
96
+ //! // Insert function epilog.
97
+ //! cb.setCursor(epilogInsertionPoint);
98
+ //! cb.emitEpilog(frame);
99
+ //!
100
+ //! // Let's see how the function's prolog and epilog looks.
101
+ //! dumpCode(cb, "Prolog & Epilog");
102
+ //!
103
+ //! // IMPORTANT: Builder requires finalize() to be called to serialize its
104
+ //! // code to the Assembler (it automatically creates one if not attached).
105
+ //! cb.finalize();
106
+ //!
107
+ //! SumIntsFunc fn;
108
+ //! Error err = rt.add(&fn, &code); // Add the generated code to the runtime.
109
+ //! if (err) return 1; // Handle a possible error case.
110
+ //!
111
+ //! // Execute the generated function.
112
+ //! int inA[4] = { 4, 3, 2, 1 };
113
+ //! int inB[4] = { 1, 5, 2, 8 };
114
+ //! int out[4];
115
+ //! fn(out, inA, inB);
116
+ //!
117
+ //! // Prints {5 8 4 9}
118
+ //! printf("{%d %d %d %d}\n", out[0], out[1], out[2], out[3]);
119
+ //!
120
+ //! rt.release(fn); // Explicitly remove the function from the runtime.
121
+ //! return 0;
122
+ //! }
123
+ //! ```
124
+ //!
125
+ //! When the example is executed it should output the following (this one using AMD64-SystemV ABI):
126
+ //!
127
+ //! ```
128
+ //! Raw Function:
129
+ //! movdqu xmm0, [rcx]
130
+ //! movdqu xmm1, [rdx]
131
+ //! paddd xmm0, xmm1
132
+ //! movdqu [rax], xmm0
133
+ //!
134
+ //! Prolog & Epilog:
135
+ //! mov rax, rdi
136
+ //! mov rcx, rsi
137
+ //! movdqu xmm0, [rcx]
138
+ //! movdqu xmm1, [rdx]
139
+ //! paddd xmm0, xmm1
140
+ //! movdqu [rax], xmm0
141
+ //! ret
142
+ //!
143
+ //! {5 8 4 9}
144
+ //! ```
145
+ //!
146
+ //! The number of use-cases of \ref BaseBuilder is not limited and highly depends on your creativity and experience.
147
+ //! The previous example can be easily improved to collect all dirty registers inside the function programmatically
148
+ //! and to pass them to \ref FuncFrame::setDirtyRegs().
149
+ //!
150
+ //! ```
151
+ //! #include <asmjit/x86.h>
152
+ //!
153
+ //! using namespace asmjit;
154
+ //!
155
+ //! // NOTE: This function doesn't cover all possible constructs. It ignores instructions that write
156
+ //! // to implicit registers that are not part of the operand list. It also counts read-only registers.
157
+ //! // Real implementation would be a bit more complicated, but still relatively easy to implement.
158
+ //! static void collectDirtyRegs(const BaseNode* first,
159
+ //! const BaseNode* last,
160
+ //! Support::Array<RegMask, Globals::kNumVirtGroups>& regMask) {
161
+ //! const BaseNode* node = first;
162
+ //! while (node) {
163
+ //! if (node->actsAsInst()) {
164
+ //! const InstNode* inst = node->as<InstNode>();
165
+ //! const Operand* opArray = inst->operands();
166
+ //!
167
+ //! for (uint32_t i = 0, opCount = inst->opCount(); i < opCount; i++) {
168
+ //! const Operand& op = opArray[i];
169
+ //! if (op.isReg()) {
170
+ //! const x86::Reg& reg = op.as<x86::Reg>();
171
+ //! if (reg.group() <= RegGroup::kMaxVirt) {
172
+ //! regMask[reg.group()] |= 1u << reg.id();
173
+ //! }
174
+ //! }
175
+ //! }
176
+ //! }
177
+ //!
178
+ //! if (node == last)
179
+ //! break;
180
+ //! node = node->next();
181
+ //! }
182
+ //! }
183
+ //!
184
+ //! static void setDirtyRegsOfFuncFrame(const x86::Builder& builder, FuncFrame& frame) {
185
+ //! Support::Array<RegMask, Globals::kNumVirtGroups> regMask {};
186
+ //! collectDirtyRegs(builder.firstNode(), builder.lastNode(), regMask);
187
+ //!
188
+ //! // X86/X64 ABIs only require to save GP/XMM registers:
189
+ //! frame.setDirtyRegs(RegGroup::kGp, regMask[RegGroup::kGp]);
190
+ //! frame.setDirtyRegs(RegGroup::kVec, regMask[RegGroup::kVec]);
191
+ //! }
192
+ //! ```
193
+ //!
194
+ //! ### Casting Between Various Emitters
195
+ //!
196
+ //! Even when \ref BaseAssembler and \ref BaseBuilder provide the same interface as defined by \ref BaseEmitter their
197
+ //! platform dependent variants like \ref x86::Assembler and \ref x86::Builder cannot be interchanged or casted to each
198
+ //! other by using a C++ `static_cast<>`. The main reason is the inheritance graph of these classes is different and
199
+ //! cast-incompatible, as illustrated below:
200
+ //!
201
+ //! ```
202
+ //! +--------------+ +=========================+
203
+ //! +----------------------->| x86::Emitter |<--+--# x86::EmitterImplicitT<> #<--+
204
+ //! | +--------------+ | +=========================+ |
205
+ //! | (abstract) | (mixin) |
206
+ //! | +--------------+ +~~~~~~~~~~~~~~+ | |
207
+ //! +-->| BaseAssembler|---->|x86::Assembler|<--+ |
208
+ //! | +--------------+ +~~~~~~~~~~~~~~+ | |
209
+ //! | (abstract) (final) | |
210
+ //! +===============+ | +--------------+ +~~~~~~~~~~~~~~+ | |
211
+ //! # BaseEmitter #--+-->| BaseBuilder |--+->| x86::Builder |<--+ |
212
+ //! +===============+ +--------------+ | +~~~~~~~~~~~~~~+ |
213
+ //! (abstract) (abstract) | (final) |
214
+ //! +---------------------+ |
215
+ //! | |
216
+ //! | +--------------+ +~~~~~~~~~~~~~~+ +=========================+ |
217
+ //! +-->| BaseCompiler |---->| x86::Compiler|<-----# x86::EmitterExplicitT<> #---+
218
+ //! +--------------+ +~~~~~~~~~~~~~~+ +=========================+
219
+ //! (abstract) (final) (mixin)
220
+ //! ```
221
+ //!
222
+ //! The graph basically shows that it's not possible to cast between \ref x86::Assembler and \ref x86::Builder.
223
+ //! However, since both share the base interface (\ref BaseEmitter) it's possible to cast them to a class that
224
+ //! cannot be instantiated, but defines the same interface - the class is called \ref x86::Emitter and was
225
+ //! introduced to make it possible to write a function that can emit to both \ref x86::Assembler and \ref
226
+ //! x86::Builder. Note that \ref x86::Emitter cannot be created, it's abstract and has private constructors and
227
+ //! destructors; it was only designed to be casted to and used as an interface.
228
+ //!
229
+ //! Each architecture-specific emitter implements a member function called
230
+ //! `as<arch::Emitter>()`, which casts the instance to the architecture
231
+ //! specific emitter as illustrated below:
232
+ //!
233
+ //! ```
234
+ //! #include <asmjit/x86.h>
235
+ //!
236
+ //! using namespace asmjit;
237
+ //!
238
+ //! static void emitSomething(x86::Emitter* e) {
239
+ //! e->mov(x86::eax, x86::ebx);
240
+ //! }
241
+ //!
242
+ //! static void assemble(CodeHolder& code, bool useAsm) {
243
+ //! if (useAsm) {
244
+ //! x86::Assembler assembler(&code);
245
+ //! emitSomething(assembler.as<x86::Emitter>());
246
+ //! }
247
+ //! else {
248
+ //! x86::Builder builder(&code);
249
+ //! emitSomething(builder.as<x86::Emitter>());
250
+ //!
251
+ //! // NOTE: Builder requires `finalize()` to be called to serialize its
252
+ //! // content to Assembler (it automatically creates one if not attached).
253
+ //! builder.finalize();
254
+ //! }
255
+ //! }
256
+ //! ```
257
+ //!
258
+ //! The example above shows how to create a function that can emit code to either \ref x86::Assembler or \ref
259
+ //! x86::Builder through \ref x86::Emitter, which provides emitter-neutral functionality. \ref x86::Emitter,
260
+ //! however, doesn't provide any emitter-specific functionality like `setCursor()`.
261
+ //!
262
+ //! ### Code Injection and Manipulation
263
+ //!
264
+ //! \ref BaseBuilder emitter stores its nodes in a double-linked list, which makes it easy to manipulate that
265
+ //! list during the code generation or afterwards. Each node is always emitted next to the current cursor and
266
+ //! the cursor is advanced to that newly emitted node. The cursor can be retrieved and changed by \ref
267
+ //! BaseBuilder::cursor() and \ref BaseBuilder::setCursor(), respectively.
268
+ //!
269
+ //! The example below demonstrates how to remember a node and inject something
270
+ //! next to it.
271
+ //!
272
+ //! ```
273
+ //! static void example(x86::Builder& builder) {
274
+ //! // Emit something, after it returns the cursor would point at the last
275
+ //! // emitted node.
276
+ //! builder.mov(x86::rax, x86::rdx); // [1]
277
+ //!
278
+ //! // We can retrieve the node.
279
+ //! BaseNode* node = builder.cursor();
280
+ //!
281
+ //! // Change the instruction we just emitted, just for fun...
282
+ //! if (node->isInst()) {
283
+ //! InstNode* inst = node->as<InstNode>();
284
+ //! // Changes the operands at index [1] to RCX.
285
+ //! inst->setOp(1, x86::rcx);
286
+ //! }
287
+ //!
288
+ //! // ------------------------- Generate Some Code -------------------------
289
+ //! builder.add(x86::rax, x86::rdx); // [2]
290
+ //! builder.shr(x86::rax, 3); // [3]
291
+ //! // ----------------------------------------------------------------------
292
+ //!
293
+ //! // Now, we know where our node is, and we can simply change the cursor
294
+ //! // and start emitting something after it. The setCursor() function
295
+ //! // returns the previous cursor, and it's always a good practice to remember
296
+ //! // it, because you never know if you are not already injecting the code
297
+ //! // somewhere else...
298
+ //! BaseNode* oldCursor = builder.setCursor(node);
299
+ //!
300
+ //! builder.mul(x86::rax, 8); // [4]
301
+ //!
302
+ //! // Restore the cursor
303
+ //! builder.setCursor(oldCursor);
304
+ //! }
305
+ //! ```
306
+ //!
307
+ //! The function above would actually emit the following:
308
+ //!
309
+ //! ```
310
+ //! mov rax, rcx ; [1] Patched at the beginning.
311
+ //! mul rax, 8 ; [4] Injected.
312
+ //! add rax, rdx ; [2] Followed [1] initially.
313
+ //! shr rax, 3 ; [3] Follows [2].
314
+ //! ```
315
+ class ASMJIT_VIRTAPI Builder
316
+ : public BaseBuilder,
317
+ public EmitterImplicitT<Builder> {
318
+ public:
319
+ ASMJIT_NONCOPYABLE(Builder)
320
+ typedef BaseBuilder Base;
321
+
322
+ //! \name Construction & Destruction
323
+ //! \{
324
+
325
+ ASMJIT_API explicit Builder(CodeHolder* code = nullptr) noexcept;
326
+ ASMJIT_API virtual ~Builder() noexcept;
327
+
328
+ //! \}
329
+
330
+ //! \name Events
331
+ //! \{
332
+
333
+ ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
334
+ ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
335
+
336
+ //! \}
337
+
338
+ //! \name Finalize
339
+ //! \{
340
+
341
+ ASMJIT_API Error finalize() override;
342
+
343
+ //! \}
344
+ };
345
+
346
+ //! \}
347
+
348
+ ASMJIT_END_SUB_NAMESPACE
349
+
350
+ #endif // !ASMJIT_NO_BUILDER
351
+ #endif // ASMJIT_X86_X86BUILDER_H_INCLUDED
@@ -0,0 +1,61 @@
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_X86) && !defined(ASMJIT_NO_COMPILER)
8
+
9
+ #include "../x86/x86assembler.h"
10
+ #include "../x86/x86compiler.h"
11
+ #include "../x86/x86instapi_p.h"
12
+ #include "../x86/x86rapass_p.h"
13
+
14
+ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
15
+
16
+ // x86::Compiler - Construction & Destruction
17
+ // ==========================================
18
+
19
+ Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() {
20
+ _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) |
21
+ (uint64_t(1) << uint32_t(Arch::kX64)) ;
22
+ assignEmitterFuncs(this);
23
+
24
+ if (code)
25
+ code->attach(this);
26
+ }
27
+ Compiler::~Compiler() noexcept {}
28
+
29
+ // x86::Compiler - Events
30
+ // ======================
31
+
32
+ Error Compiler::onAttach(CodeHolder* code) noexcept {
33
+ ASMJIT_PROPAGATE(Base::onAttach(code));
34
+ Error err = addPassT<X86RAPass>();
35
+
36
+ if (ASMJIT_UNLIKELY(err)) {
37
+ onDetach(code);
38
+ return err;
39
+ }
40
+
41
+ return kErrorOk;
42
+ }
43
+
44
+ Error Compiler::onDetach(CodeHolder* code) noexcept {
45
+ return Base::onDetach(code);
46
+ }
47
+
48
+ // x86::Compiler - Finalize
49
+ // ========================
50
+
51
+ Error Compiler::finalize() {
52
+ ASMJIT_PROPAGATE(runPasses());
53
+ Assembler a(_code);
54
+ a.addEncodingOptions(encodingOptions());
55
+ a.addDiagnosticOptions(diagnosticOptions());
56
+ return serializeTo(&a);
57
+ }
58
+
59
+ ASMJIT_END_SUB_NAMESPACE
60
+
61
+ #endif // !ASMJIT_NO_X86 && !ASMJIT_NO_COMPILER