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,1391 @@
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_BUILDER_H_INCLUDED
7
+ #define ASMJIT_CORE_BUILDER_H_INCLUDED
8
+
9
+ #include "../core/api-config.h"
10
+ #ifndef ASMJIT_NO_BUILDER
11
+
12
+ #include "../core/assembler.h"
13
+ #include "../core/codeholder.h"
14
+ #include "../core/constpool.h"
15
+ #include "../core/formatter.h"
16
+ #include "../core/inst.h"
17
+ #include "../core/operand.h"
18
+ #include "../core/string.h"
19
+ #include "../core/support.h"
20
+ #include "../core/type.h"
21
+ #include "../core/zone.h"
22
+ #include "../core/zonevector.h"
23
+
24
+ ASMJIT_BEGIN_NAMESPACE
25
+
26
+ //! \addtogroup asmjit_builder
27
+ //! \{
28
+
29
+ class BaseBuilder;
30
+ class Pass;
31
+
32
+ class BaseNode;
33
+ class InstNode;
34
+ class SectionNode;
35
+ class LabelNode;
36
+ class AlignNode;
37
+ class EmbedDataNode;
38
+ class EmbedLabelNode;
39
+ class ConstPoolNode;
40
+ class CommentNode;
41
+ class SentinelNode;
42
+ class LabelDeltaNode;
43
+
44
+ //! Type of node used by \ref BaseBuilder and \ref BaseCompiler.
45
+ enum class NodeType : uint8_t {
46
+ //! Invalid node (internal, don't use).
47
+ kNone = 0,
48
+
49
+ // [BaseBuilder]
50
+
51
+ //! Node is \ref InstNode or \ref InstExNode.
52
+ kInst = 1,
53
+ //! Node is \ref SectionNode.
54
+ kSection = 2,
55
+ //! Node is \ref LabelNode.
56
+ kLabel = 3,
57
+ //! Node is \ref AlignNode.
58
+ kAlign = 4,
59
+ //! Node is \ref EmbedDataNode.
60
+ kEmbedData = 5,
61
+ //! Node is \ref EmbedLabelNode.
62
+ kEmbedLabel = 6,
63
+ //! Node is \ref EmbedLabelDeltaNode.
64
+ kEmbedLabelDelta = 7,
65
+ //! Node is \ref ConstPoolNode.
66
+ kConstPool = 8,
67
+ //! Node is \ref CommentNode.
68
+ kComment = 9,
69
+ //! Node is \ref SentinelNode.
70
+ kSentinel = 10,
71
+
72
+ // [BaseCompiler]
73
+
74
+ //! Node is \ref JumpNode (acts as InstNode).
75
+ kJump = 15,
76
+ //! Node is \ref FuncNode (acts as LabelNode).
77
+ kFunc = 16,
78
+ //! Node is \ref FuncRetNode (acts as InstNode).
79
+ kFuncRet = 17,
80
+ //! Node is \ref InvokeNode (acts as InstNode).
81
+ kInvoke = 18,
82
+
83
+ // [UserDefined]
84
+
85
+ //! First id of a user-defined node.
86
+ kUser = 32
87
+ };
88
+
89
+ //! Node flags, specify what the node is and/or does.
90
+ enum class NodeFlags : uint8_t {
91
+ //! No flags.
92
+ kNone = 0,
93
+ //! Node is code that can be executed (instruction, label, align, etc...).
94
+ kIsCode = 0x01u,
95
+ //! Node is data that cannot be executed (data, const-pool, etc...).
96
+ kIsData = 0x02u,
97
+ //! Node is informative, can be removed and ignored.
98
+ kIsInformative = 0x04u,
99
+ //! Node can be safely removed if unreachable.
100
+ kIsRemovable = 0x08u,
101
+ //! Node does nothing when executed (label, align, explicit nop).
102
+ kHasNoEffect = 0x10u,
103
+ //! Node is an instruction or acts as it.
104
+ kActsAsInst = 0x20u,
105
+ //! Node is a label or acts as it.
106
+ kActsAsLabel = 0x40u,
107
+ //! Node is active (part of the code).
108
+ kIsActive = 0x80u
109
+ };
110
+ ASMJIT_DEFINE_ENUM_FLAGS(NodeFlags)
111
+
112
+ //! Type of the sentinel (purery informative purpose).
113
+ enum class SentinelType : uint8_t {
114
+ //! Type of the sentinel is not known.
115
+ kUnknown = 0u,
116
+ //! This is a sentinel used at the end of \ref FuncNode.
117
+ kFuncEnd = 1u
118
+ };
119
+
120
+ //! Builder interface.
121
+ //!
122
+ //! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler replacement in case pre-processing or
123
+ //! post-processing of the generated code is required. The code can be modified during or after code generation.
124
+ //! Pre processing or post processing can be done manually or through a \ref Pass object. \ref BaseBuilder stores
125
+ //! the emitted code as a double-linked list of nodes, which allows O(1) insertion and removal during processing.
126
+ //!
127
+ //! Check out architecture specific builders for more details and examples:
128
+ //!
129
+ //! - \ref x86::Builder - X86/X64 builder implementation.
130
+ class ASMJIT_VIRTAPI BaseBuilder : public BaseEmitter {
131
+ public:
132
+ ASMJIT_NONCOPYABLE(BaseBuilder)
133
+ typedef BaseEmitter Base;
134
+
135
+ //! \name Members
136
+ //! \{
137
+
138
+ //! Base zone used to allocate nodes and passes.
139
+ Zone _codeZone;
140
+ //! Data zone used to allocate data and names.
141
+ Zone _dataZone;
142
+ //! Pass zone, passed to `Pass::run()`.
143
+ Zone _passZone;
144
+ //! Allocator that uses `_codeZone`.
145
+ ZoneAllocator _allocator;
146
+
147
+ //! Array of `Pass` objects.
148
+ ZoneVector<Pass*> _passes {};
149
+ //! Maps section indexes to `LabelNode` nodes.
150
+ ZoneVector<SectionNode*> _sectionNodes {};
151
+ //! Maps label indexes to `LabelNode` nodes.
152
+ ZoneVector<LabelNode*> _labelNodes {};
153
+
154
+ //! Current node (cursor).
155
+ BaseNode* _cursor = nullptr;
156
+ //! First node of the current section.
157
+ BaseNode* _firstNode = nullptr;
158
+ //! Last node of the current section.
159
+ BaseNode* _lastNode = nullptr;
160
+
161
+ //! Flags assigned to each new node.
162
+ NodeFlags _nodeFlags = NodeFlags::kNone;
163
+ //! The sections links are dirty (used internally).
164
+ bool _dirtySectionLinks = false;
165
+
166
+ //! \}
167
+
168
+ //! \name Construction & Destruction
169
+ //! \{
170
+
171
+ //! Creates a new `BaseBuilder` instance.
172
+ ASMJIT_API BaseBuilder() noexcept;
173
+ //! Destroys the `BaseBuilder` instance.
174
+ ASMJIT_API virtual ~BaseBuilder() noexcept;
175
+
176
+ //! \}
177
+
178
+ //! \name Node Management
179
+ //! \{
180
+
181
+ //! Returns the first node.
182
+ inline BaseNode* firstNode() const noexcept { return _firstNode; }
183
+ //! Returns the last node.
184
+ inline BaseNode* lastNode() const noexcept { return _lastNode; }
185
+
186
+ //! Allocates and instantiates a new node of type `T` and returns its instance. If the allocation fails `nullptr`
187
+ //! is returned.
188
+ //!
189
+ //! The template argument `T` must be a type that is extends \ref BaseNode.
190
+ //!
191
+ //! \remarks The pointer returned (if non-null) is owned by the Builder or Compiler. When the Builder/Compiler
192
+ //! is destroyed it destroys all nodes it created so no manual memory management is required.
193
+ template<typename T, typename... Args>
194
+ inline Error _newNodeT(T** ASMJIT_NONNULL(out), Args&&... args) {
195
+ *out = _allocator.newT<T>(this, std::forward<Args>(args)...);
196
+ if (ASMJIT_UNLIKELY(!*out))
197
+ return reportError(DebugUtils::errored(kErrorOutOfMemory));
198
+ return kErrorOk;
199
+ }
200
+
201
+ //! Creates a new \ref InstNode.
202
+ ASMJIT_API Error newInstNode(InstNode** ASMJIT_NONNULL(out), InstId instId, InstOptions instOptions, uint32_t opCount);
203
+ //! Creates a new \ref LabelNode.
204
+ ASMJIT_API Error newLabelNode(LabelNode** ASMJIT_NONNULL(out));
205
+ //! Creates a new \ref AlignNode.
206
+ ASMJIT_API Error newAlignNode(AlignNode** ASMJIT_NONNULL(out), AlignMode alignMode, uint32_t alignment);
207
+ //! Creates a new \ref EmbedDataNode.
208
+ ASMJIT_API Error newEmbedDataNode(EmbedDataNode** ASMJIT_NONNULL(out), TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1);
209
+ //! Creates a new \ref ConstPoolNode.
210
+ ASMJIT_API Error newConstPoolNode(ConstPoolNode** ASMJIT_NONNULL(out));
211
+ //! Creates a new \ref CommentNode.
212
+ ASMJIT_API Error newCommentNode(CommentNode** ASMJIT_NONNULL(out), const char* data, size_t size);
213
+
214
+ //! Adds `node` after the current and sets the current node to the given `node`.
215
+ ASMJIT_API BaseNode* addNode(BaseNode* ASMJIT_NONNULL(node)) noexcept;
216
+ //! Inserts the given `node` after `ref`.
217
+ ASMJIT_API BaseNode* addAfter(BaseNode* ASMJIT_NONNULL(node), BaseNode* ASMJIT_NONNULL(ref)) noexcept;
218
+ //! Inserts the given `node` before `ref`.
219
+ ASMJIT_API BaseNode* addBefore(BaseNode* ASMJIT_NONNULL(node), BaseNode* ASMJIT_NONNULL(ref)) noexcept;
220
+ //! Removes the given `node`.
221
+ ASMJIT_API BaseNode* removeNode(BaseNode* ASMJIT_NONNULL(node)) noexcept;
222
+ //! Removes multiple nodes.
223
+ ASMJIT_API void removeNodes(BaseNode* first, BaseNode* last) noexcept;
224
+
225
+ //! Returns the cursor.
226
+ //!
227
+ //! When the Builder/Compiler is created it automatically creates a '.text' \ref SectionNode, which will be the
228
+ //! initial one. When instructions are added they are always added after the cursor and the cursor is changed
229
+ //! to be that newly added node. Use `setCursor()` to change where new nodes are inserted.
230
+ inline BaseNode* cursor() const noexcept { return _cursor; }
231
+
232
+ //! Sets the current node to `node` and return the previous one.
233
+ ASMJIT_API BaseNode* setCursor(BaseNode* node) noexcept;
234
+
235
+ //! Sets the current node without returning the previous node.
236
+ //!
237
+ //! Only use this function if you are concerned about performance and want this inlined (for example if you set
238
+ //! the cursor in a loop, etc...).
239
+ inline void _setCursor(BaseNode* node) noexcept { _cursor = node; }
240
+
241
+ //! \}
242
+
243
+ //! \name Section Management
244
+ //! \{
245
+
246
+ //! Returns a vector of SectionNode objects.
247
+ //!
248
+ //! \note If a section of some id is not associated with the Builder/Compiler it would be null, so always check
249
+ //! for nulls if you iterate over the vector.
250
+ inline const ZoneVector<SectionNode*>& sectionNodes() const noexcept {
251
+ return _sectionNodes;
252
+ }
253
+
254
+ //! Tests whether the `SectionNode` of the given `sectionId` was registered.
255
+ inline bool hasRegisteredSectionNode(uint32_t sectionId) const noexcept {
256
+ return sectionId < _sectionNodes.size() && _sectionNodes[sectionId] != nullptr;
257
+ }
258
+
259
+ //! Returns or creates a `SectionNode` that matches the given `sectionId`.
260
+ //!
261
+ //! \remarks This function will either get the existing `SectionNode` or create it in case it wasn't created before.
262
+ //! You can check whether a section has a registered `SectionNode` by using `BaseBuilder::hasRegisteredSectionNode()`.
263
+ ASMJIT_API Error sectionNodeOf(SectionNode** ASMJIT_NONNULL(out), uint32_t sectionId);
264
+
265
+ ASMJIT_API Error section(Section* ASMJIT_NONNULL(section)) override;
266
+
267
+ //! Returns whether the section links of active section nodes are dirty. You can update these links by calling
268
+ //! `updateSectionLinks()` in such case.
269
+ inline bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; }
270
+
271
+ //! Updates links of all active section nodes.
272
+ ASMJIT_API void updateSectionLinks() noexcept;
273
+
274
+ //! \}
275
+
276
+ //! \name Label Management
277
+ //! \{
278
+
279
+ //! Returns a vector of \ref LabelNode nodes.
280
+ //!
281
+ //! \note If a label of some id is not associated with the Builder/Compiler it would be null, so always check for
282
+ //! nulls if you iterate over the vector.
283
+ inline const ZoneVector<LabelNode*>& labelNodes() const noexcept { return _labelNodes; }
284
+
285
+ //! Tests whether the `LabelNode` of the given `labelId` was registered.
286
+ inline bool hasRegisteredLabelNode(uint32_t labelId) const noexcept {
287
+ return labelId < _labelNodes.size() && _labelNodes[labelId] != nullptr;
288
+ }
289
+
290
+ //! \overload
291
+ inline bool hasRegisteredLabelNode(const Label& label) const noexcept {
292
+ return hasRegisteredLabelNode(label.id());
293
+ }
294
+
295
+ //! Gets or creates a \ref LabelNode that matches the given `labelId`.
296
+ //!
297
+ //! \remarks This function will either get the existing `LabelNode` or create it in case it wasn't created before.
298
+ //! You can check whether a label has a registered `LabelNode` by calling \ref BaseBuilder::hasRegisteredLabelNode().
299
+ ASMJIT_API Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), uint32_t labelId);
300
+
301
+ //! \overload
302
+ inline Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), const Label& label) {
303
+ return labelNodeOf(out, label.id());
304
+ }
305
+
306
+ //! Registers this \ref LabelNode (internal).
307
+ //!
308
+ //! This function is used internally to register a newly created `LabelNode` with this instance of Builder/Compiler.
309
+ //! Use \ref labelNodeOf() functions to get back \ref LabelNode from a label or its identifier.
310
+ ASMJIT_API Error registerLabelNode(LabelNode* ASMJIT_NONNULL(node));
311
+
312
+ ASMJIT_API Label newLabel() override;
313
+ ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) override;
314
+ ASMJIT_API Error bind(const Label& label) override;
315
+
316
+ //! \}
317
+
318
+ //! \name Passes
319
+ //! \{
320
+
321
+ //! Returns a vector of `Pass` instances that will be executed by `runPasses()`.
322
+ inline const ZoneVector<Pass*>& passes() const noexcept { return _passes; }
323
+
324
+ //! Allocates and instantiates a new pass of type `T` and returns its instance. If the allocation fails `nullptr` is
325
+ //! returned.
326
+ //!
327
+ //! The template argument `T` must be a type that is extends \ref Pass.
328
+ //!
329
+ //! \remarks The pointer returned (if non-null) is owned by the Builder or Compiler. When the Builder/Compiler is
330
+ //! destroyed it destroys all passes it created so no manual memory management is required.
331
+ template<typename T>
332
+ inline T* newPassT() noexcept { return _codeZone.newT<T>(); }
333
+
334
+ //! \overload
335
+ template<typename T, typename... Args>
336
+ inline T* newPassT(Args&&... args) noexcept { return _codeZone.newT<T>(std::forward<Args>(args)...); }
337
+
338
+ template<typename T>
339
+ inline Error addPassT() { return addPass(newPassT<T>()); }
340
+
341
+ template<typename T, typename... Args>
342
+ inline Error addPassT(Args&&... args) { return addPass(newPassT<T, Args...>(std::forward<Args>(args)...)); }
343
+
344
+ //! Returns `Pass` by name.
345
+ //!
346
+ //! If the pass having the given `name` doesn't exist `nullptr` is returned.
347
+ ASMJIT_API Pass* passByName(const char* name) const noexcept;
348
+ //! Adds `pass` to the list of passes.
349
+ ASMJIT_API Error addPass(Pass* pass) noexcept;
350
+ //! Removes `pass` from the list of passes and delete it.
351
+ ASMJIT_API Error deletePass(Pass* pass) noexcept;
352
+
353
+ //! Runs all passes in order.
354
+ ASMJIT_API Error runPasses();
355
+
356
+ //! \}
357
+
358
+ //! \name Emit
359
+ //! \{
360
+
361
+ ASMJIT_API Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override;
362
+
363
+ //! \}
364
+
365
+ //! \name Align
366
+ //! \{
367
+
368
+ ASMJIT_API Error align(AlignMode alignMode, uint32_t alignment) override;
369
+
370
+ //! \}
371
+
372
+ //! \name Embed
373
+ //! \{
374
+
375
+ ASMJIT_API Error embed(const void* data, size_t dataSize) override;
376
+ ASMJIT_API Error embedDataArray(TypeId typeId, const void* data, size_t count, size_t repeat = 1) override;
377
+ ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override;
378
+
379
+ ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override;
380
+ ASMJIT_API Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) override;
381
+
382
+ //! \}
383
+
384
+ //! \name Comment
385
+ //! \{
386
+
387
+ ASMJIT_API Error comment(const char* data, size_t size = SIZE_MAX) override;
388
+
389
+ //! \}
390
+
391
+ //! \name Serialization
392
+ //! \{
393
+
394
+ //! Serializes everything the given emitter `dst`.
395
+ //!
396
+ //! Although not explicitly required the emitter will most probably be of Assembler type. The reason is that
397
+ //! there is no known use of serializing nodes held by Builder/Compiler into another Builder-like emitter.
398
+ ASMJIT_API Error serializeTo(BaseEmitter* dst);
399
+
400
+ //! \}
401
+
402
+ //! \name Events
403
+ //! \{
404
+
405
+ ASMJIT_API Error onAttach(CodeHolder* code) noexcept override;
406
+ ASMJIT_API Error onDetach(CodeHolder* code) noexcept override;
407
+
408
+ //! \}
409
+ };
410
+
411
+ //! Base node.
412
+ //!
413
+ //! Every node represents a building-block used by \ref BaseBuilder. It can be instruction, data, label, comment,
414
+ //! directive, or any other high-level representation that can be transformed to the building blocks mentioned.
415
+ //! Every class that inherits \ref BaseBuilder can define its own high-level nodes that can be later lowered to
416
+ //! basic nodes like instructions.
417
+ class BaseNode {
418
+ public:
419
+ ASMJIT_NONCOPYABLE(BaseNode)
420
+
421
+ //! \name Members
422
+ //! \{
423
+
424
+ union {
425
+ struct {
426
+ //! Previous node.
427
+ BaseNode* _prev;
428
+ //! Next node.
429
+ BaseNode* _next;
430
+ };
431
+ //! Links (an alternative view to previous and next nodes).
432
+ BaseNode* _links[2];
433
+ };
434
+
435
+ //! Data shared between all types of nodes.
436
+ struct AnyData {
437
+ //! Node type.
438
+ NodeType _nodeType;
439
+ //! Node flags.
440
+ NodeFlags _nodeFlags;
441
+ //! Not used by BaseNode.
442
+ uint8_t _reserved0;
443
+ //! Not used by BaseNode.
444
+ uint8_t _reserved1;
445
+ };
446
+
447
+ //! Data used by \ref AlignNode.
448
+ struct AlignData {
449
+ //! Node type.
450
+ NodeType _nodeType;
451
+ //! Node flags.
452
+ NodeFlags _nodeFlags;
453
+ //! Align mode.
454
+ AlignMode _alignMode;
455
+ //! Not used by AlignNode.
456
+ uint8_t _reserved;
457
+ };
458
+
459
+ //! Data used by \ref InstNode.
460
+ struct InstData {
461
+ //! Node type.
462
+ NodeType _nodeType;
463
+ //! Node flags.
464
+ NodeFlags _nodeFlags;
465
+ //! Instruction operands count (used).
466
+ uint8_t _opCount;
467
+ //! Instruction operands capacity (allocated).
468
+ uint8_t _opCapacity;
469
+ };
470
+
471
+ //! Data used by \ref EmbedDataNode.
472
+ struct EmbedData {
473
+ //! Node type.
474
+ NodeType _nodeType;
475
+ //! Node flags.
476
+ NodeFlags _nodeFlags;
477
+ //! Type id.
478
+ TypeId _typeId;
479
+ //! Size of `_typeId`.
480
+ uint8_t _typeSize;
481
+ };
482
+
483
+ //! Data used by \ref SentinelNode.
484
+ struct SentinelData {
485
+ //! Node type.
486
+ NodeType _nodeType;
487
+ //! Node flags.
488
+ NodeFlags _nodeFlags;
489
+ //! Sentinel type.
490
+ SentinelType _sentinelType;
491
+ //! Not used by BaseNode.
492
+ uint8_t _reserved1;
493
+ };
494
+
495
+ //! Data that can have different meaning dependning on \ref NodeType.
496
+ union {
497
+ //! Data useful by any node type.
498
+ AnyData _any;
499
+ //! Data specific to \ref AlignNode.
500
+ AlignData _alignData;
501
+ //! Data specific to \ref InstNode.
502
+ InstData _inst;
503
+ //! Data specific to \ref EmbedDataNode.
504
+ EmbedData _embed;
505
+ //! Data specific to \ref SentinelNode.
506
+ SentinelData _sentinel;
507
+ };
508
+
509
+ //! Node position in code (should be unique).
510
+ uint32_t _position;
511
+
512
+ //! Value reserved for AsmJit users never touched by AsmJit itself.
513
+ union {
514
+ //! User data as 64-bit integer.
515
+ uint64_t _userDataU64;
516
+ //! User data as pointer.
517
+ void* _userDataPtr;
518
+ };
519
+
520
+ //! Data used exclusively by the current `Pass`.
521
+ void* _passData;
522
+
523
+ //! Inline comment/annotation or nullptr if not used.
524
+ const char* _inlineComment;
525
+
526
+ //! \}
527
+
528
+ //! \name Construction & Destruction
529
+ //! \{
530
+
531
+ //! Creates a new `BaseNode` - always use `BaseBuilder` to allocate nodes.
532
+ inline BaseNode(BaseBuilder* cb, NodeType nodeType, NodeFlags nodeFlags = NodeFlags::kNone) noexcept {
533
+ _prev = nullptr;
534
+ _next = nullptr;
535
+ _any._nodeType = nodeType;
536
+ _any._nodeFlags = nodeFlags | cb->_nodeFlags;
537
+ _any._reserved0 = 0;
538
+ _any._reserved1 = 0;
539
+ _position = 0;
540
+ _userDataU64 = 0;
541
+ _passData = nullptr;
542
+ _inlineComment = nullptr;
543
+ }
544
+
545
+ //! \}
546
+
547
+ //! \name Accessors
548
+ //! \{
549
+
550
+ //! Casts this node to `T*`.
551
+ template<typename T>
552
+ inline T* as() noexcept { return static_cast<T*>(this); }
553
+ //! Casts this node to `const T*`.
554
+ template<typename T>
555
+ inline const T* as() const noexcept { return static_cast<const T*>(this); }
556
+
557
+ //! Returns previous node or `nullptr` if this node is either first or not
558
+ //! part of Builder/Compiler node-list.
559
+ inline BaseNode* prev() const noexcept { return _prev; }
560
+ //! Returns next node or `nullptr` if this node is either last or not part
561
+ //! of Builder/Compiler node-list.
562
+ inline BaseNode* next() const noexcept { return _next; }
563
+
564
+ //! Returns the type of the node, see `NodeType`.
565
+ inline NodeType type() const noexcept { return _any._nodeType; }
566
+
567
+ //! Sets the type of the node, see `NodeType` (internal).
568
+ //!
569
+ //! \remarks You should never set a type of a node to anything else than the initial value. This function is only
570
+ //! provided for users that use custom nodes and need to change the type either during construction or later.
571
+ inline void setType(NodeType type) noexcept { _any._nodeType = type; }
572
+
573
+ //! Tests whether this node is either `InstNode` or extends it.
574
+ inline bool isInst() const noexcept { return hasFlag(NodeFlags::kActsAsInst); }
575
+ //! Tests whether this node is `SectionNode`.
576
+ inline bool isSection() const noexcept { return type() == NodeType::kSection; }
577
+ //! Tests whether this node is either `LabelNode` or extends it.
578
+ inline bool isLabel() const noexcept { return hasFlag(NodeFlags::kActsAsLabel); }
579
+ //! Tests whether this node is `AlignNode`.
580
+ inline bool isAlign() const noexcept { return type() == NodeType::kAlign; }
581
+ //! Tests whether this node is `EmbedDataNode`.
582
+ inline bool isEmbedData() const noexcept { return type() == NodeType::kEmbedData; }
583
+ //! Tests whether this node is `EmbedLabelNode`.
584
+ inline bool isEmbedLabel() const noexcept { return type() == NodeType::kEmbedLabel; }
585
+ //! Tests whether this node is `EmbedLabelDeltaNode`.
586
+ inline bool isEmbedLabelDelta() const noexcept { return type() == NodeType::kEmbedLabelDelta; }
587
+ //! Tests whether this node is `ConstPoolNode`.
588
+ inline bool isConstPool() const noexcept { return type() == NodeType::kConstPool; }
589
+ //! Tests whether this node is `CommentNode`.
590
+ inline bool isComment() const noexcept { return type() == NodeType::kComment; }
591
+ //! Tests whether this node is `SentinelNode`.
592
+ inline bool isSentinel() const noexcept { return type() == NodeType::kSentinel; }
593
+
594
+ //! Tests whether this node is `FuncNode`.
595
+ inline bool isFunc() const noexcept { return type() == NodeType::kFunc; }
596
+ //! Tests whether this node is `FuncRetNode`.
597
+ inline bool isFuncRet() const noexcept { return type() == NodeType::kFuncRet; }
598
+ //! Tests whether this node is `InvokeNode`.
599
+ inline bool isInvoke() const noexcept { return type() == NodeType::kInvoke; }
600
+
601
+ //! Returns the node flags.
602
+ inline NodeFlags flags() const noexcept { return _any._nodeFlags; }
603
+ //! Tests whether the node has the given `flag` set.
604
+ inline bool hasFlag(NodeFlags flag) const noexcept { return Support::test(_any._nodeFlags, flag); }
605
+ //! Replaces node flags with `flags`.
606
+ inline void setFlags(NodeFlags flags) noexcept { _any._nodeFlags = flags; }
607
+ //! Adds the given `flags` to node flags.
608
+ inline void addFlags(NodeFlags flags) noexcept { _any._nodeFlags |= flags; }
609
+ //! Clears the given `flags` from node flags.
610
+ inline void clearFlags(NodeFlags flags) noexcept { _any._nodeFlags &= ~flags; }
611
+
612
+ //! Tests whether the node is code that can be executed.
613
+ inline bool isCode() const noexcept { return hasFlag(NodeFlags::kIsCode); }
614
+ //! Tests whether the node is data that cannot be executed.
615
+ inline bool isData() const noexcept { return hasFlag(NodeFlags::kIsData); }
616
+ //! Tests whether the node is informative only (is never encoded like comment, etc...).
617
+ inline bool isInformative() const noexcept { return hasFlag(NodeFlags::kIsInformative); }
618
+ //! Tests whether the node is removable if it's in an unreachable code block.
619
+ inline bool isRemovable() const noexcept { return hasFlag(NodeFlags::kIsRemovable); }
620
+ //! Tests whether the node has no effect when executed (label, .align, nop, ...).
621
+ inline bool hasNoEffect() const noexcept { return hasFlag(NodeFlags::kHasNoEffect); }
622
+ //! Tests whether the node is part of the code.
623
+ inline bool isActive() const noexcept { return hasFlag(NodeFlags::kIsActive); }
624
+
625
+ //! Tests whether the node has a position assigned.
626
+ //!
627
+ //! \remarks Returns `true` if node position is non-zero.
628
+ inline bool hasPosition() const noexcept { return _position != 0; }
629
+ //! Returns node position.
630
+ inline uint32_t position() const noexcept { return _position; }
631
+ //! Sets node position.
632
+ //!
633
+ //! Node position is a 32-bit unsigned integer that is used by Compiler to track where the node is relatively to
634
+ //! the start of the function. It doesn't describe a byte position in a binary, instead it's just a pseudo position
635
+ //! used by liveness analysis and other tools around Compiler.
636
+ //!
637
+ //! If you don't use Compiler then you may use `position()` and `setPosition()` freely for your own purposes if
638
+ //! the 32-bit value limit is okay for you.
639
+ inline void setPosition(uint32_t position) noexcept { _position = position; }
640
+
641
+ //! Returns user data casted to `T*`.
642
+ //!
643
+ //! User data is decicated to be used only by AsmJit users and not touched by the library. The data has a pointer
644
+ //! size so you can either store a pointer or `intptr_t` value through `setUserDataAsIntPtr()`.
645
+ template<typename T>
646
+ inline T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); }
647
+ //! Returns user data casted to `int64_t`.
648
+ inline int64_t userDataAsInt64() const noexcept { return int64_t(_userDataU64); }
649
+ //! Returns user data casted to `uint64_t`.
650
+ inline uint64_t userDataAsUInt64() const noexcept { return _userDataU64; }
651
+
652
+ //! Sets user data to `data`.
653
+ template<typename T>
654
+ inline void setUserDataAsPtr(T* data) noexcept { _userDataPtr = static_cast<void*>(data); }
655
+ //! Sets used data to the given 64-bit signed `value`.
656
+ inline void setUserDataAsInt64(int64_t value) noexcept { _userDataU64 = uint64_t(value); }
657
+ //! Sets used data to the given 64-bit unsigned `value`.
658
+ inline void setUserDataAsUInt64(uint64_t value) noexcept { _userDataU64 = value; }
659
+
660
+ //! Resets user data to zero / nullptr.
661
+ inline void resetUserData() noexcept { _userDataU64 = 0; }
662
+
663
+ //! Tests whether the node has an associated pass data.
664
+ inline bool hasPassData() const noexcept { return _passData != nullptr; }
665
+ //! Returns the node pass data - data used during processing & transformations.
666
+ template<typename T>
667
+ inline T* passData() const noexcept { return (T*)_passData; }
668
+ //! Sets the node pass data to `data`.
669
+ template<typename T>
670
+ inline void setPassData(T* data) noexcept { _passData = (void*)data; }
671
+ //! Resets the node pass data to nullptr.
672
+ inline void resetPassData() noexcept { _passData = nullptr; }
673
+
674
+ //! Tests whether the node has an inline comment/annotation.
675
+ inline bool hasInlineComment() const noexcept { return _inlineComment != nullptr; }
676
+ //! Returns an inline comment/annotation string.
677
+ inline const char* inlineComment() const noexcept { return _inlineComment; }
678
+ //! Sets an inline comment/annotation string to `s`.
679
+ inline void setInlineComment(const char* s) noexcept { _inlineComment = s; }
680
+ //! Resets an inline comment/annotation string to nullptr.
681
+ inline void resetInlineComment() noexcept { _inlineComment = nullptr; }
682
+
683
+ //! \}
684
+ };
685
+
686
+ //! Instruction node.
687
+ //!
688
+ //! Wraps an instruction with its options and operands.
689
+ class InstNode : public BaseNode {
690
+ public:
691
+ ASMJIT_NONCOPYABLE(InstNode)
692
+
693
+ //! \name Constants
694
+ //! \{
695
+
696
+ enum : uint32_t {
697
+ //! Count of embedded operands per `InstNode` that are always allocated as a part of the instruction. Minimum
698
+ //! embedded operands is 4, but in 32-bit more pointers are smaller and we can embed 5. The rest (up to 6 operands)
699
+ //! is always stored in `InstExNode`.
700
+ kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_))
701
+ };
702
+
703
+ //! \}
704
+
705
+ //! \name Members
706
+ //! \{
707
+
708
+ //! Base instruction data.
709
+ BaseInst _baseInst;
710
+ //! First 4 or 5 operands (indexed from 0).
711
+ Operand_ _opArray[kBaseOpCapacity];
712
+
713
+ //! \}
714
+
715
+ //! \name Construction & Destruction
716
+ //! \{
717
+
718
+ //! Creates a new `InstNode` instance.
719
+ inline InstNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept
720
+ : BaseNode(cb, NodeType::kInst, NodeFlags::kIsCode | NodeFlags::kIsRemovable | NodeFlags::kActsAsInst),
721
+ _baseInst(instId, options) {
722
+ _inst._opCapacity = uint8_t(opCapacity);
723
+ _inst._opCount = uint8_t(opCount);
724
+ }
725
+
726
+ //! \cond INTERNAL
727
+ //! Reset all built-in operands, including `extraReg`.
728
+ inline void _resetOps() noexcept {
729
+ _baseInst.resetExtraReg();
730
+ resetOpRange(0, opCapacity());
731
+ }
732
+ //! \endcond
733
+
734
+ //! \}
735
+
736
+ //! \name Instruction Object
737
+ //! \{
738
+
739
+ inline BaseInst& baseInst() noexcept { return _baseInst; }
740
+ inline const BaseInst& baseInst() const noexcept { return _baseInst; }
741
+
742
+ //! \}
743
+
744
+ //! \name Instruction Id
745
+ //! \{
746
+
747
+ //! Returns the instruction id, see `BaseInst::Id`.
748
+ inline InstId id() const noexcept { return _baseInst.id(); }
749
+ //! Returns the instruction real id, see `BaseInst::Id`.
750
+ inline InstId realId() const noexcept { return _baseInst.realId(); }
751
+
752
+ //! Sets the instruction id to `id`, see `BaseInst::Id`.
753
+ inline void setId(InstId id) noexcept { _baseInst.setId(id); }
754
+
755
+ //! \}
756
+
757
+ //! \name Instruction Options
758
+ //! \{
759
+
760
+ inline InstOptions options() const noexcept { return _baseInst.options(); }
761
+ inline bool hasOption(InstOptions option) const noexcept { return _baseInst.hasOption(option); }
762
+ inline void setOptions(InstOptions options) noexcept { _baseInst.setOptions(options); }
763
+ inline void addOptions(InstOptions options) noexcept { _baseInst.addOptions(options); }
764
+ inline void clearOptions(InstOptions options) noexcept { _baseInst.clearOptions(options); }
765
+ inline void resetOptions() noexcept { _baseInst.resetOptions(); }
766
+
767
+ //! \}
768
+
769
+ //! \name Extra Register
770
+ //! \{
771
+
772
+ //! Tests whether the node has an extra register operand.
773
+ inline bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); }
774
+ //! Returns extra register operand.
775
+ inline RegOnly& extraReg() noexcept { return _baseInst.extraReg(); }
776
+ //! \overload
777
+ inline const RegOnly& extraReg() const noexcept { return _baseInst.extraReg(); }
778
+ //! Sets extra register operand to `reg`.
779
+ inline void setExtraReg(const BaseReg& reg) noexcept { _baseInst.setExtraReg(reg); }
780
+ //! Sets extra register operand to `reg`.
781
+ inline void setExtraReg(const RegOnly& reg) noexcept { _baseInst.setExtraReg(reg); }
782
+ //! Resets extra register operand.
783
+ inline void resetExtraReg() noexcept { _baseInst.resetExtraReg(); }
784
+
785
+ //! \}
786
+
787
+ //! \name Instruction Operands
788
+ //! \{
789
+
790
+ //! Returns operand count.
791
+ inline uint32_t opCount() const noexcept { return _inst._opCount; }
792
+ //! Returns operand capacity.
793
+ inline uint32_t opCapacity() const noexcept { return _inst._opCapacity; }
794
+
795
+ //! Sets operand count.
796
+ inline void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); }
797
+
798
+ //! Returns operands array.
799
+ inline Operand* operands() noexcept { return (Operand*)_opArray; }
800
+ //! Returns operands array (const).
801
+ inline const Operand* operands() const noexcept { return (const Operand*)_opArray; }
802
+
803
+ //! Returns operand at the given `index`.
804
+ inline Operand& op(uint32_t index) noexcept {
805
+ ASMJIT_ASSERT(index < opCapacity());
806
+ return _opArray[index].as<Operand>();
807
+ }
808
+
809
+ //! Returns operand at the given `index` (const).
810
+ inline const Operand& op(uint32_t index) const noexcept {
811
+ ASMJIT_ASSERT(index < opCapacity());
812
+ return _opArray[index].as<Operand>();
813
+ }
814
+
815
+ //! Sets operand at the given `index` to `op`.
816
+ inline void setOp(uint32_t index, const Operand_& op) noexcept {
817
+ ASMJIT_ASSERT(index < opCapacity());
818
+ _opArray[index].copyFrom(op);
819
+ }
820
+
821
+ //! Resets operand at the given `index` to none.
822
+ inline void resetOp(uint32_t index) noexcept {
823
+ ASMJIT_ASSERT(index < opCapacity());
824
+ _opArray[index].reset();
825
+ }
826
+
827
+ //! Resets operands at `[start, end)` range.
828
+ inline void resetOpRange(uint32_t start, uint32_t end) noexcept {
829
+ for (uint32_t i = start; i < end; i++)
830
+ _opArray[i].reset();
831
+ }
832
+
833
+ //! \}
834
+
835
+ //! \name Utilities
836
+ //! \{
837
+
838
+ inline bool hasOpType(OperandType opType) const noexcept {
839
+ for (uint32_t i = 0, count = opCount(); i < count; i++)
840
+ if (_opArray[i].opType() == opType)
841
+ return true;
842
+ return false;
843
+ }
844
+
845
+ inline bool hasRegOp() const noexcept { return hasOpType(OperandType::kReg); }
846
+ inline bool hasMemOp() const noexcept { return hasOpType(OperandType::kMem); }
847
+ inline bool hasImmOp() const noexcept { return hasOpType(OperandType::kImm); }
848
+ inline bool hasLabelOp() const noexcept { return hasOpType(OperandType::kLabel); }
849
+
850
+ inline uint32_t indexOfOpType(OperandType opType) const noexcept {
851
+ uint32_t i = 0;
852
+ uint32_t count = opCount();
853
+
854
+ while (i < count) {
855
+ if (_opArray[i].opType() == opType)
856
+ break;
857
+ i++;
858
+ }
859
+
860
+ return i;
861
+ }
862
+
863
+ inline uint32_t indexOfMemOp() const noexcept { return indexOfOpType(OperandType::kMem); }
864
+ inline uint32_t indexOfImmOp() const noexcept { return indexOfOpType(OperandType::kImm); }
865
+ inline uint32_t indexOfLabelOp() const noexcept { return indexOfOpType(OperandType::kLabel); }
866
+
867
+ //! \}
868
+
869
+ //! \name Rewriting
870
+ //! \{
871
+
872
+ //! \cond INTERNAL
873
+ inline uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; }
874
+ inline const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; }
875
+
876
+ inline uint32_t getRewriteIndex(const uint32_t* id) const noexcept {
877
+ const uint32_t* array = _getRewriteArray();
878
+ ASMJIT_ASSERT(array <= id);
879
+
880
+ size_t index = (size_t)(id - array);
881
+ ASMJIT_ASSERT(index < 32);
882
+
883
+ return uint32_t(index);
884
+ }
885
+
886
+ inline void rewriteIdAtIndex(uint32_t index, uint32_t id) noexcept {
887
+ uint32_t* array = _getRewriteArray();
888
+ array[index] = id;
889
+ }
890
+ //! \endcond
891
+
892
+ //! \}
893
+
894
+ //! \name Static Functions
895
+ //! \{
896
+
897
+ //! \cond INTERNAL
898
+ static inline uint32_t capacityOfOpCount(uint32_t opCount) noexcept {
899
+ return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount;
900
+ }
901
+
902
+ static inline size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept {
903
+ size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand);
904
+ return base + opCapacity * sizeof(Operand);
905
+ }
906
+ //! \endcond
907
+
908
+ //! \}
909
+ };
910
+
911
+ //! Instruction node with maximum number of operands.
912
+ //!
913
+ //! This node is created automatically by Builder/Compiler in case that the required number of operands exceeds
914
+ //! the default capacity of `InstNode`.
915
+ class InstExNode : public InstNode {
916
+ public:
917
+ ASMJIT_NONCOPYABLE(InstExNode)
918
+
919
+ //! \name Members
920
+ //! \{
921
+
922
+ //! Continued `_opArray[]` to hold up to `kMaxOpCount` operands.
923
+ Operand_ _opArrayEx[Globals::kMaxOpCount - kBaseOpCapacity];
924
+
925
+ //! \}
926
+
927
+ //! \name Construction & Destruction
928
+ //! \{
929
+
930
+ //! Creates a new `InstExNode` instance.
931
+ inline InstExNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept
932
+ : InstNode(cb, instId, options, opCapacity) {}
933
+
934
+ //! \}
935
+ };
936
+
937
+ //! Section node.
938
+ class SectionNode : public BaseNode {
939
+ public:
940
+ ASMJIT_NONCOPYABLE(SectionNode)
941
+
942
+ //! \name Members
943
+ //! \{
944
+
945
+ //! Section id.
946
+ uint32_t _id;
947
+
948
+ //! Next section node that follows this section.
949
+ //!
950
+ //! This link is only valid when the section is active (is part of the code) and when `Builder::hasDirtySectionLinks()`
951
+ //! returns `false`. If you intend to use this field you should always call `Builder::updateSectionLinks()` before you
952
+ //! do so.
953
+ SectionNode* _nextSection;
954
+
955
+ //! \}
956
+
957
+ //! \name Construction & Destruction
958
+ //! \{
959
+
960
+ //! Creates a new `SectionNode` instance.
961
+ inline SectionNode(BaseBuilder* cb, uint32_t secionId = 0) noexcept
962
+ : BaseNode(cb, NodeType::kSection, NodeFlags::kHasNoEffect),
963
+ _id(secionId),
964
+ _nextSection(nullptr) {}
965
+
966
+ //! \}
967
+
968
+ //! \name Accessors
969
+ //! \{
970
+
971
+ //! Returns the section id.
972
+ inline uint32_t id() const noexcept { return _id; }
973
+
974
+ //! \}
975
+ };
976
+
977
+ //! Label node.
978
+ class LabelNode : public BaseNode {
979
+ public:
980
+ ASMJIT_NONCOPYABLE(LabelNode)
981
+
982
+ //! \name Members
983
+ //! \{
984
+
985
+ //! Label identifier.
986
+ uint32_t _labelId;
987
+
988
+ //! \}
989
+
990
+ //! \name Construction & Destruction
991
+ //! \{
992
+
993
+ //! Creates a new `LabelNode` instance.
994
+ inline LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept
995
+ : BaseNode(cb, NodeType::kLabel, NodeFlags::kHasNoEffect | NodeFlags::kActsAsLabel),
996
+ _labelId(labelId) {}
997
+
998
+ //! \}
999
+
1000
+ //! \name Accessors
1001
+ //! \{
1002
+
1003
+ //! Returns \ref Label representation of the \ref LabelNode.
1004
+ inline Label label() const noexcept { return Label(_labelId); }
1005
+ //! Returns the id of the label.
1006
+ inline uint32_t labelId() const noexcept { return _labelId; }
1007
+
1008
+ //! \}
1009
+ };
1010
+
1011
+ //! Align directive (BaseBuilder).
1012
+ //!
1013
+ //! Wraps `.align` directive.
1014
+ class AlignNode : public BaseNode {
1015
+ public:
1016
+ ASMJIT_NONCOPYABLE(AlignNode)
1017
+
1018
+ //! \name Members
1019
+ //! \{
1020
+
1021
+ //! Alignment (in bytes).
1022
+ uint32_t _alignment;
1023
+
1024
+ //! \}
1025
+
1026
+ //! \name Construction & Destruction
1027
+ //! \{
1028
+
1029
+ //! Creates a new `AlignNode` instance.
1030
+ inline AlignNode(BaseBuilder* cb, AlignMode alignMode, uint32_t alignment) noexcept
1031
+ : BaseNode(cb, NodeType::kAlign, NodeFlags::kIsCode | NodeFlags::kHasNoEffect) {
1032
+
1033
+ _alignData._alignMode = alignMode;
1034
+ _alignment = alignment;
1035
+ }
1036
+
1037
+ //! \}
1038
+
1039
+ //! \name Accessors
1040
+ //! \{
1041
+
1042
+ //! Returns align mode.
1043
+ inline AlignMode alignMode() const noexcept { return _alignData._alignMode; }
1044
+ //! Sets align mode to `alignMode`.
1045
+ inline void setAlignMode(AlignMode alignMode) noexcept { _alignData._alignMode = alignMode; }
1046
+
1047
+ //! Returns align offset in bytes.
1048
+ inline uint32_t alignment() const noexcept { return _alignment; }
1049
+ //! Sets align offset in bytes to `offset`.
1050
+ inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
1051
+
1052
+ //! \}
1053
+ };
1054
+
1055
+ //! Embed data node.
1056
+ //!
1057
+ //! Wraps `.data` directive. The node contains data that will be placed at the node's position in the assembler
1058
+ //! stream. The data is considered to be RAW; no analysis nor byte-order conversion is performed on RAW data.
1059
+ class EmbedDataNode : public BaseNode {
1060
+ public:
1061
+ ASMJIT_NONCOPYABLE(EmbedDataNode)
1062
+
1063
+ //! \cond INTERNAL
1064
+ enum : uint32_t {
1065
+ kInlineBufferSize = 128 - (sizeof(BaseNode) + sizeof(size_t) * 2)
1066
+ };
1067
+ //! \endcond
1068
+
1069
+ //! \name Members
1070
+ //! \{
1071
+
1072
+ size_t _itemCount;
1073
+ size_t _repeatCount;
1074
+
1075
+ union {
1076
+ uint8_t* _externalData;
1077
+ uint8_t _inlineData[kInlineBufferSize];
1078
+ };
1079
+
1080
+ //! \}
1081
+
1082
+ //! \name Construction & Destruction
1083
+ //! \{
1084
+
1085
+ //! Creates a new `EmbedDataNode` instance.
1086
+ inline EmbedDataNode(BaseBuilder* cb) noexcept
1087
+ : BaseNode(cb, NodeType::kEmbedData, NodeFlags::kIsData),
1088
+ _itemCount(0),
1089
+ _repeatCount(0) {
1090
+ _embed._typeId = TypeId::kUInt8;
1091
+ _embed._typeSize = uint8_t(1);
1092
+ memset(_inlineData, 0, kInlineBufferSize);
1093
+ }
1094
+
1095
+ //! \}
1096
+
1097
+ //! \name Accessors
1098
+ //! \{
1099
+
1100
+ //! Returns data type as \ref TypeId.
1101
+ inline TypeId typeId() const noexcept { return _embed._typeId; }
1102
+ //! Returns the size of a single data element.
1103
+ inline uint32_t typeSize() const noexcept { return _embed._typeSize; }
1104
+
1105
+ //! Returns a pointer to the data casted to `uint8_t`.
1106
+ inline uint8_t* data() const noexcept {
1107
+ return dataSize() <= kInlineBufferSize ? const_cast<uint8_t*>(_inlineData) : _externalData;
1108
+ }
1109
+
1110
+ //! Returns a pointer to the data casted to `T`.
1111
+ template<typename T>
1112
+ inline T* dataAs() const noexcept { return reinterpret_cast<T*>(data()); }
1113
+
1114
+ //! Returns the number of (typed) items in the array.
1115
+ inline size_t itemCount() const noexcept { return _itemCount; }
1116
+
1117
+ //! Returns how many times the data is repeated (default 1).
1118
+ //!
1119
+ //! Repeated data is useful when defining constants for SIMD, for example.
1120
+ inline size_t repeatCount() const noexcept { return _repeatCount; }
1121
+
1122
+ //! Returns the size of the data, not considering the number of times it repeats.
1123
+ //!
1124
+ //! \note The returned value is the same as `typeSize() * itemCount()`.
1125
+ inline size_t dataSize() const noexcept { return typeSize() * _itemCount; }
1126
+
1127
+ //! \}
1128
+ };
1129
+
1130
+ //! Label data node.
1131
+ class EmbedLabelNode : public BaseNode {
1132
+ public:
1133
+ ASMJIT_NONCOPYABLE(EmbedLabelNode)
1134
+
1135
+ //! \name Members
1136
+ //! \{
1137
+
1138
+ uint32_t _labelId;
1139
+ uint32_t _dataSize;
1140
+
1141
+ //! \}
1142
+
1143
+ //! \name Construction & Destruction
1144
+ //! \{
1145
+
1146
+ //! Creates a new `EmbedLabelNode` instance.
1147
+ inline EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept
1148
+ : BaseNode(cb, NodeType::kEmbedLabel, NodeFlags::kIsData),
1149
+ _labelId(labelId),
1150
+ _dataSize(dataSize) {}
1151
+
1152
+ //! \}
1153
+
1154
+ //! \name Accessors
1155
+ //! \{
1156
+
1157
+ //! Returns the label to embed as \ref Label operand.
1158
+ inline Label label() const noexcept { return Label(_labelId); }
1159
+ //! Returns the id of the label.
1160
+ inline uint32_t labelId() const noexcept { return _labelId; }
1161
+
1162
+ //! Sets the label id from `label` operand.
1163
+ inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); }
1164
+ //! Sets the label id (use with caution, improper use can break a lot of things).
1165
+ inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; }
1166
+
1167
+ //! Returns the data size.
1168
+ inline uint32_t dataSize() const noexcept { return _dataSize; }
1169
+ //! Sets the data size.
1170
+ inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; }
1171
+
1172
+ //! \}
1173
+ };
1174
+
1175
+ //! Label data node.
1176
+ class EmbedLabelDeltaNode : public BaseNode {
1177
+ public:
1178
+ ASMJIT_NONCOPYABLE(EmbedLabelDeltaNode)
1179
+
1180
+ //! \name Members
1181
+ //! \{
1182
+
1183
+ uint32_t _labelId;
1184
+ uint32_t _baseLabelId;
1185
+ uint32_t _dataSize;
1186
+
1187
+ //! \}
1188
+
1189
+ //! \name Construction & Destruction
1190
+ //! \{
1191
+
1192
+ //! Creates a new `EmbedLabelDeltaNode` instance.
1193
+ inline EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept
1194
+ : BaseNode(cb, NodeType::kEmbedLabelDelta, NodeFlags::kIsData),
1195
+ _labelId(labelId),
1196
+ _baseLabelId(baseLabelId),
1197
+ _dataSize(dataSize) {}
1198
+
1199
+ //! \}
1200
+
1201
+ //! \name Accessors
1202
+ //! \{
1203
+
1204
+ //! Returns the label as `Label` operand.
1205
+ inline Label label() const noexcept { return Label(_labelId); }
1206
+ //! Returns the id of the label.
1207
+ inline uint32_t labelId() const noexcept { return _labelId; }
1208
+
1209
+ //! Sets the label id from `label` operand.
1210
+ inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); }
1211
+ //! Sets the label id.
1212
+ inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; }
1213
+
1214
+ //! Returns the base label as `Label` operand.
1215
+ inline Label baseLabel() const noexcept { return Label(_baseLabelId); }
1216
+ //! Returns the id of the base label.
1217
+ inline uint32_t baseLabelId() const noexcept { return _baseLabelId; }
1218
+
1219
+ //! Sets the base label id from `label` operand.
1220
+ inline void setBaseLabel(const Label& baseLabel) noexcept { setBaseLabelId(baseLabel.id()); }
1221
+ //! Sets the base label id.
1222
+ inline void setBaseLabelId(uint32_t baseLabelId) noexcept { _baseLabelId = baseLabelId; }
1223
+
1224
+ //! Returns the size of the embedded label address.
1225
+ inline uint32_t dataSize() const noexcept { return _dataSize; }
1226
+ //! Sets the size of the embedded label address.
1227
+ inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; }
1228
+
1229
+ //! \}
1230
+ };
1231
+
1232
+ //! A node that wraps `ConstPool`.
1233
+ class ConstPoolNode : public LabelNode {
1234
+ public:
1235
+ ASMJIT_NONCOPYABLE(ConstPoolNode)
1236
+
1237
+ //! \name Members
1238
+ //! \{
1239
+
1240
+ ConstPool _constPool;
1241
+
1242
+ //! \}
1243
+
1244
+ //! \name Construction & Destruction
1245
+ //! \{
1246
+
1247
+ //! Creates a new `ConstPoolNode` instance.
1248
+ inline ConstPoolNode(BaseBuilder* cb, uint32_t id = 0) noexcept
1249
+ : LabelNode(cb, id),
1250
+ _constPool(&cb->_codeZone) {
1251
+
1252
+ setType(NodeType::kConstPool);
1253
+ addFlags(NodeFlags::kIsData);
1254
+ clearFlags(NodeFlags::kIsCode | NodeFlags::kHasNoEffect);
1255
+ }
1256
+
1257
+ //! \}
1258
+
1259
+ //! \name Accessors
1260
+ //! \{
1261
+
1262
+ //! Tests whether the constant-pool is empty.
1263
+ inline bool empty() const noexcept { return _constPool.empty(); }
1264
+ //! Returns the size of the constant-pool in bytes.
1265
+ inline size_t size() const noexcept { return _constPool.size(); }
1266
+ //! Returns minimum alignment.
1267
+ inline size_t alignment() const noexcept { return _constPool.alignment(); }
1268
+
1269
+ //! Returns the wrapped `ConstPool` instance.
1270
+ inline ConstPool& constPool() noexcept { return _constPool; }
1271
+ //! Returns the wrapped `ConstPool` instance (const).
1272
+ inline const ConstPool& constPool() const noexcept { return _constPool; }
1273
+
1274
+ //! \}
1275
+
1276
+ //! \name Utilities
1277
+ //! \{
1278
+
1279
+ //! See `ConstPool::add()`.
1280
+ inline Error add(const void* data, size_t size, size_t& dstOffset) noexcept {
1281
+ return _constPool.add(data, size, dstOffset);
1282
+ }
1283
+
1284
+ //! \}
1285
+ };
1286
+
1287
+ //! Comment node.
1288
+ class CommentNode : public BaseNode {
1289
+ public:
1290
+ ASMJIT_NONCOPYABLE(CommentNode)
1291
+
1292
+ //! \name Construction & Destruction
1293
+ //! \{
1294
+
1295
+ //! Creates a new `CommentNode` instance.
1296
+ inline CommentNode(BaseBuilder* cb, const char* comment) noexcept
1297
+ : BaseNode(cb, NodeType::kComment, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect | NodeFlags::kIsRemovable) {
1298
+ _inlineComment = comment;
1299
+ }
1300
+
1301
+ //! \}
1302
+ };
1303
+
1304
+ //! Sentinel node.
1305
+ //!
1306
+ //! Sentinel is a marker that is completely ignored by the code builder. It's used to remember a position in a code
1307
+ //! as it never gets removed by any pass.
1308
+ class SentinelNode : public BaseNode {
1309
+ public:
1310
+ ASMJIT_NONCOPYABLE(SentinelNode)
1311
+
1312
+ //! \name Construction & Destruction
1313
+ //! \{
1314
+
1315
+ //! Creates a new `SentinelNode` instance.
1316
+ inline SentinelNode(BaseBuilder* cb, SentinelType sentinelType = SentinelType::kUnknown) noexcept
1317
+ : BaseNode(cb, NodeType::kSentinel, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect) {
1318
+
1319
+ _sentinel._sentinelType = sentinelType;
1320
+ }
1321
+
1322
+ //! \}
1323
+
1324
+ //! \name Accessors
1325
+ //! \{
1326
+
1327
+ //! Returns the type of the sentinel.
1328
+ inline SentinelType sentinelType() const noexcept {
1329
+ return _sentinel._sentinelType;
1330
+ }
1331
+
1332
+ //! Sets the type of the sentinel.
1333
+ inline void setSentinelType(SentinelType type) noexcept {
1334
+ _sentinel._sentinelType = type;
1335
+ }
1336
+
1337
+ //! \}
1338
+ };
1339
+
1340
+ //! Pass can be used to implement code transformations, analysis, and lowering.
1341
+ class ASMJIT_VIRTAPI Pass {
1342
+ public:
1343
+ ASMJIT_BASE_CLASS(Pass)
1344
+ ASMJIT_NONCOPYABLE(Pass)
1345
+
1346
+ //! \name Members
1347
+ //! \{
1348
+
1349
+ //! BaseBuilder this pass is assigned to.
1350
+ BaseBuilder* _cb = nullptr;
1351
+ //! Name of the pass.
1352
+ const char* _name = nullptr;
1353
+
1354
+ //! \}
1355
+
1356
+ //! \name Construction & Destruction
1357
+ //! \{
1358
+
1359
+ ASMJIT_API Pass(const char* name) noexcept;
1360
+ ASMJIT_API virtual ~Pass() noexcept;
1361
+
1362
+ //! \}
1363
+
1364
+ //! \name Accessors
1365
+ //! \{
1366
+
1367
+ //! Returns \ref BaseBuilder associated with the pass.
1368
+ inline const BaseBuilder* cb() const noexcept { return _cb; }
1369
+ //! Returns the name of the pass.
1370
+ inline const char* name() const noexcept { return _name; }
1371
+
1372
+ //! \}
1373
+
1374
+ //! \name Pass Interface
1375
+ //! \{
1376
+
1377
+ //! Processes the code stored in Builder or Compiler.
1378
+ //!
1379
+ //! This is the only function that is called by the `BaseBuilder` to process the code. It passes `zone`,
1380
+ //! which will be reset after the `run()` finishes.
1381
+ virtual Error run(Zone* zone, Logger* logger) = 0;
1382
+
1383
+ //! \}
1384
+ };
1385
+
1386
+ //! \}
1387
+
1388
+ ASMJIT_END_NAMESPACE
1389
+
1390
+ #endif // !ASMJIT_NO_BUILDER
1391
+ #endif // ASMJIT_CORE_BUILDER_H_INCLUDED