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,741 @@
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_EMITTER_H_INCLUDED
7
+ #define ASMJIT_CORE_EMITTER_H_INCLUDED
8
+
9
+ #include "../core/archtraits.h"
10
+ #include "../core/codeholder.h"
11
+ #include "../core/formatter.h"
12
+ #include "../core/inst.h"
13
+ #include "../core/operand.h"
14
+ #include "../core/type.h"
15
+
16
+ ASMJIT_BEGIN_NAMESPACE
17
+
18
+ //! \addtogroup asmjit_core
19
+ //! \{
20
+
21
+ class ConstPool;
22
+ class FuncFrame;
23
+ class FuncArgsAssignment;
24
+
25
+ //! Align mode, used by \ref BaseEmitter::align().
26
+ enum class AlignMode : uint8_t {
27
+ //! Align executable code.
28
+ kCode = 0,
29
+ //! Align non-executable code.
30
+ kData = 1,
31
+ //! Align by a sequence of zeros.
32
+ kZero = 2,
33
+
34
+ //! Maximum value of `AlignMode`.
35
+ kMaxValue = kZero
36
+ };
37
+
38
+ //! Emitter type used by \ref BaseEmitter.
39
+ enum class EmitterType : uint8_t {
40
+ //! Unknown or uninitialized.
41
+ kNone = 0,
42
+ //! Emitter inherits from \ref BaseAssembler.
43
+ kAssembler = 1,
44
+ //! Emitter inherits from \ref BaseBuilder.
45
+ kBuilder = 2,
46
+ //! Emitter inherits from \ref BaseCompiler.
47
+ kCompiler = 3,
48
+
49
+ //! Maximum value of `EmitterType`.
50
+ kMaxValue = kCompiler
51
+ };
52
+
53
+ //! Emitter flags, used by \ref BaseEmitter.
54
+ enum class EmitterFlags : uint8_t {
55
+ //! No flags.
56
+ kNone = 0u,
57
+ //! Emitter is attached to CodeHolder.
58
+ kAttached = 0x01u,
59
+ //! The emitter must emit comments.
60
+ kLogComments = 0x08u,
61
+ //! The emitter has its own \ref Logger (not propagated from \ref CodeHolder).
62
+ kOwnLogger = 0x10u,
63
+ //! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder).
64
+ kOwnErrorHandler = 0x20u,
65
+ //! The emitter was finalized.
66
+ kFinalized = 0x40u,
67
+ //! The emitter was destroyed.
68
+ //!
69
+ //! This flag is used for a very short time when an emitter is being destroyed by
70
+ //! CodeHolder.
71
+ kDestroyed = 0x80u
72
+ };
73
+ ASMJIT_DEFINE_ENUM_FLAGS(EmitterFlags)
74
+
75
+ //! Encoding options.
76
+ enum class EncodingOptions : uint32_t {
77
+ //! No encoding options.
78
+ kNone = 0,
79
+
80
+ //! Emit instructions that are optimized for size, if possible.
81
+ //!
82
+ //! Default: false.
83
+ //!
84
+ //! X86 Specific
85
+ //! ------------
86
+ //!
87
+ //! When this option is set it the assembler will try to fix instructions if possible into operation equivalent
88
+ //! instructions that take less bytes by taking advantage of implicit zero extension. For example instruction
89
+ //! like `mov r64, imm` and `and r64, imm` can be translated to `mov r32, imm` and `and r32, imm` when the
90
+ //! immediate constant is lesser than `2^31`.
91
+ kOptimizeForSize = 0x00000001u,
92
+
93
+ //! Emit optimized code-alignment sequences.
94
+ //!
95
+ //! Default: false.
96
+ //!
97
+ //! X86 Specific
98
+ //! ------------
99
+ //!
100
+ //! Default align sequence used by X86 architecture is one-byte (0x90) opcode that is often shown by disassemblers
101
+ //! as NOP. However there are more optimized align sequences for 2-11 bytes that may execute faster on certain CPUs.
102
+ //! If this feature is enabled AsmJit will generate specialized sequences for alignment between 2 to 11 bytes.
103
+ kOptimizedAlign = 0x00000002u,
104
+
105
+ //! Emit jump-prediction hints.
106
+ //!
107
+ //! Default: false.
108
+ //!
109
+ //! X86 Specific
110
+ //! ------------
111
+ //!
112
+ //! Jump prediction is usually based on the direction of the jump. If the jump is backward it is usually predicted as
113
+ //! taken; and if the jump is forward it is usually predicted as not-taken. The reason is that loops generally use
114
+ //! backward jumps and conditions usually use forward jumps. However this behavior can be overridden by using
115
+ //! instruction prefixes. If this option is enabled these hints will be emitted.
116
+ //!
117
+ //! This feature is disabled by default, because the only processor that used to take into consideration prediction
118
+ //! hints was P4. Newer processors implement heuristics for branch prediction and ignore static hints. This means
119
+ //! that this feature can be only used for annotation purposes.
120
+ kPredictedJumps = 0x00000010u
121
+ };
122
+ ASMJIT_DEFINE_ENUM_FLAGS(EncodingOptions)
123
+
124
+ //! Diagnostic options are used to tell emitters and their passes to perform diagnostics when emitting or processing
125
+ //! user code. These options control validation and extra diagnostics that can be performed by higher level emitters.
126
+ //!
127
+ //! Instruction Validation
128
+ //! ----------------------
129
+ //!
130
+ //! \ref BaseAssembler implementation perform by default only basic checks that are necessary to identify all
131
+ //! variations of an instruction so the correct encoding can be selected. This is fine for production-ready code
132
+ //! as the assembler doesn't have to perform checks that would slow it down. However, sometimes these checks are
133
+ //! beneficial especially when the project that uses AsmJit is in a development phase, in which mistakes happen
134
+ //! often. To make the experience of using AsmJit seamless it offers validation features that can be controlled
135
+ //! by \ref DiagnosticOptions.
136
+ //!
137
+ //! Compiler Diagnostics
138
+ //! --------------------
139
+ //!
140
+ //! Diagnostic options work with \ref BaseCompiler passes (precisely with its register allocation pass). These options
141
+ //! can be used to enable logging of all operations that the Compiler does.
142
+ enum class DiagnosticOptions : uint32_t {
143
+ //! No validation options.
144
+ kNone = 0,
145
+
146
+ //! Perform strict validation in \ref BaseAssembler::emit() implementations.
147
+ //!
148
+ //! This flag ensures that each instruction is checked before it's encoded into a binary representation. This flag
149
+ //! is only relevant for \ref BaseAssembler implementations, but can be set in any other emitter type, in that case
150
+ //! if that emitter needs to create an assembler on its own, for the purpose of \ref BaseEmitter::finalize() it
151
+ //! would propagate this flag to such assembler so all instructions passed to it are explicitly validated.
152
+ //!
153
+ //! Default: false.
154
+ kValidateAssembler = 0x00000001u,
155
+
156
+ //! Perform strict validation in \ref BaseBuilder::emit() and \ref BaseCompiler::emit() implementations.
157
+ //!
158
+ //! This flag ensures that each instruction is checked before an \ref InstNode representing the instruction is
159
+ //! created by \ref BaseBuilder or \ref BaseCompiler. This option could be more useful than \ref kValidateAssembler
160
+ //! in cases in which there is an invalid instruction passed to an assembler, which was invalid much earlier, most
161
+ //! likely when such instruction was passed to Builder/Compiler.
162
+ //!
163
+ //! This is a separate option that was introduced, because it's possible to manipulate the instruction stream
164
+ //! emitted by \ref BaseBuilder and \ref BaseCompiler - this means that it's allowed to emit invalid instructions
165
+ //! (for example with missing operands) that will be fixed later before finalizing it.
166
+ //!
167
+ //! Default: false.
168
+ kValidateIntermediate = 0x00000002u,
169
+
170
+ //! Annotate all nodes processed by register allocator (Compiler/RA).
171
+ //!
172
+ //! \note Annotations don't need debug options, however, some debug options like `kRADebugLiveness` may influence
173
+ //! their output (for example the mentioned option would add liveness information to per-instruction annotation).
174
+ kRAAnnotate = 0x00000080u,
175
+
176
+ //! Debug CFG generation and other related algorithms / operations (Compiler/RA).
177
+ kRADebugCFG = 0x00000100u,
178
+
179
+ //! Debug liveness analysis (Compiler/RA).
180
+ kRADebugLiveness = 0x00000200u,
181
+
182
+ //! Debug register allocation assignment (Compiler/RA).
183
+ kRADebugAssignment = 0x00000400u,
184
+
185
+ //! Debug the removal of code part of unreachable blocks.
186
+ kRADebugUnreachable = 0x00000800u,
187
+
188
+ //! Enable all debug options (Compiler/RA).
189
+ kRADebugAll = 0x0000FF00u,
190
+ };
191
+ ASMJIT_DEFINE_ENUM_FLAGS(DiagnosticOptions)
192
+
193
+ //! Provides a base foundation to emitting code - specialized by \ref BaseAssembler and \ref BaseBuilder.
194
+ class ASMJIT_VIRTAPI BaseEmitter {
195
+ public:
196
+ ASMJIT_BASE_CLASS(BaseEmitter)
197
+
198
+ //! \name Members
199
+ //! \{
200
+
201
+ //! See \ref EmitterType.
202
+ EmitterType _emitterType = EmitterType::kNone;
203
+ //! See \ref EmitterFlags.
204
+ EmitterFlags _emitterFlags = EmitterFlags::kNone;
205
+ //! Validation flags in case validation is used.
206
+ //!
207
+ //! \note Validation flags are specific to the emitter and they are setup at construction time and then never
208
+ //! changed.
209
+ ValidationFlags _validationFlags = ValidationFlags::kNone;
210
+ //! Validation options.
211
+ DiagnosticOptions _diagnosticOptions = DiagnosticOptions::kNone;
212
+
213
+ //! All supported architectures in a bit-mask, where LSB is the bit with a zero index.
214
+ uint64_t _archMask = 0;
215
+
216
+ //! Encoding options.
217
+ EncodingOptions _encodingOptions = EncodingOptions::kNone;
218
+
219
+ //! Forced instruction options, combined with \ref _instOptions by \ref emit().
220
+ InstOptions _forcedInstOptions = InstOptions::kReserved;
221
+ //! Internal private data used freely by any emitter.
222
+ uint32_t _privateData = 0;
223
+
224
+ //! CodeHolder the emitter is attached to.
225
+ CodeHolder* _code = nullptr;
226
+ //! Attached \ref Logger.
227
+ Logger* _logger = nullptr;
228
+ //! Attached \ref ErrorHandler.
229
+ ErrorHandler* _errorHandler = nullptr;
230
+
231
+ //! Describes the target environment, matches \ref CodeHolder::environment().
232
+ Environment _environment {};
233
+ //! Native GP register signature and signature related information.
234
+ OperandSignature _gpSignature {};
235
+
236
+ //! Next instruction options (affects the next instruction).
237
+ InstOptions _instOptions = InstOptions::kNone;
238
+ //! Extra register (op-mask {k} on AVX-512) (affects the next instruction).
239
+ RegOnly _extraReg {};
240
+ //! Inline comment of the next instruction (affects the next instruction).
241
+ const char* _inlineComment = nullptr;
242
+
243
+ //! Function callbacks used by emitter implementation.
244
+ //!
245
+ //! These are typically shared between Assembler/Builder/Compiler of a single backend.
246
+ struct Funcs {
247
+ typedef Error (ASMJIT_CDECL* EmitProlog)(BaseEmitter* emitter, const FuncFrame& frame);
248
+ typedef Error (ASMJIT_CDECL* EmitEpilog)(BaseEmitter* emitter, const FuncFrame& frame);
249
+ typedef Error (ASMJIT_CDECL* EmitArgsAssignment)(BaseEmitter* emitter, const FuncFrame& frame, const FuncArgsAssignment& args);
250
+
251
+ typedef Error (ASMJIT_CDECL* FormatInstruction)(
252
+ String& sb,
253
+ FormatFlags formatFlags,
254
+ const BaseEmitter* emitter,
255
+ Arch arch,
256
+ const BaseInst& inst, const Operand_* operands, size_t opCount) ASMJIT_NOEXCEPT_TYPE;
257
+
258
+ typedef Error (ASMJIT_CDECL* ValidateFunc)(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) ASMJIT_NOEXCEPT_TYPE;
259
+
260
+ //! Emit prolog implementation.
261
+ EmitProlog emitProlog;
262
+ //! Emit epilog implementation.
263
+ EmitEpilog emitEpilog;
264
+ //! Emit arguments assignment implementation.
265
+ EmitArgsAssignment emitArgsAssignment;
266
+ //! Instruction formatter implementation.
267
+ FormatInstruction formatInstruction;
268
+ //! Instruction validation implementation.
269
+ ValidateFunc validate;
270
+
271
+ //! Resets all functions to nullptr.
272
+ inline void reset() noexcept {
273
+ emitProlog = nullptr;
274
+ emitEpilog = nullptr;
275
+ emitArgsAssignment = nullptr;
276
+ validate = nullptr;
277
+ }
278
+ };
279
+
280
+ Funcs _funcs {};
281
+
282
+ //! \}
283
+
284
+ //! \name Construction & Destruction
285
+ //! \{
286
+
287
+ ASMJIT_API explicit BaseEmitter(EmitterType emitterType) noexcept;
288
+ ASMJIT_API virtual ~BaseEmitter() noexcept;
289
+
290
+ //! \}
291
+
292
+ //! \name Cast
293
+ //! \{
294
+
295
+ template<typename T>
296
+ inline T* as() noexcept { return reinterpret_cast<T*>(this); }
297
+
298
+ template<typename T>
299
+ inline const T* as() const noexcept { return reinterpret_cast<const T*>(this); }
300
+
301
+ //! \}
302
+
303
+ //! \name Emitter Type & Flags
304
+ //! \{
305
+
306
+ //! Returns the type of this emitter, see `EmitterType`.
307
+ inline EmitterType emitterType() const noexcept { return _emitterType; }
308
+ //! Returns emitter flags , see `Flags`.
309
+ inline EmitterFlags emitterFlags() const noexcept { return _emitterFlags; }
310
+
311
+ //! Tests whether the emitter inherits from `BaseAssembler`.
312
+ inline bool isAssembler() const noexcept { return _emitterType == EmitterType::kAssembler; }
313
+ //! Tests whether the emitter inherits from `BaseBuilder`.
314
+ //!
315
+ //! \note Both Builder and Compiler emitters would return `true`.
316
+ inline bool isBuilder() const noexcept { return uint32_t(_emitterType) >= uint32_t(EmitterType::kBuilder); }
317
+ //! Tests whether the emitter inherits from `BaseCompiler`.
318
+ inline bool isCompiler() const noexcept { return _emitterType == EmitterType::kCompiler; }
319
+
320
+ //! Tests whether the emitter has the given `flag` enabled.
321
+ inline bool hasEmitterFlag(EmitterFlags flag) const noexcept { return Support::test(_emitterFlags, flag); }
322
+ //! Tests whether the emitter is finalized.
323
+ inline bool isFinalized() const noexcept { return hasEmitterFlag(EmitterFlags::kFinalized); }
324
+ //! Tests whether the emitter is destroyed (only used during destruction).
325
+ inline bool isDestroyed() const noexcept { return hasEmitterFlag(EmitterFlags::kDestroyed); }
326
+
327
+ inline void _addEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags |= flags; }
328
+ inline void _clearEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags &= _emitterFlags & ~flags; }
329
+
330
+ //! \}
331
+
332
+ //! \name Target Information
333
+ //! \{
334
+
335
+ //! Returns the CodeHolder this emitter is attached to.
336
+ inline CodeHolder* code() const noexcept { return _code; }
337
+
338
+ //! Returns the target environment.
339
+ //!
340
+ //! The returned \ref Environment reference matches \ref CodeHolder::environment().
341
+ inline const Environment& environment() const noexcept { return _environment; }
342
+
343
+ //! Tests whether the target architecture is 32-bit.
344
+ inline bool is32Bit() const noexcept { return environment().is32Bit(); }
345
+ //! Tests whether the target architecture is 64-bit.
346
+ inline bool is64Bit() const noexcept { return environment().is64Bit(); }
347
+
348
+ //! Returns the target architecture type.
349
+ inline Arch arch() const noexcept { return environment().arch(); }
350
+ //! Returns the target architecture sub-type.
351
+ inline SubArch subArch() const noexcept { return environment().subArch(); }
352
+
353
+ //! Returns the target architecture's GP register size (4 or 8 bytes).
354
+ inline uint32_t registerSize() const noexcept { return environment().registerSize(); }
355
+
356
+ //! \}
357
+
358
+ //! \name Initialization & Finalization
359
+ //! \{
360
+
361
+ //! Tests whether the emitter is initialized (i.e. attached to \ref CodeHolder).
362
+ inline bool isInitialized() const noexcept { return _code != nullptr; }
363
+
364
+ //! Finalizes this emitter.
365
+ //!
366
+ //! Materializes the content of the emitter by serializing it to the attached \ref CodeHolder through an architecture
367
+ //! specific \ref BaseAssembler. This function won't do anything if the emitter inherits from \ref BaseAssembler as
368
+ //! assemblers emit directly to a \ref CodeBuffer held by \ref CodeHolder. However, if this is an emitter that
369
+ //! inherits from \ref BaseBuilder or \ref BaseCompiler then these emitters need the materialization phase as they
370
+ //! store their content in a representation not visible to \ref CodeHolder.
371
+ ASMJIT_API virtual Error finalize();
372
+
373
+ //! \}
374
+
375
+ //! \name Logging
376
+ //! \{
377
+
378
+ //! Tests whether the emitter has a logger.
379
+ inline bool hasLogger() const noexcept { return _logger != nullptr; }
380
+
381
+ //! Tests whether the emitter has its own logger.
382
+ //!
383
+ //! Own logger means that it overrides the possible logger that may be used by \ref CodeHolder this emitter is
384
+ //! attached to.
385
+ inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnLogger); }
386
+
387
+ //! Returns the logger this emitter uses.
388
+ //!
389
+ //! The returned logger is either the emitter's own logger or it's logger used by \ref CodeHolder this emitter
390
+ //! is attached to.
391
+ inline Logger* logger() const noexcept { return _logger; }
392
+
393
+ //! Sets or resets the logger of the emitter.
394
+ //!
395
+ //! If the `logger` argument is non-null then the logger will be considered emitter's own logger, see \ref
396
+ //! hasOwnLogger() for more details. If the given `logger` is null then the emitter will automatically use logger
397
+ //! that is attached to the \ref CodeHolder this emitter is attached to.
398
+ ASMJIT_API void setLogger(Logger* logger) noexcept;
399
+
400
+ //! Resets the logger of this emitter.
401
+ //!
402
+ //! The emitter will bail to using a logger attached to \ref CodeHolder this emitter is attached to, or no logger
403
+ //! at all if \ref CodeHolder doesn't have one.
404
+ inline void resetLogger() noexcept { return setLogger(nullptr); }
405
+
406
+ //! \}
407
+
408
+ //! \name Error Handling
409
+ //! \{
410
+
411
+ //! Tests whether the emitter has an error handler attached.
412
+ inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; }
413
+
414
+ //! Tests whether the emitter has its own error handler.
415
+ //!
416
+ //! Own error handler means that it overrides the possible error handler that may be used by \ref CodeHolder this
417
+ //! emitter is attached to.
418
+ inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnErrorHandler); }
419
+
420
+ //! Returns the error handler this emitter uses.
421
+ //!
422
+ //! The returned error handler is either the emitter's own error handler or it's error handler used by
423
+ //! \ref CodeHolder this emitter is attached to.
424
+ inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; }
425
+
426
+ //! Sets or resets the error handler of the emitter.
427
+ ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept;
428
+
429
+ //! Resets the error handler.
430
+ inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); }
431
+
432
+ //! Handles the given error in the following way:
433
+ //! 1. If the emitter has \ref ErrorHandler attached, it calls its \ref ErrorHandler::handleError() member function
434
+ //! first, and then returns the error. The `handleError()` function may throw.
435
+ //! 2. if the emitter doesn't have \ref ErrorHandler, the error is simply returned.
436
+ ASMJIT_API Error reportError(Error err, const char* message = nullptr);
437
+
438
+ //! \}
439
+
440
+ //! \name Encoding Options
441
+ //! \{
442
+
443
+ //! Returns encoding options.
444
+ inline EncodingOptions encodingOptions() const noexcept { return _encodingOptions; }
445
+ //! Tests whether the encoding `option` is set.
446
+ inline bool hasEncodingOption(EncodingOptions option) const noexcept { return Support::test(_encodingOptions, option); }
447
+
448
+ //! Enables the given encoding `options`.
449
+ inline void addEncodingOptions(EncodingOptions options) noexcept { _encodingOptions |= options; }
450
+ //! Disables the given encoding `options`.
451
+ inline void clearEncodingOptions(EncodingOptions options) noexcept { _encodingOptions &= ~options; }
452
+
453
+ //! \}
454
+
455
+ //! \name Diagnostic Options
456
+ //! \{
457
+
458
+ //! Returns the emitter's diagnostic options.
459
+ inline DiagnosticOptions diagnosticOptions() const noexcept { return _diagnosticOptions; }
460
+
461
+ //! Tests whether the given `option` is present in the emitter's diagnostic options.
462
+ inline bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); }
463
+
464
+ //! Activates the given diagnostic `options`.
465
+ //!
466
+ //! This function is used to activate explicit validation options that will be then used by all emitter
467
+ //! implementations. There are in general two possibilities:
468
+ //!
469
+ //! - Architecture specific assembler is used. In this case a \ref DiagnosticOptions::kValidateAssembler can be
470
+ //! used to turn on explicit validation that will be used before an instruction is emitted. This means that
471
+ //! internally an extra step will be performed to make sure that the instruction is correct. This is needed,
472
+ //! because by default assemblers prefer speed over strictness.
473
+ //!
474
+ //! This option should be used in debug builds as it's pretty expensive.
475
+ //!
476
+ //! - Architecture specific builder or compiler is used. In this case the user can turn on
477
+ //! \ref DiagnosticOptions::kValidateIntermediate option that adds explicit validation step before the Builder
478
+ //! or Compiler creates an \ref InstNode to represent an emitted instruction. Error will be returned if the
479
+ //! instruction is ill-formed. In addition, also \ref DiagnosticOptions::kValidateAssembler can be used, which
480
+ //! would not be consumed by Builder / Compiler directly, but it would be propagated to an architecture specific
481
+ //! \ref BaseAssembler implementation it creates during \ref BaseEmitter::finalize().
482
+ ASMJIT_API void addDiagnosticOptions(DiagnosticOptions options) noexcept;
483
+
484
+ //! Deactivates the given validation `options`.
485
+ //!
486
+ //! See \ref addDiagnosticOptions() and \ref DiagnosticOptions for more details.
487
+ ASMJIT_API void clearDiagnosticOptions(DiagnosticOptions options) noexcept;
488
+
489
+ //! \}
490
+
491
+ //! \name Instruction Options
492
+ //! \{
493
+
494
+ //! Returns forced instruction options.
495
+ //!
496
+ //! Forced instruction options are merged with next instruction options before the instruction is encoded. These
497
+ //! options have some bits reserved that are used by error handling, logging, and instruction validation purposes.
498
+ //! Other options are globals that affect each instruction.
499
+ inline InstOptions forcedInstOptions() const noexcept { return _forcedInstOptions; }
500
+
501
+ //! Returns options of the next instruction.
502
+ inline InstOptions instOptions() const noexcept { return _instOptions; }
503
+ //! Returns options of the next instruction.
504
+ inline void setInstOptions(InstOptions options) noexcept { _instOptions = options; }
505
+ //! Adds options of the next instruction.
506
+ inline void addInstOptions(InstOptions options) noexcept { _instOptions |= options; }
507
+ //! Resets options of the next instruction.
508
+ inline void resetInstOptions() noexcept { _instOptions = InstOptions::kNone; }
509
+
510
+ //! Tests whether the extra register operand is valid.
511
+ inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
512
+ //! Returns an extra operand that will be used by the next instruction (architecture specific).
513
+ inline const RegOnly& extraReg() const noexcept { return _extraReg; }
514
+ //! Sets an extra operand that will be used by the next instruction (architecture specific).
515
+ inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
516
+ //! Sets an extra operand that will be used by the next instruction (architecture specific).
517
+ inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
518
+ //! Resets an extra operand that will be used by the next instruction (architecture specific).
519
+ inline void resetExtraReg() noexcept { _extraReg.reset(); }
520
+
521
+ //! Returns comment/annotation of the next instruction.
522
+ inline const char* inlineComment() const noexcept { return _inlineComment; }
523
+ //! Sets comment/annotation of the next instruction.
524
+ //!
525
+ //! \note This string is set back to null by `_emit()`, but until that it has to remain valid as the Emitter is not
526
+ //! required to make a copy of it (and it would be slow to do that for each instruction).
527
+ inline void setInlineComment(const char* s) noexcept { _inlineComment = s; }
528
+ //! Resets the comment/annotation to nullptr.
529
+ inline void resetInlineComment() noexcept { _inlineComment = nullptr; }
530
+
531
+ //! \}
532
+
533
+ //! \name Sections
534
+ //! \{
535
+
536
+ virtual Error section(Section* section) = 0;
537
+
538
+ //! \}
539
+
540
+ //! \name Labels
541
+ //! \{
542
+
543
+ //! Creates a new label.
544
+ virtual Label newLabel() = 0;
545
+ //! Creates a new named label.
546
+ virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) = 0;
547
+
548
+ //! Creates a new anonymous label with a name, which can only be used for debugging purposes.
549
+ inline Label newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kAnonymous); }
550
+ //! Creates a new external label.
551
+ inline Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kExternal); }
552
+
553
+ //! Returns `Label` by `name`.
554
+ //!
555
+ //! Returns invalid Label in case that the name is invalid or label was not found.
556
+ //!
557
+ //! \note This function doesn't trigger ErrorHandler in case the name is invalid or no such label exist. You must
558
+ //! always check the validity of the `Label` returned.
559
+ ASMJIT_API Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept;
560
+
561
+ //! Binds the `label` to the current position of the current section.
562
+ //!
563
+ //! \note Attempt to bind the same label multiple times will return an error.
564
+ virtual Error bind(const Label& label) = 0;
565
+
566
+ //! Tests whether the label `id` is valid (i.e. registered).
567
+ ASMJIT_API bool isLabelValid(uint32_t labelId) const noexcept;
568
+ //! Tests whether the `label` is valid (i.e. registered).
569
+ inline bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); }
570
+
571
+ //! \}
572
+
573
+ //! \name Emit
574
+ //! \{
575
+
576
+ // NOTE: These `emit()` helpers are designed to address a code-bloat generated by C++ compilers to call a function
577
+ // having many arguments. Each parameter to `_emit()` requires some code to pass it, which means that if we default
578
+ // to 5 arguments in `_emit()` and instId the C++ compiler would have to generate a virtual function call having 5
579
+ // parameters and additional `this` argument, which is quite a lot. Since by default most instructions have 2 to 3
580
+ // operands it's better to introduce helpers that pass from 0 to 6 operands that help to reduce the size of emit(...)
581
+ // function call.
582
+
583
+ //! Emits an instruction (internal).
584
+ ASMJIT_API Error _emitI(InstId instId);
585
+ //! \overload
586
+ ASMJIT_API Error _emitI(InstId instId, const Operand_& o0);
587
+ //! \overload
588
+ ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1);
589
+ //! \overload
590
+ ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2);
591
+ //! \overload
592
+ ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3);
593
+ //! \overload
594
+ ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4);
595
+ //! \overload
596
+ ASMJIT_API Error _emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5);
597
+
598
+ //! Emits an instruction `instId` with the given `operands`.
599
+ template<typename... Args>
600
+ ASMJIT_FORCE_INLINE Error emit(InstId instId, Args&&... operands) {
601
+ return _emitI(instId, Support::ForwardOp<Args>::forward(operands)...);
602
+ }
603
+
604
+ ASMJIT_FORCE_INLINE Error emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
605
+ return _emitOpArray(instId, operands, opCount);
606
+ }
607
+
608
+ ASMJIT_FORCE_INLINE Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) {
609
+ setInstOptions(inst.options());
610
+ setExtraReg(inst.extraReg());
611
+ return _emitOpArray(inst.id(), operands, opCount);
612
+ }
613
+
614
+ //! \cond INTERNAL
615
+ //! Emits an instruction - all 6 operands must be defined.
616
+ virtual Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0;
617
+ //! Emits instruction having operands stored in array.
618
+ ASMJIT_API virtual Error _emitOpArray(InstId instId, const Operand_* operands, size_t opCount);
619
+ //! \endcond
620
+
621
+ //! \}
622
+
623
+ //! \name Emit Utilities
624
+ //! \{
625
+
626
+ ASMJIT_API Error emitProlog(const FuncFrame& frame);
627
+ ASMJIT_API Error emitEpilog(const FuncFrame& frame);
628
+ ASMJIT_API Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args);
629
+
630
+ //! \}
631
+
632
+ //! \name Align
633
+ //! \{
634
+
635
+ //! Aligns the current CodeBuffer position to the `alignment` specified.
636
+ //!
637
+ //! The sequence that is used to fill the gap between the aligned location and the current location depends on the
638
+ //! align `mode`, see \ref AlignMode. The `alignment` argument specifies alignment in bytes, so for example when
639
+ //! it's `32` it means that the code buffer will be aligned to `32` bytes.
640
+ virtual Error align(AlignMode alignMode, uint32_t alignment) = 0;
641
+
642
+ //! \}
643
+
644
+ //! \name Embed
645
+ //! \{
646
+
647
+ //! Embeds raw data into the \ref CodeBuffer.
648
+ virtual Error embed(const void* data, size_t dataSize) = 0;
649
+
650
+ //! Embeds a typed data array.
651
+ //!
652
+ //! This is the most flexible function for embedding data as it allows to:
653
+ //!
654
+ //! - Assign a `typeId` to the data, so the emitter knows the type of items stored in `data`. Binary data should
655
+ //! use \ref TypeId::kUInt8.
656
+ //!
657
+ //! - Repeat the given data `repeatCount` times, so the data can be used as a fill pattern for example, or as a
658
+ //! pattern used by SIMD instructions.
659
+ virtual Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0;
660
+
661
+ //! Embeds int8_t `value` repeated by `repeatCount`.
662
+ inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt8, &value, 1, repeatCount); }
663
+ //! Embeds uint8_t `value` repeated by `repeatCount`.
664
+ inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt8, &value, 1, repeatCount); }
665
+ //! Embeds int16_t `value` repeated by `repeatCount`.
666
+ inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt16, &value, 1, repeatCount); }
667
+ //! Embeds uint16_t `value` repeated by `repeatCount`.
668
+ inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt16, &value, 1, repeatCount); }
669
+ //! Embeds int32_t `value` repeated by `repeatCount`.
670
+ inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt32, &value, 1, repeatCount); }
671
+ //! Embeds uint32_t `value` repeated by `repeatCount`.
672
+ inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt32, &value, 1, repeatCount); }
673
+ //! Embeds int64_t `value` repeated by `repeatCount`.
674
+ inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt64, &value, 1, repeatCount); }
675
+ //! Embeds uint64_t `value` repeated by `repeatCount`.
676
+ inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt64, &value, 1, repeatCount); }
677
+ //! Embeds a floating point `value` repeated by `repeatCount`.
678
+ inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<float>::kTypeId), &value, 1, repeatCount); }
679
+ //! Embeds a floating point `value` repeated by `repeatCount`.
680
+ inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<double>::kTypeId), &value, 1, repeatCount); }
681
+
682
+ //! Embeds a constant pool at the current offset by performing the following:
683
+ //! 1. Aligns by using AlignMode::kData to the minimum `pool` alignment.
684
+ //! 2. Binds the ConstPool label so it's bound to an aligned location.
685
+ //! 3. Emits ConstPool content.
686
+ virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0;
687
+
688
+ //! Embeds an absolute `label` address as data.
689
+ //!
690
+ //! The `dataSize` is an optional argument that can be used to specify the size of the address data. If it's zero
691
+ //! (default) the address size is deduced from the target architecture (either 4 or 8 bytes).
692
+ virtual Error embedLabel(const Label& label, size_t dataSize = 0) = 0;
693
+
694
+ //! Embeds a delta (distance) between the `label` and `base` calculating it as `label - base`. This function was
695
+ //! designed to make it easier to embed lookup tables where each index is a relative distance of two labels.
696
+ virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) = 0;
697
+
698
+ //! \}
699
+
700
+ //! \name Comment
701
+ //! \{
702
+
703
+ //! Emits a comment stored in `data` with an optional `size` parameter.
704
+ virtual Error comment(const char* data, size_t size = SIZE_MAX) = 0;
705
+
706
+ //! Emits a formatted comment specified by `fmt` and variable number of arguments.
707
+ ASMJIT_API Error commentf(const char* fmt, ...);
708
+ //! Emits a formatted comment specified by `fmt` and `ap`.
709
+ ASMJIT_API Error commentv(const char* fmt, va_list ap);
710
+
711
+ //! \}
712
+
713
+ //! \name Events
714
+ //! \{
715
+
716
+ //! Called after the emitter was attached to `CodeHolder`.
717
+ virtual Error onAttach(CodeHolder* ASMJIT_NONNULL(code)) noexcept = 0;
718
+ //! Called after the emitter was detached from `CodeHolder`.
719
+ virtual Error onDetach(CodeHolder* ASMJIT_NONNULL(code)) noexcept = 0;
720
+
721
+ //! Called when \ref CodeHolder has updated an important setting, which involves the following:
722
+ //!
723
+ //! - \ref Logger has been changed (\ref CodeHolder::setLogger() has been called).
724
+ //!
725
+ //! - \ref ErrorHandler has been changed (\ref CodeHolder::setErrorHandler() has been called).
726
+ //!
727
+ //! This function ensures that the settings are properly propagated from \ref CodeHolder to the emitter.
728
+ //!
729
+ //! \note This function is virtual and can be overridden, however, if you do so, always call \ref
730
+ //! BaseEmitter::onSettingsUpdated() within your own implementation to ensure that the emitter is
731
+ //! in a consistent state.
732
+ ASMJIT_API virtual void onSettingsUpdated() noexcept;
733
+
734
+ //! \}
735
+ };
736
+
737
+ //! \}
738
+
739
+ ASMJIT_END_NAMESPACE
740
+
741
+ #endif // ASMJIT_CORE_EMITTER_H_INCLUDED