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,737 @@
1
+ // This file is part of AsmJit project <https://asmjit.com>
2
+ //
3
+ // See asmjit.h or LICENSE.md for license and copyright information
4
+ // SPDX-License-Identifier: Zlib
5
+
6
+ #ifndef ASMJIT_CORE_COMPILER_H_INCLUDED
7
+ #define ASMJIT_CORE_COMPILER_H_INCLUDED
8
+
9
+ #include "../core/api-config.h"
10
+ #ifndef ASMJIT_NO_COMPILER
11
+
12
+ #include "../core/assembler.h"
13
+ #include "../core/builder.h"
14
+ #include "../core/constpool.h"
15
+ #include "../core/compilerdefs.h"
16
+ #include "../core/func.h"
17
+ #include "../core/inst.h"
18
+ #include "../core/operand.h"
19
+ #include "../core/support.h"
20
+ #include "../core/zone.h"
21
+ #include "../core/zonevector.h"
22
+
23
+ ASMJIT_BEGIN_NAMESPACE
24
+
25
+ class JumpAnnotation;
26
+ class JumpNode;
27
+ class FuncNode;
28
+ class FuncRetNode;
29
+ class InvokeNode;
30
+
31
+ //! \addtogroup asmjit_compiler
32
+ //! \{
33
+
34
+ //! Code emitter that uses virtual registers and performs register allocation.
35
+ //!
36
+ //! Compiler is a high-level code-generation tool that provides register allocation and automatic handling of function
37
+ //! calling conventions. It was primarily designed for merging multiple parts of code into a function without worrying
38
+ //! about registers and function calling conventions.
39
+ //!
40
+ //! BaseCompiler can be used, with a minimum effort, to handle 32-bit and 64-bit code generation within a single code
41
+ //! base.
42
+ //!
43
+ //! BaseCompiler is based on BaseBuilder and contains all the features it provides. It means that the code it stores
44
+ //! can be modified (removed, added, injected) and analyzed. When the code is finalized the compiler can emit the code
45
+ //! into an Assembler to translate the abstract representation into a machine code.
46
+ //!
47
+ //! Check out architecture specific compilers for more details and examples:
48
+ //!
49
+ //! - \ref x86::Compiler - X86/X64 compiler implementation.
50
+ class ASMJIT_VIRTAPI BaseCompiler : public BaseBuilder {
51
+ public:
52
+ ASMJIT_NONCOPYABLE(BaseCompiler)
53
+ typedef BaseBuilder Base;
54
+
55
+ //! \name Members
56
+ //! \{
57
+
58
+ //! Current function.
59
+ FuncNode* _func;
60
+ //! Allocates `VirtReg` objects.
61
+ Zone _vRegZone;
62
+ //! Stores array of `VirtReg` pointers.
63
+ ZoneVector<VirtReg*> _vRegArray;
64
+ //! Stores jump annotations.
65
+ ZoneVector<JumpAnnotation*> _jumpAnnotations;
66
+
67
+ //! Local and global constant pools.
68
+ //!
69
+ //! Local constant pool is flushed with each function, global constant pool is flushed only by \ref finalize().
70
+ ConstPoolNode* _constPools[2];
71
+
72
+ //! \}
73
+
74
+ //! \name Construction & Destruction
75
+ //! \{
76
+
77
+ //! Creates a new `BaseCompiler` instance.
78
+ ASMJIT_API BaseCompiler() noexcept;
79
+ //! Destroys the `BaseCompiler` instance.
80
+ ASMJIT_API virtual ~BaseCompiler() noexcept;
81
+
82
+ //! \}
83
+
84
+ //! \name Function Management
85
+ //! \{
86
+
87
+ //! Creates a new \ref FuncNode.
88
+ ASMJIT_API Error newFuncNode(FuncNode** ASMJIT_NONNULL(out), const FuncSignature& signature);
89
+ //! Creates a new \ref FuncNode adds it to the instruction stream.
90
+ ASMJIT_API Error addFuncNode(FuncNode** ASMJIT_NONNULL(out), const FuncSignature& signature);
91
+
92
+ //! Creates a new \ref FuncRetNode.
93
+ ASMJIT_API Error newFuncRetNode(FuncRetNode** ASMJIT_NONNULL(out), const Operand_& o0, const Operand_& o1);
94
+ //! Creates a new \ref FuncRetNode and adds it to the instruction stream.
95
+ ASMJIT_API Error addFuncRetNode(FuncRetNode** ASMJIT_NONNULL(out), const Operand_& o0, const Operand_& o1);
96
+
97
+ //! Returns the current function.
98
+ inline FuncNode* func() const noexcept { return _func; }
99
+
100
+ //! Creates a new \ref FuncNode with the given `signature` and returns it.
101
+ inline FuncNode* newFunc(const FuncSignature& signature) {
102
+ FuncNode* node;
103
+ newFuncNode(&node, signature);
104
+ return node;
105
+ }
106
+
107
+ //! Creates a new \ref FuncNode with the given `signature`, adds it to the instruction stream by using
108
+ //! the \ref addFunc(FuncNode*) overload, and returns it.
109
+ inline FuncNode* addFunc(const FuncSignature& signature) {
110
+ FuncNode* node;
111
+ addFuncNode(&node, signature);
112
+ return node;
113
+ }
114
+
115
+ //! Adds a function `node` to the instruction stream.
116
+ ASMJIT_API FuncNode* addFunc(FuncNode* ASMJIT_NONNULL(func));
117
+ //! Emits a sentinel that marks the end of the current function.
118
+ ASMJIT_API Error endFunc();
119
+
120
+ #if !defined(ASMJIT_NO_DEPRECATED)
121
+ inline Error _setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg);
122
+
123
+ //! Sets a function argument at `argIndex` to `reg`.
124
+ ASMJIT_DEPRECATED("Setting arguments through Compiler is deprecated, use FuncNode->setArg() instead")
125
+ inline Error setArg(size_t argIndex, const BaseReg& reg) { return _setArg(argIndex, 0, reg); }
126
+
127
+ //! Sets a function argument at `argIndex` at `valueIndex` to `reg`.
128
+ ASMJIT_DEPRECATED("Setting arguments through Compiler is deprecated, use FuncNode->setArg() instead")
129
+ inline Error setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) { return _setArg(argIndex, valueIndex, reg); }
130
+ #endif
131
+
132
+ inline Error addRet(const Operand_& o0, const Operand_& o1) {
133
+ FuncRetNode* node;
134
+ return addFuncRetNode(&node, o0, o1);
135
+ }
136
+
137
+ //! \}
138
+
139
+ //! \name Function Invocation
140
+ //! \{
141
+
142
+ //! Creates a new \ref InvokeNode.
143
+ ASMJIT_API Error newInvokeNode(InvokeNode** ASMJIT_NONNULL(out), InstId instId, const Operand_& o0, const FuncSignature& signature);
144
+ //! Creates a new \ref InvokeNode and adds it to the instruction stream.
145
+ ASMJIT_API Error addInvokeNode(InvokeNode** ASMJIT_NONNULL(out), InstId instId, const Operand_& o0, const FuncSignature& signature);
146
+
147
+ //! \}
148
+
149
+ //! \name Virtual Registers
150
+ //! \{
151
+
152
+ //! Creates a new virtual register representing the given `typeId` and `signature`.
153
+ //!
154
+ //! \note This function is public, but it's not generally recommended to be used by AsmJit users, use architecture
155
+ //! specific `newReg()` functionality instead or functions like \ref _newReg() and \ref _newRegFmt().
156
+ ASMJIT_API Error newVirtReg(VirtReg** ASMJIT_NONNULL(out), TypeId typeId, OperandSignature signature, const char* name);
157
+
158
+ //! Creates a new virtual register of the given `typeId` and stores it to `out` operand.
159
+ ASMJIT_API Error _newReg(BaseReg* ASMJIT_NONNULL(out), TypeId typeId, const char* name = nullptr);
160
+
161
+ //! Creates a new virtual register of the given `typeId` and stores it to `out` operand.
162
+ //!
163
+ //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments.
164
+ ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId, const char* fmt, ...);
165
+
166
+ //! Creates a new virtual register compatible with the provided reference register `ref`.
167
+ ASMJIT_API Error _newReg(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* name = nullptr);
168
+
169
+ //! Creates a new virtual register compatible with the provided reference register `ref`.
170
+ //!
171
+ //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments.
172
+ ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* fmt, ...);
173
+
174
+ //! Tests whether the given `id` is a valid virtual register id.
175
+ inline bool isVirtIdValid(uint32_t id) const noexcept {
176
+ uint32_t index = Operand::virtIdToIndex(id);
177
+ return index < _vRegArray.size();
178
+ }
179
+ //! Tests whether the given `reg` is a virtual register having a valid id.
180
+ inline bool isVirtRegValid(const BaseReg& reg) const noexcept {
181
+ return isVirtIdValid(reg.id());
182
+ }
183
+
184
+ //! Returns \ref VirtReg associated with the given `id`.
185
+ inline VirtReg* virtRegById(uint32_t id) const noexcept {
186
+ ASMJIT_ASSERT(isVirtIdValid(id));
187
+ return _vRegArray[Operand::virtIdToIndex(id)];
188
+ }
189
+
190
+ //! Returns \ref VirtReg associated with the given `reg`.
191
+ inline VirtReg* virtRegByReg(const BaseReg& reg) const noexcept { return virtRegById(reg.id()); }
192
+
193
+ //! Returns \ref VirtReg associated with the given virtual register `index`.
194
+ //!
195
+ //! \note This is not the same as virtual register id. The conversion between id and its index is implemented
196
+ //! by \ref Operand_::virtIdToIndex() and \ref Operand_::indexToVirtId() functions.
197
+ inline VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; }
198
+
199
+ //! Returns an array of all virtual registers managed by the Compiler.
200
+ inline const ZoneVector<VirtReg*>& virtRegs() const noexcept { return _vRegArray; }
201
+
202
+ //! \name Stack
203
+ //! \{
204
+
205
+ //! Creates a new stack of the given `size` and `alignment` and stores it to `out`.
206
+ //!
207
+ //! \note `name` can be used to give the stack a name, for debugging purposes.
208
+ ASMJIT_API Error _newStack(BaseMem* ASMJIT_NONNULL(out), uint32_t size, uint32_t alignment, const char* name = nullptr);
209
+
210
+ //! Updates the stack size of a stack created by `_newStack()` by its `virtId`.
211
+ ASMJIT_API Error setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment = 0);
212
+
213
+ //! Updates the stack size of a stack created by `_newStack()`.
214
+ inline Error setStackSize(const BaseMem& mem, uint32_t newSize, uint32_t newAlignment = 0) {
215
+ return setStackSize(mem.id(), newSize, newAlignment);
216
+ }
217
+
218
+ //! \}
219
+
220
+ //! \name Constants
221
+ //! \{
222
+
223
+ //! Creates a new constant of the given `scope` (see \ref ConstPoolScope).
224
+ //!
225
+ //! This function adds a constant of the given `size` to the built-in \ref ConstPool and stores the reference to that
226
+ //! constant to the `out` operand.
227
+ ASMJIT_API Error _newConst(BaseMem* ASMJIT_NONNULL(out), ConstPoolScope scope, const void* data, size_t size);
228
+
229
+ //! \}
230
+
231
+ //! \name Miscellaneous
232
+ //! \{
233
+
234
+ //! Rename the given virtual register `reg` to a formatted string `fmt`.
235
+ ASMJIT_API void rename(const BaseReg& reg, const char* fmt, ...);
236
+
237
+ //! \}
238
+
239
+ //! \name Jump Annotations
240
+ //! \{
241
+
242
+ inline const ZoneVector<JumpAnnotation*>& jumpAnnotations() const noexcept {
243
+ return _jumpAnnotations;
244
+ }
245
+
246
+ ASMJIT_API Error newJumpNode(JumpNode** ASMJIT_NONNULL(out), InstId instId, InstOptions instOptions, const Operand_& o0, JumpAnnotation* annotation);
247
+ ASMJIT_API Error emitAnnotatedJump(InstId instId, const Operand_& o0, JumpAnnotation* annotation);
248
+
249
+ //! Returns a new `JumpAnnotation` instance, which can be used to aggregate possible targets of a jump where the
250
+ //! target is not a label, for example to implement jump tables.
251
+ ASMJIT_API JumpAnnotation* newJumpAnnotation();
252
+
253
+ //! \}
254
+
255
+ //! \name Events
256
+ //! \{
257
+
258
+ ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
259
+ ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
260
+
261
+ //! \}
262
+ };
263
+
264
+ //! Jump annotation used to annotate jumps.
265
+ //!
266
+ //! \ref BaseCompiler allows to emit jumps where the target is either register or memory operand. Such jumps cannot be
267
+ //! trivially inspected, so instead of doing heuristics AsmJit allows to annotate such jumps with possible targets.
268
+ //! Register allocator then uses the annotation to construct control-flow, which is then used by liveness analysis and
269
+ //! other tools to prepare ground for register allocation.
270
+ class JumpAnnotation {
271
+ public:
272
+ ASMJIT_NONCOPYABLE(JumpAnnotation)
273
+
274
+ //! \name Members
275
+ //! \{
276
+
277
+ //! Compiler that owns this JumpAnnotation.
278
+ BaseCompiler* _compiler;
279
+ //! Annotation identifier.
280
+ uint32_t _annotationId;
281
+ //! Vector of label identifiers, see \ref labelIds().
282
+ ZoneVector<uint32_t> _labelIds;
283
+
284
+ //! \}
285
+
286
+ //! \name Construction & Destruction
287
+ //! \{
288
+
289
+ inline JumpAnnotation(BaseCompiler* ASMJIT_NONNULL(compiler), uint32_t annotationId) noexcept
290
+ : _compiler(compiler),
291
+ _annotationId(annotationId) {}
292
+
293
+ //! \}
294
+
295
+ //! \name Accessors
296
+ //! \{
297
+
298
+ //! Returns the compiler that owns this JumpAnnotation.
299
+ inline BaseCompiler* compiler() const noexcept { return _compiler; }
300
+ //! Returns the annotation id.
301
+ inline uint32_t annotationId() const noexcept { return _annotationId; }
302
+ //! Returns a vector of label identifiers that lists all targets of the jump.
303
+ const ZoneVector<uint32_t>& labelIds() const noexcept { return _labelIds; }
304
+
305
+ //! Tests whether the given `label` is a target of this JumpAnnotation.
306
+ inline bool hasLabel(const Label& label) const noexcept { return hasLabelId(label.id()); }
307
+ //! Tests whether the given `labelId` is a target of this JumpAnnotation.
308
+ inline bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); }
309
+
310
+ //! \}
311
+
312
+ //! \name Annotation Building API
313
+ //! \{
314
+
315
+ //! Adds the `label` to the list of targets of this JumpAnnotation.
316
+ inline Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); }
317
+ //! Adds the `labelId` to the list of targets of this JumpAnnotation.
318
+ inline Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); }
319
+
320
+ //! \}
321
+ };
322
+
323
+ //! Jump instruction with \ref JumpAnnotation.
324
+ //!
325
+ //! \note This node should be only used to represent jump where the jump target cannot be deduced by examining
326
+ //! instruction operands. For example if the jump target is register or memory location. This pattern is often
327
+ //! used to perform indirect jumps that use jump table, e.g. to implement `switch{}` statement.
328
+ class JumpNode : public InstNode {
329
+ public:
330
+ ASMJIT_NONCOPYABLE(JumpNode)
331
+
332
+ //! \name Members
333
+ //! \{
334
+
335
+ JumpAnnotation* _annotation;
336
+
337
+ //! \}
338
+
339
+ //! \name Construction & Destruction
340
+ //! \{
341
+
342
+ inline JumpNode(BaseCompiler* ASMJIT_NONNULL(cc), InstId instId, InstOptions options, uint32_t opCount, JumpAnnotation* annotation) noexcept
343
+ : InstNode(cc, instId, options, opCount, kBaseOpCapacity),
344
+ _annotation(annotation) {
345
+ setType(NodeType::kJump);
346
+ }
347
+
348
+ //! \}
349
+
350
+ //! \name Accessors
351
+ //! \{
352
+
353
+ //! Tests whether this JumpNode has associated a \ref JumpAnnotation.
354
+ inline bool hasAnnotation() const noexcept { return _annotation != nullptr; }
355
+ //! Returns the \ref JumpAnnotation associated with this jump, or `nullptr`.
356
+ inline JumpAnnotation* annotation() const noexcept { return _annotation; }
357
+ //! Sets the \ref JumpAnnotation associated with this jump to `annotation`.
358
+ inline void setAnnotation(JumpAnnotation* annotation) noexcept { _annotation = annotation; }
359
+
360
+ //! \}
361
+ };
362
+
363
+ //! Function node represents a function used by \ref BaseCompiler.
364
+ //!
365
+ //! A function is composed of the following:
366
+ //!
367
+ //! - Function entry, \ref FuncNode acts as a label, so the entry is implicit. To get the entry, simply use
368
+ //! \ref FuncNode::label(), which is the same as \ref LabelNode::label().
369
+ //!
370
+ //! - Function exit, which is represented by \ref FuncNode::exitNode(). A helper function
371
+ //! \ref FuncNode::exitLabel() exists and returns an exit label instead of node.
372
+ //!
373
+ //! - Function \ref FuncNode::endNode() sentinel. This node marks the end of a function - there should be no
374
+ //! code that belongs to the function after this node, but the Compiler doesn't enforce that at the moment.
375
+ //!
376
+ //! - Function detail, see \ref FuncNode::detail().
377
+ //!
378
+ //! - Function frame, see \ref FuncNode::frame().
379
+ //!
380
+ //! - Function arguments mapped to virtual registers, see \ref FuncNode::argPacks().
381
+ //!
382
+ //! In a node list, the function and its body looks like the following:
383
+ //!
384
+ //! \code{.unparsed}
385
+ //! [...] - Anything before the function.
386
+ //!
387
+ //! [FuncNode] - Entry point of the function, acts as a label as well.
388
+ //! <Prolog> - Prolog inserted by the register allocator.
389
+ //! {...} - Function body - user code basically.
390
+ //! [ExitLabel] - Exit label
391
+ //! <Epilog> - Epilog inserted by the register allocator.
392
+ //! <Return> - Return inserted by the register allocator.
393
+ //! {...} - Can contain data or user code (error handling, special cases, ...).
394
+ //! [FuncEnd] - End sentinel
395
+ //!
396
+ //! [...] - Anything after the function.
397
+ //! \endcode
398
+ //!
399
+ //! When a function is added to the instruction stream by \ref BaseCompiler::addFunc() it actually inserts 3 nodes
400
+ //! (FuncNode, ExitLabel, and FuncEnd) and sets the current cursor to be FuncNode. When \ref BaseCompiler::endFunc()
401
+ //! is called the cursor is set to FuncEnd. This guarantees that user can use ExitLabel as a marker after additional
402
+ //! code or data can be placed, which is a common practice.
403
+ class FuncNode : public LabelNode {
404
+ public:
405
+ ASMJIT_NONCOPYABLE(FuncNode)
406
+
407
+ //! Arguments pack.
408
+ struct ArgPack {
409
+ RegOnly _data[Globals::kMaxValuePack];
410
+
411
+ inline void reset() noexcept {
412
+ for (size_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++)
413
+ _data[valueIndex].reset();
414
+ }
415
+
416
+ inline RegOnly& operator[](size_t valueIndex) noexcept { return _data[valueIndex]; }
417
+ inline const RegOnly& operator[](size_t valueIndex) const noexcept { return _data[valueIndex]; }
418
+ };
419
+
420
+ //! \name Members
421
+ //! \{
422
+
423
+ //! Function detail.
424
+ FuncDetail _funcDetail;
425
+ //! Function frame.
426
+ FuncFrame _frame;
427
+ //! Function exit label.
428
+ LabelNode* _exitNode;
429
+ //! Function end (sentinel).
430
+ SentinelNode* _end;
431
+ //! Argument packs.
432
+ ArgPack* _args;
433
+
434
+ //! \}
435
+
436
+ //! \name Construction & Destruction
437
+ //! \{
438
+
439
+ //! Creates a new `FuncNode` instance.
440
+ //!
441
+ //! Always use `BaseCompiler::addFunc()` to create a new `FuncNode`.
442
+ inline FuncNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept
443
+ : LabelNode(cb),
444
+ _funcDetail(),
445
+ _frame(),
446
+ _exitNode(nullptr),
447
+ _end(nullptr),
448
+ _args(nullptr) {
449
+ setType(NodeType::kFunc);
450
+ }
451
+
452
+ //! \}
453
+
454
+ //! \{
455
+ //! \name Accessors
456
+
457
+ //! Returns function exit `LabelNode`.
458
+ inline LabelNode* exitNode() const noexcept { return _exitNode; }
459
+ //! Returns function exit label.
460
+ inline Label exitLabel() const noexcept { return _exitNode->label(); }
461
+
462
+ //! Returns "End of Func" sentinel node.
463
+ inline SentinelNode* endNode() const noexcept { return _end; }
464
+
465
+ //! Returns function detail.
466
+ inline FuncDetail& detail() noexcept { return _funcDetail; }
467
+ //! Returns function detail.
468
+ inline const FuncDetail& detail() const noexcept { return _funcDetail; }
469
+
470
+ //! Returns function frame.
471
+ inline FuncFrame& frame() noexcept { return _frame; }
472
+ //! Returns function frame.
473
+ inline const FuncFrame& frame() const noexcept { return _frame; }
474
+
475
+ //! Returns function attributes.
476
+ inline FuncAttributes attributes() const noexcept { return _frame.attributes(); }
477
+ //! Adds `attrs` to the function attributes.
478
+ inline void addAttributes(FuncAttributes attrs) noexcept { _frame.addAttributes(attrs); }
479
+
480
+ //! Returns arguments count.
481
+ inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); }
482
+ //! Returns argument packs.
483
+ inline ArgPack* argPacks() const noexcept { return _args; }
484
+
485
+ //! Tests whether the function has a return value.
486
+ inline bool hasRet() const noexcept { return _funcDetail.hasRet(); }
487
+
488
+ //! Returns argument pack at `argIndex`.
489
+ inline ArgPack& argPack(size_t argIndex) const noexcept {
490
+ ASMJIT_ASSERT(argIndex < argCount());
491
+ return _args[argIndex];
492
+ }
493
+
494
+ //! Sets argument at `argIndex`.
495
+ inline void setArg(size_t argIndex, const BaseReg& vReg) noexcept {
496
+ ASMJIT_ASSERT(argIndex < argCount());
497
+ _args[argIndex][0].init(vReg);
498
+ }
499
+
500
+ //! \overload
501
+ inline void setArg(size_t argIndex, const RegOnly& vReg) noexcept {
502
+ ASMJIT_ASSERT(argIndex < argCount());
503
+ _args[argIndex][0].init(vReg);
504
+ }
505
+
506
+ //! Sets argument at `argIndex` and `valueIndex`.
507
+ inline void setArg(size_t argIndex, size_t valueIndex, const BaseReg& vReg) noexcept {
508
+ ASMJIT_ASSERT(argIndex < argCount());
509
+ _args[argIndex][valueIndex].init(vReg);
510
+ }
511
+
512
+ //! \overload
513
+ inline void setArg(size_t argIndex, size_t valueIndex, const RegOnly& vReg) noexcept {
514
+ ASMJIT_ASSERT(argIndex < argCount());
515
+ _args[argIndex][valueIndex].init(vReg);
516
+ }
517
+
518
+ //! Resets argument pack at `argIndex`.
519
+ inline void resetArg(size_t argIndex) noexcept {
520
+ ASMJIT_ASSERT(argIndex < argCount());
521
+ _args[argIndex].reset();
522
+ }
523
+
524
+ //! Resets argument pack at `argIndex`.
525
+ inline void resetArg(size_t argIndex, size_t valueIndex) noexcept {
526
+ ASMJIT_ASSERT(argIndex < argCount());
527
+ _args[argIndex][valueIndex].reset();
528
+ }
529
+
530
+ //! \}
531
+ };
532
+
533
+ //! Function return, used by \ref BaseCompiler.
534
+ class FuncRetNode : public InstNode {
535
+ public:
536
+ ASMJIT_NONCOPYABLE(FuncRetNode)
537
+
538
+ //! \name Construction & Destruction
539
+ //! \{
540
+
541
+ //! Creates a new `FuncRetNode` instance.
542
+ inline FuncRetNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept : InstNode(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) {
543
+ _any._nodeType = NodeType::kFuncRet;
544
+ }
545
+
546
+ //! \}
547
+ };
548
+
549
+ //! Function invocation, used by \ref BaseCompiler.
550
+ class InvokeNode : public InstNode {
551
+ public:
552
+ ASMJIT_NONCOPYABLE(InvokeNode)
553
+
554
+ //! Operand pack provides multiple operands that can be associated with a single return value of function
555
+ //! argument. Sometims this is necessary to express an argument or return value that requires multiple
556
+ //! registers, for example 64-bit value in 32-bit mode or passing / returning homogeneous data structures.
557
+ struct OperandPack {
558
+ //! Operands.
559
+ Operand_ _data[Globals::kMaxValuePack];
560
+
561
+ //! Reset the pack by resetting all operands in the pack.
562
+ inline void reset() noexcept {
563
+ for (size_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++)
564
+ _data[valueIndex].reset();
565
+ }
566
+
567
+ //! Returns an operand at the given `valueIndex`.
568
+ inline Operand& operator[](size_t valueIndex) noexcept {
569
+ ASMJIT_ASSERT(valueIndex < Globals::kMaxValuePack);
570
+ return _data[valueIndex].as<Operand>();
571
+ }
572
+
573
+ //! Returns an operand at the given `valueIndex` (const).
574
+ const inline Operand& operator[](size_t valueIndex) const noexcept {
575
+ ASMJIT_ASSERT(valueIndex < Globals::kMaxValuePack);
576
+ return _data[valueIndex].as<Operand>();
577
+ }
578
+ };
579
+
580
+ //! \name Members
581
+ //! \{
582
+
583
+ //! Function detail.
584
+ FuncDetail _funcDetail;
585
+ //! Function return value(s).
586
+ OperandPack _rets;
587
+ //! Function arguments.
588
+ OperandPack* _args;
589
+
590
+ //! \}
591
+
592
+ //! \name Construction & Destruction
593
+ //! \{
594
+
595
+ //! Creates a new `InvokeNode` instance.
596
+ inline InvokeNode(BaseBuilder* ASMJIT_NONNULL(cb), InstId instId, InstOptions options) noexcept
597
+ : InstNode(cb, instId, options, kBaseOpCapacity),
598
+ _funcDetail(),
599
+ _args(nullptr) {
600
+ setType(NodeType::kInvoke);
601
+ _resetOps();
602
+ _rets.reset();
603
+ addFlags(NodeFlags::kIsRemovable);
604
+ }
605
+
606
+ //! \}
607
+
608
+ //! \name Accessors
609
+ //! \{
610
+
611
+ //! Sets the function signature.
612
+ inline Error init(const FuncSignature& signature, const Environment& environment) noexcept {
613
+ return _funcDetail.init(signature, environment);
614
+ }
615
+
616
+ //! Returns the function detail.
617
+ inline FuncDetail& detail() noexcept { return _funcDetail; }
618
+ //! Returns the function detail.
619
+ inline const FuncDetail& detail() const noexcept { return _funcDetail; }
620
+
621
+ //! Returns the target operand.
622
+ inline Operand& target() noexcept { return _opArray[0].as<Operand>(); }
623
+ //! \overload
624
+ inline const Operand& target() const noexcept { return _opArray[0].as<Operand>(); }
625
+
626
+ //! Returns the number of function return values.
627
+ inline bool hasRet() const noexcept { return _funcDetail.hasRet(); }
628
+ //! Returns the number of function arguments.
629
+ inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); }
630
+
631
+ //! Returns operand pack representing function return value(s).
632
+ inline OperandPack& retPack() noexcept { return _rets; }
633
+ //! Returns operand pack representing function return value(s).
634
+ inline const OperandPack& retPack() const noexcept { return _rets; }
635
+
636
+ //! Returns the return value at the given `valueIndex`.
637
+ inline Operand& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; }
638
+ //! \overload
639
+ inline const Operand& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; }
640
+
641
+ //! Returns operand pack representing function return value(s).
642
+ inline OperandPack& argPack(size_t argIndex) noexcept {
643
+ ASMJIT_ASSERT(argIndex < argCount());
644
+ return _args[argIndex];
645
+ }
646
+ //! \overload
647
+ inline const OperandPack& argPack(size_t argIndex) const noexcept {
648
+ ASMJIT_ASSERT(argIndex < argCount());
649
+ return _args[argIndex];
650
+ }
651
+
652
+ //! Returns a function argument at the given `argIndex`.
653
+ inline Operand& arg(size_t argIndex, size_t valueIndex) noexcept {
654
+ ASMJIT_ASSERT(argIndex < argCount());
655
+ return _args[argIndex][valueIndex];
656
+ }
657
+ //! \overload
658
+ inline const Operand& arg(size_t argIndex, size_t valueIndex) const noexcept {
659
+ ASMJIT_ASSERT(argIndex < argCount());
660
+ return _args[argIndex][valueIndex];
661
+ }
662
+
663
+ //! Sets the function return value at `i` to `op`.
664
+ inline void _setRet(size_t valueIndex, const Operand_& op) noexcept { _rets[valueIndex] = op; }
665
+ //! Sets the function argument at `i` to `op`.
666
+ inline void _setArg(size_t argIndex, size_t valueIndex, const Operand_& op) noexcept {
667
+ ASMJIT_ASSERT(argIndex < argCount());
668
+ _args[argIndex][valueIndex] = op;
669
+ }
670
+
671
+ //! Sets the function return value at `valueIndex` to `reg`.
672
+ inline void setRet(size_t valueIndex, const BaseReg& reg) noexcept { _setRet(valueIndex, reg); }
673
+
674
+ //! Sets the first function argument in a value-pack at `argIndex` to `reg`.
675
+ inline void setArg(size_t argIndex, const BaseReg& reg) noexcept { _setArg(argIndex, 0, reg); }
676
+ //! Sets the first function argument in a value-pack at `argIndex` to `imm`.
677
+ inline void setArg(size_t argIndex, const Imm& imm) noexcept { _setArg(argIndex, 0, imm); }
678
+
679
+ //! Sets the function argument at `argIndex` and `valueIndex` to `reg`.
680
+ inline void setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) noexcept { _setArg(argIndex, valueIndex, reg); }
681
+ //! Sets the function argument at `argIndex` and `valueIndex` to `imm`.
682
+ inline void setArg(size_t argIndex, size_t valueIndex, const Imm& imm) noexcept { _setArg(argIndex, valueIndex, imm); }
683
+
684
+ //! \}
685
+ };
686
+
687
+ //! Function pass extends \ref Pass with \ref FuncPass::runOnFunction().
688
+ class ASMJIT_VIRTAPI FuncPass : public Pass {
689
+ public:
690
+ ASMJIT_NONCOPYABLE(FuncPass)
691
+ typedef Pass Base;
692
+
693
+ //! \name Construction & Destruction
694
+ //! \{
695
+
696
+ ASMJIT_API FuncPass(const char* name) noexcept;
697
+
698
+ //! \}
699
+
700
+ //! \name Accessors
701
+ //! \{
702
+
703
+ //! Returns the associated `BaseCompiler`.
704
+ inline BaseCompiler* cc() const noexcept { return static_cast<BaseCompiler*>(_cb); }
705
+
706
+ //! \}
707
+
708
+ //! \name Pass Interface
709
+ //! \{
710
+
711
+ //! Calls `runOnFunction()` on each `FuncNode` node found.
712
+ ASMJIT_API Error run(Zone* zone, Logger* logger) override;
713
+
714
+ //! Called once per `FuncNode`.
715
+ virtual Error runOnFunction(Zone* zone, Logger* logger, FuncNode* func) = 0;
716
+
717
+ //! \}
718
+ };
719
+
720
+ #if !defined(ASMJIT_NO_DEPRECATED)
721
+ inline Error BaseCompiler::_setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) {
722
+ FuncNode* func = _func;
723
+
724
+ if (ASMJIT_UNLIKELY(!func))
725
+ return reportError(DebugUtils::errored(kErrorInvalidState));
726
+
727
+ func->setArg(argIndex, valueIndex, reg);
728
+ return kErrorOk;
729
+ }
730
+ #endif
731
+
732
+ //! \}
733
+
734
+ ASMJIT_END_NAMESPACE
735
+
736
+ #endif // !ASMJIT_NO_COMPILER
737
+ #endif // ASMJIT_CORE_COMPILER_H_INCLUDED