asmjit 0.2.0 → 0.2.1

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