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,721 @@
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_X86COMPILER_H_INCLUDED
7
+ #define ASMJIT_X86_X86COMPILER_H_INCLUDED
8
+
9
+ #include "../core/api-config.h"
10
+ #ifndef ASMJIT_NO_COMPILER
11
+
12
+ #include "../core/compiler.h"
13
+ #include "../core/type.h"
14
+ #include "../x86/x86emitter.h"
15
+
16
+ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
17
+
18
+ //! \addtogroup asmjit_x86
19
+ //! \{
20
+
21
+ //! X86/X64 compiler implementation.
22
+ //!
23
+ //! ### Compiler Basics
24
+ //!
25
+ //! The first \ref x86::Compiler example shows how to generate a function that simply returns an integer value. It's
26
+ //! an analogy to the first Assembler example:
27
+ //!
28
+ //! ```
29
+ //! #include <asmjit/x86.h>
30
+ //! #include <stdio.h>
31
+ //!
32
+ //! using namespace asmjit;
33
+ //!
34
+ //! // Signature of the generated function.
35
+ //! typedef int (*Func)(void);
36
+ //!
37
+ //! int main() {
38
+ //! JitRuntime rt; // Runtime specialized for JIT code execution.
39
+ //! CodeHolder code; // Holds code and relocation information.
40
+ //!
41
+ //! code.init(rt.environment()); // Initialize code to match the JIT environment.
42
+ //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
43
+ //!
44
+ //! cc.addFunc(FuncSignatureT<int>());// Begin a function of `int fn(void)` signature.
45
+ //!
46
+ //! x86::Gp vReg = cc.newGpd(); // Create a 32-bit general purpose register.
47
+ //! cc.mov(vReg, 1); // Move one to our virtual register `vReg`.
48
+ //! cc.ret(vReg); // Return `vReg` from the function.
49
+ //!
50
+ //! cc.endFunc(); // End of the function body.
51
+ //! cc.finalize(); // Translate and assemble the whole 'cc' content.
52
+ //! // ----> x86::Compiler is no longer needed from here and can be destroyed <----
53
+ //!
54
+ //! Func fn;
55
+ //! Error err = rt.add(&fn, &code); // Add the generated code to the runtime.
56
+ //! if (err) return 1; // Handle a possible error returned by AsmJit.
57
+ //! // ----> CodeHolder is no longer needed from here and can be destroyed <----
58
+ //!
59
+ //! int result = fn(); // Execute the generated code.
60
+ //! printf("%d\n", result); // Print the resulting "1".
61
+ //!
62
+ //! rt.release(fn); // Explicitly remove the function from the runtime.
63
+ //! return 0;
64
+ //! }
65
+ //! ```
66
+ //!
67
+ //! The \ref BaseCompiler::addFunc() and \ref BaseCompiler::endFunc() functions are used to define the function and
68
+ //! its end. Both must be called per function, but the body doesn't have to be generated in sequence. An example of
69
+ //! generating two functions will be shown later. The next example shows more complicated code that contain a loop
70
+ //! and generates a simple memory copy function that uses `uint32_t` items:
71
+ //!
72
+ //! ```
73
+ //! #include <asmjit/x86.h>
74
+ //! #include <stdio.h>
75
+ //!
76
+ //! using namespace asmjit;
77
+ //!
78
+ //! // Signature of the generated function.
79
+ //! typedef void (*MemCpy32)(uint32_t* dst, const uint32_t* src, size_t count);
80
+ //!
81
+ //! int main() {
82
+ //! JitRuntime rt; // Runtime specialized for JIT code execution.
83
+ //! CodeHolder code; // Holds code and relocation information.
84
+ //!
85
+ //! code.init(rt.environment()); // Initialize code to match the JIT environment.
86
+ //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
87
+ //!
88
+ //! FuncNode* funcNode = cc.addFunc( // Begin the function of the following signature:
89
+ //! FuncSignatureT<void, // Return value - void (no return value).
90
+ //! uint32_t*, // 1st argument - uint32_t* (machine reg-size).
91
+ //! const uint32_t*, // 2nd argument - uint32_t* (machine reg-size).
92
+ //! size_t>()); // 3rd argument - size_t (machine reg-size).
93
+ //!
94
+ //! Label L_Loop = cc.newLabel(); // Start of the loop.
95
+ //! Label L_Exit = cc.newLabel(); // Used to exit early.
96
+ //!
97
+ //! x86::Gp dst = cc.newIntPtr("dst");// Create `dst` register (destination pointer).
98
+ //! x86::Gp src = cc.newIntPtr("src");// Create `src` register (source pointer).
99
+ //! x86::Gp i = cc.newUIntPtr("i"); // Create `i` register (loop counter).
100
+ //!
101
+ //! funcNode->setArg(0, dst); // Assign `dst` argument.
102
+ //! funcNode->setArg(1, src); // Assign `src` argument.
103
+ //! funcNode->setArg(2, i); // Assign `i` argument.
104
+ //!
105
+ //! cc.test(i, i); // Early exit if length is zero.
106
+ //! cc.jz(L_Exit);
107
+ //!
108
+ //! cc.bind(L_Loop); // Bind the beginning of the loop here.
109
+ //!
110
+ //! x86::Gp tmp = cc.newInt32("tmp"); // Copy a single dword (4 bytes).
111
+ //! cc.mov(tmp, x86::dword_ptr(src)); // Load DWORD from [src] address.
112
+ //! cc.mov(x86::dword_ptr(dst), tmp); // Store DWORD to [dst] address.
113
+ //!
114
+ //! cc.add(src, 4); // Increment `src`.
115
+ //! cc.add(dst, 4); // Increment `dst`.
116
+ //!
117
+ //! cc.dec(i); // Loop until `i` is non-zero.
118
+ //! cc.jnz(L_Loop);
119
+ //!
120
+ //! cc.bind(L_Exit); // Label used by early exit.
121
+ //! cc.endFunc(); // End of the function body.
122
+ //!
123
+ //! cc.finalize(); // Translate and assemble the whole 'cc' content.
124
+ //! // ----> x86::Compiler is no longer needed from here and can be destroyed <----
125
+ //!
126
+ //! // Add the generated code to the runtime.
127
+ //! MemCpy32 memcpy32;
128
+ //! Error err = rt.add(&memcpy32, &code);
129
+ //!
130
+ //! // Handle a possible error returned by AsmJit.
131
+ //! if (err)
132
+ //! return 1;
133
+ //! // ----> CodeHolder is no longer needed from here and can be destroyed <----
134
+ //!
135
+ //! // Test the generated code.
136
+ //! uint32_t input[6] = { 1, 2, 3, 5, 8, 13 };
137
+ //! uint32_t output[6];
138
+ //! memcpy32(output, input, 6);
139
+ //!
140
+ //! for (uint32_t i = 0; i < 6; i++)
141
+ //! printf("%d\n", output[i]);
142
+ //!
143
+ //! rt.release(memcpy32);
144
+ //! return 0;
145
+ //! }
146
+ //! ```
147
+ //!
148
+ //! ### AVX and AVX-512
149
+ //!
150
+ //! AVX and AVX-512 code generation must be explicitly enabled via \ref FuncFrame to work properly. If it's not setup
151
+ //! correctly then Prolog & Epilog would use SSE instead of AVX instructions to work with SIMD registers. In addition,
152
+ //! Compiler requires explicitly enable AVX-512 via \ref FuncFrame in order to use all 32 SIMD registers.
153
+ //!
154
+ //! ```
155
+ //! #include <asmjit/x86.h>
156
+ //! #include <stdio.h>
157
+ //!
158
+ //! using namespace asmjit;
159
+ //!
160
+ //! // Signature of the generated function.
161
+ //! typedef void (*Func)(void*);
162
+ //!
163
+ //! int main() {
164
+ //! JitRuntime rt; // Runtime specialized for JIT code execution.
165
+ //! CodeHolder code; // Holds code and relocation information.
166
+ //!
167
+ //! code.init(rt.environment()); // Initialize code to match the JIT environment.
168
+ //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
169
+ //!
170
+ //! FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*>());
171
+ //!
172
+ //! // Use the following to enable AVX and/or AVX-512.
173
+ //! funcNode->frame().setAvxEnabled();
174
+ //! funcNode->frame().setAvx512Enabled();
175
+ //!
176
+ //! // Do something with the input pointer.
177
+ //! x86::Gp addr = cc.newIntPtr("addr");
178
+ //! x86::Zmm vreg = cc.newZmm("vreg");
179
+ //!
180
+ //! funcNode->setArg(0, addr);
181
+ //!
182
+ //! cc.vmovdqu32(vreg, x86::ptr(addr));
183
+ //! cc.vpaddq(vreg, vreg, vreg);
184
+ //! cc.vmovdqu32(x86::ptr(addr), vreg);
185
+ //!
186
+ //! cc.endFunc(); // End of the function body.
187
+ //! cc.finalize(); // Translate and assemble the whole 'cc' content.
188
+ //! // ----> x86::Compiler is no longer needed from here and can be destroyed <----
189
+ //!
190
+ //! Func fn;
191
+ //! Error err = rt.add(&fn, &code); // Add the generated code to the runtime.
192
+ //! if (err) return 1; // Handle a possible error returned by AsmJit.
193
+ //! // ----> CodeHolder is no longer needed from here and can be destroyed <----
194
+ //!
195
+ //! // Execute the generated code and print some output.
196
+ //! uint64_t data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
197
+ //! fn(data);
198
+ //! printf("%llu\n", (unsigned long long)data[0]);
199
+ //!
200
+ //! rt.release(fn); // Explicitly remove the function from the runtime.
201
+ //! return 0;
202
+ //! }
203
+ //! ```
204
+ //!
205
+ //! ### Recursive Functions
206
+ //!
207
+ //! It's possible to create more functions by using the same \ref x86::Compiler instance and make links between them.
208
+ //! In such case it's important to keep the pointer to \ref FuncNode.
209
+ //!
210
+ //! The example below creates a simple Fibonacci function that calls itself recursively:
211
+ //!
212
+ //! ```
213
+ //! #include <asmjit/x86.h>
214
+ //! #include <stdio.h>
215
+ //!
216
+ //! using namespace asmjit;
217
+ //!
218
+ //! // Signature of the generated function.
219
+ //! typedef uint32_t (*Fibonacci)(uint32_t x);
220
+ //!
221
+ //! int main() {
222
+ //! JitRuntime rt; // Runtime specialized for JIT code execution.
223
+ //! CodeHolder code; // Holds code and relocation information.
224
+ //!
225
+ //! code.init(rt.environment()); // Initialize code to match the JIT environment.
226
+ //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
227
+ //!
228
+ //! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc()
229
+ //! FuncSignatureT<int, int>()); // Returns a pointer to the FuncNode node.
230
+ //!
231
+ //! Label L_Exit = cc.newLabel() // Exit label.
232
+ //! x86::Gp x = cc.newUInt32(); // Function x argument.
233
+ //! x86::Gp y = cc.newUInt32(); // Temporary.
234
+ //!
235
+ //! funcNode->setArg(0, x);
236
+ //!
237
+ //! cc.cmp(x, 3); // Return x if less than 3.
238
+ //! cc.jb(L_Exit);
239
+ //!
240
+ //! cc.mov(y, x); // Make copy of the original x.
241
+ //! cc.dec(x); // Decrease x.
242
+ //!
243
+ //! InvokeNode* invokeNode; // Function invocation:
244
+ //! cc.invoke(&invokeNode, // - InvokeNode (output).
245
+ //! funcNode->label(), // - Function address or Label.
246
+ //! FuncSignatureT<int, int>()); // - Function signature.
247
+ //!
248
+ //! invokeNode->setArg(0, x); // Assign x as the first argument.
249
+ //! invokeNode->setRet(0, x); // Assign x as a return value as well.
250
+ //!
251
+ //! cc.add(x, y); // Combine the return value with y.
252
+ //!
253
+ //! cc.bind(L_Exit);
254
+ //! cc.ret(x); // Return x.
255
+ //! cc.endFunc(); // End of the function body.
256
+ //!
257
+ //! cc.finalize(); // Translate and assemble the whole 'cc' content.
258
+ //! // ----> x86::Compiler is no longer needed from here and can be destroyed <----
259
+ //!
260
+ //! Fibonacci fib;
261
+ //! Error err = rt.add(&fib, &code); // Add the generated code to the runtime.
262
+ //! if (err) return 1; // Handle a possible error returned by AsmJit.
263
+ //! // ----> CodeHolder is no longer needed from here and can be destroyed <----
264
+ //!
265
+ //! // Test the generated code.
266
+ //! printf("Fib(%u) -> %u\n", 8, fib(8));
267
+ //!
268
+ //! rt.release(fib);
269
+ //! return 0;
270
+ //! }
271
+ //! ```
272
+ //!
273
+ //! ### Stack Management
274
+ //!
275
+ //! Function's stack-frame is managed automatically, which is used by the register allocator to spill virtual
276
+ //! registers. It also provides an interface to allocate user-defined block of the stack, which can be used as
277
+ //! a temporary storage by the generated function. In the following example a stack of 256 bytes size is allocated,
278
+ //! filled by bytes starting from 0 to 255 and then iterated again to sum all the values.
279
+ //!
280
+ //! ```
281
+ //! #include <asmjit/x86.h>
282
+ //! #include <stdio.h>
283
+ //!
284
+ //! using namespace asmjit;
285
+ //!
286
+ //! // Signature of the generated function.
287
+ //! typedef int (*Func)(void);
288
+ //!
289
+ //! int main() {
290
+ //! JitRuntime rt; // Runtime specialized for JIT code execution.
291
+ //! CodeHolder code; // Holds code and relocation information.
292
+ //!
293
+ //! code.init(rt.environment()); // Initialize code to match the JIT environment.
294
+ //! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
295
+ //!
296
+ //! cc.addFunc(FuncSignatureT<int>());// Create a function that returns int.
297
+ //!
298
+ //! x86::Gp p = cc.newIntPtr("p");
299
+ //! x86::Gp i = cc.newIntPtr("i");
300
+ //!
301
+ //! // Allocate 256 bytes on the stack aligned to 4 bytes.
302
+ //! x86::Mem stack = cc.newStack(256, 4);
303
+ //!
304
+ //! x86::Mem stackIdx(stack); // Copy of stack with i added.
305
+ //! stackIdx.setIndex(i); // stackIdx <- stack[i].
306
+ //! stackIdx.setSize(1); // stackIdx <- byte ptr stack[i].
307
+ //!
308
+ //! // Load a stack address to `p`. This step is purely optional and shows
309
+ //! // that `lea` is useful to load a memory operands address (even absolute)
310
+ //! // to a general purpose register.
311
+ //! cc.lea(p, stack);
312
+ //!
313
+ //! // Clear i (xor is a C++ keyword, hence 'xor_' is used instead).
314
+ //! cc.xor_(i, i);
315
+ //!
316
+ //! Label L1 = cc.newLabel();
317
+ //! Label L2 = cc.newLabel();
318
+ //!
319
+ //! cc.bind(L1); // First loop, fill the stack.
320
+ //! cc.mov(stackIdx, i.r8()); // stack[i] = uint8_t(i).
321
+ //!
322
+ //! cc.inc(i); // i++;
323
+ //! cc.cmp(i, 256); // if (i < 256)
324
+ //! cc.jb(L1); // goto L1;
325
+ //!
326
+ //! // Second loop, sum all bytes stored in `stack`.
327
+ //! x86::Gp sum = cc.newInt32("sum");
328
+ //! x86::Gp val = cc.newInt32("val");
329
+ //!
330
+ //! cc.xor_(i, i);
331
+ //! cc.xor_(sum, sum);
332
+ //!
333
+ //! cc.bind(L2);
334
+ //!
335
+ //! cc.movzx(val, stackIdx); // val = uint32_t(stack[i]);
336
+ //! cc.add(sum, val); // sum += val;
337
+ //!
338
+ //! cc.inc(i); // i++;
339
+ //! cc.cmp(i, 256); // if (i < 256)
340
+ //! cc.jb(L2); // goto L2;
341
+ //!
342
+ //! cc.ret(sum); // Return the `sum` of all values.
343
+ //! cc.endFunc(); // End of the function body.
344
+ //!
345
+ //! cc.finalize(); // Translate and assemble the whole 'cc' content.
346
+ //! // ----> x86::Compiler is no longer needed from here and can be destroyed <----
347
+ //!
348
+ //! Func func;
349
+ //! Error err = rt.add(&func, &code); // Add the generated code to the runtime.
350
+ //! if (err) return 1; // Handle a possible error returned by AsmJit.
351
+ //! // ----> CodeHolder is no longer needed from here and can be destroyed <----
352
+ //!
353
+ //! printf("Func() -> %d\n", func()); // Test the generated code.
354
+ //!
355
+ //! rt.release(func);
356
+ //! return 0;
357
+ //! }
358
+ //! ```
359
+ //!
360
+ //! ### Constant Pool
361
+ //!
362
+ //! Compiler provides two constant pools for a general purpose code generation:
363
+ //!
364
+ //! - Local constant pool - Part of \ref FuncNode, can be only used by a single function and added after the
365
+ //! function epilog sequence (after `ret` instruction).
366
+ //!
367
+ //! - Global constant pool - Part of \ref BaseCompiler, flushed at the end of the generated code by \ref
368
+ //! BaseEmitter::finalize().
369
+ //!
370
+ //! The example below illustrates how a built-in constant pool can be used:
371
+ //!
372
+ //! ```
373
+ //! #include <asmjit/x86.h>
374
+ //!
375
+ //! using namespace asmjit;
376
+ //!
377
+ //! static void exampleUseOfConstPool(x86::Compiler& cc) {
378
+ //! cc.addFunc(FuncSignatureT<int>());
379
+ //!
380
+ //! x86::Gp v0 = cc.newGpd("v0");
381
+ //! x86::Gp v1 = cc.newGpd("v1");
382
+ //!
383
+ //! x86::Mem c0 = cc.newInt32Const(ConstPoolScope::kLocal, 200);
384
+ //! x86::Mem c1 = cc.newInt32Const(ConstPoolScope::kLocal, 33);
385
+ //!
386
+ //! cc.mov(v0, c0);
387
+ //! cc.mov(v1, c1);
388
+ //! cc.add(v0, v1);
389
+ //!
390
+ //! cc.ret(v0);
391
+ //! cc.endFunc();
392
+ //! }
393
+ //! ```
394
+ //!
395
+ //! ### Jump Tables
396
+ //!
397
+ //! x86::Compiler supports `jmp` instruction with reg/mem operand, which is a commonly used pattern to implement
398
+ //! indirect jumps within a function, for example to implement `switch()` statement in a programming languages.
399
+ //! By default AsmJit assumes that every basic block can be a possible jump target as it's unable to deduce targets
400
+ //! from instruction's operands. This is a very pessimistic default that should be avoided if possible as it's costly
401
+ //! and very unfriendly to liveness analysis and register allocation.
402
+ //!
403
+ //! Instead of relying on such pessimistic default behavior, let's use \ref JumpAnnotation to annotate a jump where
404
+ //! all targets are known:
405
+ //!
406
+ //! ```
407
+ //! #include <asmjit/x86.h>
408
+ //!
409
+ //! using namespace asmjit;
410
+ //!
411
+ //! static void exampleUseOfIndirectJump(x86::Compiler& cc) {
412
+ //! FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float, uint32_t>(CallConvId::kHost));
413
+ //!
414
+ //! // Function arguments
415
+ //! x86::Xmm a = cc.newXmmSs("a");
416
+ //! x86::Xmm b = cc.newXmmSs("b");
417
+ //! x86::Gp op = cc.newUInt32("op");
418
+ //!
419
+ //! x86::Gp target = cc.newIntPtr("target");
420
+ //! x86::Gp offset = cc.newIntPtr("offset");
421
+ //!
422
+ //! Label L_Table = cc.newLabel();
423
+ //! Label L_Add = cc.newLabel();
424
+ //! Label L_Sub = cc.newLabel();
425
+ //! Label L_Mul = cc.newLabel();
426
+ //! Label L_Div = cc.newLabel();
427
+ //! Label L_End = cc.newLabel();
428
+ //!
429
+ //! funcNode->setArg(0, a);
430
+ //! funcNode->setArg(1, b);
431
+ //! funcNode->setArg(2, op);
432
+ //!
433
+ //! // Jump annotation is a building block that allows to annotate all possible targets where `jmp()` can
434
+ //! // jump. It then drives the CFG construction and liveness analysis, which impacts register allocation.
435
+ //! JumpAnnotation* annotation = cc.newJumpAnnotation();
436
+ //! annotation->addLabel(L_Add);
437
+ //! annotation->addLabel(L_Sub);
438
+ //! annotation->addLabel(L_Mul);
439
+ //! annotation->addLabel(L_Div);
440
+ //!
441
+ //! // Most likely not the common indirect jump approach, but it
442
+ //! // doesn't really matter how final address is calculated. The
443
+ //! // most important path using JumpAnnotation with `jmp()`.
444
+ //! cc.lea(offset, x86::ptr(L_Table));
445
+ //! if (cc.is64Bit())
446
+ //! cc.movsxd(target, x86::dword_ptr(offset, op.cloneAs(offset), 2));
447
+ //! else
448
+ //! cc.mov(target, x86::dword_ptr(offset, op.cloneAs(offset), 2));
449
+ //! cc.add(target, offset);
450
+ //! cc.jmp(target, annotation);
451
+ //!
452
+ //! // Acts like a switch() statement in C.
453
+ //! cc.bind(L_Add);
454
+ //! cc.addss(a, b);
455
+ //! cc.jmp(L_End);
456
+ //!
457
+ //! cc.bind(L_Sub);
458
+ //! cc.subss(a, b);
459
+ //! cc.jmp(L_End);
460
+ //!
461
+ //! cc.bind(L_Mul);
462
+ //! cc.mulss(a, b);
463
+ //! cc.jmp(L_End);
464
+ //!
465
+ //! cc.bind(L_Div);
466
+ //! cc.divss(a, b);
467
+ //!
468
+ //! cc.bind(L_End);
469
+ //! cc.ret(a);
470
+ //!
471
+ //! cc.endFunc();
472
+ //!
473
+ //! // Relative int32_t offsets of `L_XXX - L_Table`.
474
+ //! cc.bind(L_Table);
475
+ //! cc.embedLabelDelta(L_Add, L_Table, 4);
476
+ //! cc.embedLabelDelta(L_Sub, L_Table, 4);
477
+ //! cc.embedLabelDelta(L_Mul, L_Table, 4);
478
+ //! cc.embedLabelDelta(L_Div, L_Table, 4);
479
+ //! }
480
+ //! ```
481
+ class ASMJIT_VIRTAPI Compiler
482
+ : public BaseCompiler,
483
+ public EmitterExplicitT<Compiler> {
484
+ public:
485
+ ASMJIT_NONCOPYABLE(Compiler)
486
+ typedef BaseCompiler Base;
487
+
488
+ //! \name Construction & Destruction
489
+ //! \{
490
+
491
+ ASMJIT_API explicit Compiler(CodeHolder* code = nullptr) noexcept;
492
+ ASMJIT_API virtual ~Compiler() noexcept;
493
+
494
+ //! \}
495
+
496
+ //! \name Virtual Registers
497
+ //! \{
498
+
499
+ #ifndef ASMJIT_NO_LOGGING
500
+ # define ASMJIT_NEW_REG_FMT(OUT, PARAM, FORMAT, ARGS) \
501
+ _newRegFmt(&OUT, PARAM, FORMAT, ARGS)
502
+ #else
503
+ # define ASMJIT_NEW_REG_FMT(OUT, PARAM, FORMAT, ARGS) \
504
+ DebugUtils::unused(FORMAT); \
505
+ DebugUtils::unused(std::forward<Args>(args)...); \
506
+ _newReg(&OUT, PARAM)
507
+ #endif
508
+
509
+ #define ASMJIT_NEW_REG_CUSTOM(FUNC, REG) \
510
+ inline REG FUNC(TypeId typeId) { \
511
+ REG reg(Globals::NoInit); \
512
+ _newReg(&reg, typeId); \
513
+ return reg; \
514
+ } \
515
+ \
516
+ template<typename... Args> \
517
+ inline REG FUNC(TypeId typeId, const char* fmt, Args&&... args) { \
518
+ REG reg(Globals::NoInit); \
519
+ ASMJIT_NEW_REG_FMT(reg, typeId, fmt, std::forward<Args>(args)...); \
520
+ return reg; \
521
+ }
522
+
523
+ #define ASMJIT_NEW_REG_TYPED(FUNC, REG, TYPE_ID) \
524
+ inline REG FUNC() { \
525
+ REG reg(Globals::NoInit); \
526
+ _newReg(&reg, TYPE_ID); \
527
+ return reg; \
528
+ } \
529
+ \
530
+ template<typename... Args> \
531
+ inline REG FUNC(const char* fmt, Args&&... args) { \
532
+ REG reg(Globals::NoInit); \
533
+ ASMJIT_NEW_REG_FMT(reg, TYPE_ID, fmt, std::forward<Args>(args)...); \
534
+ return reg; \
535
+ }
536
+
537
+ template<typename RegT>
538
+ inline RegT newSimilarReg(const RegT& ref) {
539
+ RegT reg(Globals::NoInit);
540
+ _newReg(reg, ref);
541
+ return reg;
542
+ }
543
+
544
+ template<typename RegT, typename... Args>
545
+ inline RegT newSimilarReg(const RegT& ref, const char* fmt, Args&&... args) {
546
+ RegT reg(Globals::NoInit);
547
+ ASMJIT_NEW_REG_FMT(reg, ref, fmt, std::forward<Args>(args)...);
548
+ return reg;
549
+ }
550
+
551
+ ASMJIT_NEW_REG_CUSTOM(newReg , Reg )
552
+ ASMJIT_NEW_REG_CUSTOM(newGp , Gp )
553
+ ASMJIT_NEW_REG_CUSTOM(newVec , Vec )
554
+ ASMJIT_NEW_REG_CUSTOM(newK , KReg)
555
+
556
+ ASMJIT_NEW_REG_TYPED(newInt8 , Gp , TypeId::kInt8)
557
+ ASMJIT_NEW_REG_TYPED(newUInt8 , Gp , TypeId::kUInt8)
558
+ ASMJIT_NEW_REG_TYPED(newInt16 , Gp , TypeId::kInt16)
559
+ ASMJIT_NEW_REG_TYPED(newUInt16 , Gp , TypeId::kUInt16)
560
+ ASMJIT_NEW_REG_TYPED(newInt32 , Gp , TypeId::kInt32)
561
+ ASMJIT_NEW_REG_TYPED(newUInt32 , Gp , TypeId::kUInt32)
562
+ ASMJIT_NEW_REG_TYPED(newInt64 , Gp , TypeId::kInt64)
563
+ ASMJIT_NEW_REG_TYPED(newUInt64 , Gp , TypeId::kUInt64)
564
+ ASMJIT_NEW_REG_TYPED(newIntPtr , Gp , TypeId::kIntPtr)
565
+ ASMJIT_NEW_REG_TYPED(newUIntPtr, Gp , TypeId::kUIntPtr)
566
+
567
+ ASMJIT_NEW_REG_TYPED(newGpb , Gp , TypeId::kUInt8)
568
+ ASMJIT_NEW_REG_TYPED(newGpw , Gp , TypeId::kUInt16)
569
+ ASMJIT_NEW_REG_TYPED(newGpd , Gp , TypeId::kUInt32)
570
+ ASMJIT_NEW_REG_TYPED(newGpq , Gp , TypeId::kUInt64)
571
+ ASMJIT_NEW_REG_TYPED(newGpz , Gp , TypeId::kUIntPtr)
572
+ ASMJIT_NEW_REG_TYPED(newXmm , Xmm , TypeId::kInt32x4)
573
+ ASMJIT_NEW_REG_TYPED(newXmmSs , Xmm , TypeId::kFloat32x1)
574
+ ASMJIT_NEW_REG_TYPED(newXmmSd , Xmm , TypeId::kFloat64x1)
575
+ ASMJIT_NEW_REG_TYPED(newXmmPs , Xmm , TypeId::kFloat32x4)
576
+ ASMJIT_NEW_REG_TYPED(newXmmPd , Xmm , TypeId::kFloat64x2)
577
+ ASMJIT_NEW_REG_TYPED(newYmm , Ymm , TypeId::kInt32x8)
578
+ ASMJIT_NEW_REG_TYPED(newYmmPs , Ymm , TypeId::kFloat32x8)
579
+ ASMJIT_NEW_REG_TYPED(newYmmPd , Ymm , TypeId::kFloat64x4)
580
+ ASMJIT_NEW_REG_TYPED(newZmm , Zmm , TypeId::kInt32x16)
581
+ ASMJIT_NEW_REG_TYPED(newZmmPs , Zmm , TypeId::kFloat32x16)
582
+ ASMJIT_NEW_REG_TYPED(newZmmPd , Zmm , TypeId::kFloat64x8)
583
+ ASMJIT_NEW_REG_TYPED(newMm , Mm , TypeId::kMmx64)
584
+ ASMJIT_NEW_REG_TYPED(newKb , KReg, TypeId::kMask8)
585
+ ASMJIT_NEW_REG_TYPED(newKw , KReg, TypeId::kMask16)
586
+ ASMJIT_NEW_REG_TYPED(newKd , KReg, TypeId::kMask32)
587
+ ASMJIT_NEW_REG_TYPED(newKq , KReg, TypeId::kMask64)
588
+
589
+ #undef ASMJIT_NEW_REG_TYPED
590
+ #undef ASMJIT_NEW_REG_CUSTOM
591
+ #undef ASMJIT_NEW_REG_FMT
592
+
593
+ //! \}
594
+
595
+ //! \name Stack
596
+ //! \{
597
+
598
+ //! Creates a new memory chunk allocated on the current function's stack.
599
+ inline Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
600
+ Mem m(Globals::NoInit);
601
+ _newStack(&m, size, alignment, name);
602
+ return m;
603
+ }
604
+
605
+ //! \}
606
+
607
+ //! \name Constants
608
+ //! \{
609
+
610
+ //! Put data to a constant-pool and get a memory reference to it.
611
+ inline Mem newConst(ConstPoolScope scope, const void* data, size_t size) {
612
+ Mem m(Globals::NoInit);
613
+ _newConst(&m, scope, data, size);
614
+ return m;
615
+ }
616
+
617
+ //! Put a BYTE `val` to a constant-pool.
618
+ inline Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); }
619
+ //! Put a WORD `val` to a constant-pool.
620
+ inline Mem newWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
621
+ //! Put a DWORD `val` to a constant-pool.
622
+ inline Mem newDWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
623
+ //! Put a QWORD `val` to a constant-pool.
624
+ inline Mem newQWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
625
+
626
+ //! Put a WORD `val` to a constant-pool.
627
+ inline Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); }
628
+ //! Put a WORD `val` to a constant-pool.
629
+ inline Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
630
+ //! Put a DWORD `val` to a constant-pool.
631
+ inline Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); }
632
+ //! Put a DWORD `val` to a constant-pool.
633
+ inline Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
634
+ //! Put a QWORD `val` to a constant-pool.
635
+ inline Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); }
636
+ //! Put a QWORD `val` to a constant-pool.
637
+ inline Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
638
+
639
+ //! Put a SP-FP `val` to a constant-pool.
640
+ inline Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); }
641
+ //! Put a DP-FP `val` to a constant-pool.
642
+ inline Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); }
643
+
644
+ //! \}
645
+
646
+ //! \name Instruction Options
647
+ //! \{
648
+
649
+ //! Force the compiler to not follow the conditional or unconditional jump.
650
+ inline Compiler& unfollow() noexcept { addInstOptions(InstOptions::kUnfollow); return *this; }
651
+ //! Tell the compiler that the destination variable will be overwritten.
652
+ inline Compiler& overwrite() noexcept { addInstOptions(InstOptions::kOverwrite); return *this; }
653
+
654
+ //! \}
655
+
656
+ //! \name Function Call & Ret Intrinsics
657
+ //! \{
658
+
659
+ //! Invoke a function call without `target` type enforcement.
660
+ inline Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) {
661
+ return addInvokeNode(out, Inst::kIdCall, target, signature);
662
+ }
663
+
664
+ //! Invoke a function call of the given `target` and `signature` and store the added node to `out`.
665
+ //!
666
+ //! Creates a new \ref InvokeNode, initializes all the necessary members to match the given function `signature`,
667
+ //! adds the node to the compiler, and stores its pointer to `out`. The operation is atomic, if anything fails
668
+ //! nullptr is stored in `out` and error code is returned.
669
+ inline Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
670
+ //! \overload
671
+ inline Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
672
+ //! \overload
673
+ inline Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
674
+ //! \overload
675
+ inline Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
676
+ //! \overload
677
+ inline Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); }
678
+
679
+ //! Return from function.
680
+ inline Error ret() { return addRet(Operand(), Operand()); }
681
+ //! \overload
682
+ inline Error ret(const BaseReg& o0) { return addRet(o0, Operand()); }
683
+ //! \overload
684
+ inline Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); }
685
+
686
+ //! \}
687
+
688
+ //! \name Jump Tables Support
689
+ //! \{
690
+
691
+ using EmitterExplicitT<Compiler>::jmp;
692
+
693
+ //! Adds a jump to the given `target` with the provided jump `annotation`.
694
+ inline Error jmp(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); }
695
+ //! \overload
696
+ inline Error jmp(const BaseMem& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); }
697
+
698
+ //! \}
699
+
700
+ //! \name Events
701
+ //! \{
702
+
703
+ ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
704
+ ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
705
+
706
+ //! \}
707
+
708
+ //! \name Finalize
709
+ //! \{
710
+
711
+ ASMJIT_API Error finalize() override;
712
+
713
+ //! \}
714
+ };
715
+
716
+ //! \}
717
+
718
+ ASMJIT_END_SUB_NAMESPACE
719
+
720
+ #endif // !ASMJIT_NO_COMPILER
721
+ #endif // ASMJIT_X86_X86COMPILER_H_INCLUDED