asmjit 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/Rakefile +5 -3
  4. data/asmjit.gemspec +1 -3
  5. data/ext/asmjit/asmjit/.editorconfig +10 -0
  6. data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
  7. data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
  8. data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
  9. data/ext/asmjit/asmjit/.gitignore +6 -0
  10. data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
  11. data/ext/asmjit/asmjit/LICENSE.md +17 -0
  12. data/ext/asmjit/asmjit/README.md +69 -0
  13. data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
  14. data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
  15. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
  16. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
  17. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
  18. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
  19. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
  20. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
  21. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
  22. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
  23. data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
  24. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
  25. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
  26. data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
  27. data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
  28. data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
  29. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
  30. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
  31. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
  32. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
  33. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
  34. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
  35. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
  36. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
  37. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
  38. data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
  39. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
  40. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
  41. data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
  42. data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
  43. data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
  44. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
  45. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
  46. data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
  47. data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
  48. data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
  49. data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
  50. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
  51. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
  52. data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
  53. data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
  54. data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
  55. data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
  56. data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
  57. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
  58. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
  59. data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
  60. data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
  61. data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
  62. data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
  63. data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
  64. data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
  65. data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
  66. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
  67. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
  68. data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
  69. data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
  70. data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
  71. data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
  72. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
  73. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
  74. data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
  75. data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
  76. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
  77. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
  78. data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
  79. data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
  80. data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
  81. data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
  82. data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
  83. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
  84. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
  85. data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
  86. data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
  87. data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
  88. data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
  89. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
  90. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
  91. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
  92. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
  93. data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
  94. data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
  95. data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
  96. data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
  97. data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
  98. data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
  99. data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
  100. data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
  101. data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
  102. data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
  103. data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
  104. data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
  105. data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
  106. data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
  107. data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
  108. data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
  109. data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
  110. data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
  111. data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
  112. data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
  113. data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
  114. data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
  115. data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
  116. data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
  117. data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
  118. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
  119. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
  120. data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
  121. data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
  122. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
  123. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
  124. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
  125. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
  126. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
  127. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
  128. data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
  129. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
  130. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
  131. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
  132. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
  133. data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
  134. data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
  135. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
  136. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
  137. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
  138. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
  139. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
  140. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
  141. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
  142. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
  143. data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
  144. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
  145. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
  146. data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
  147. data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
  148. data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
  149. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
  150. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
  151. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
  152. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
  153. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
  154. data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
  155. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
  156. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
  157. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
  158. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
  159. data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
  160. data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
  161. data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
  162. data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
  163. data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
  164. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
  165. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
  166. data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
  167. data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
  168. data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
  169. data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
  170. data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
  171. data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
  172. data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
  173. data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
  174. data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
  175. data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
  176. data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
  177. data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
  178. data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
  179. data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
  180. data/ext/asmjit/asmjit/test/broken.cpp +312 -0
  181. data/ext/asmjit/asmjit/test/broken.h +148 -0
  182. data/ext/asmjit/asmjit/test/cmdline.h +61 -0
  183. data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
  184. data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
  185. data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
  186. data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
  187. data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
  188. data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
  189. data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
  190. data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
  191. data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
  192. data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
  193. data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
  194. data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
  195. data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
  196. data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
  197. data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
  198. data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
  199. data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
  200. data/ext/asmjit/asmjit.cc +167 -30
  201. data/ext/asmjit/extconf.rb +9 -9
  202. data/lib/asmjit/version.rb +1 -1
  203. data/lib/asmjit.rb +14 -4
  204. metadata +198 -17
@@ -0,0 +1,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