asmjit 0.2.0 → 0.2.1

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