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,120 @@
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_ZONESTRING_H_INCLUDED
7
+ #define ASMJIT_CORE_ZONESTRING_H_INCLUDED
8
+
9
+ #include "../core/globals.h"
10
+ #include "../core/zone.h"
11
+
12
+ ASMJIT_BEGIN_NAMESPACE
13
+
14
+ //! \addtogroup asmjit_zone
15
+ //! \{
16
+
17
+ //! A helper class used by \ref ZoneString implementation.
18
+ struct ZoneStringBase {
19
+ union {
20
+ struct {
21
+ uint32_t _size;
22
+ char _embedded[sizeof(void*) * 2 - 4];
23
+ };
24
+ struct {
25
+ void* _dummy;
26
+ char* _external;
27
+ };
28
+ };
29
+
30
+ inline void reset() noexcept {
31
+ _dummy = nullptr;
32
+ _external = nullptr;
33
+ }
34
+
35
+ Error setData(Zone* zone, uint32_t maxEmbeddedSize, const char* str, size_t size) noexcept {
36
+ if (size == SIZE_MAX)
37
+ size = strlen(str);
38
+
39
+ if (size <= maxEmbeddedSize) {
40
+ memcpy(_embedded, str, size);
41
+ _embedded[size] = '\0';
42
+ }
43
+ else {
44
+ char* external = static_cast<char*>(zone->dup(str, size, true));
45
+ if (ASMJIT_UNLIKELY(!external))
46
+ return DebugUtils::errored(kErrorOutOfMemory);
47
+ _external = external;
48
+ }
49
+
50
+ _size = uint32_t(size);
51
+ return kErrorOk;
52
+ }
53
+ };
54
+
55
+ //! A string template that can be zone allocated.
56
+ //!
57
+ //! Helps with creating strings that can be either statically allocated if they are small, or externally allocated
58
+ //! in case their size exceeds the limit. The `N` represents the size of the whole `ZoneString` structure, based on
59
+ //! that size the maximum size of the internal buffer is determined.
60
+ template<size_t N>
61
+ class ZoneString {
62
+ public:
63
+ //! \name Constants
64
+ //! \{
65
+
66
+ enum : uint32_t {
67
+ kWholeSize = (N > sizeof(ZoneStringBase)) ? uint32_t(N) : uint32_t(sizeof(ZoneStringBase)),
68
+ kMaxEmbeddedSize = kWholeSize - 5
69
+ };
70
+
71
+ //! \}
72
+
73
+ //! \name Members
74
+ //! \{
75
+
76
+ union {
77
+ ZoneStringBase _base;
78
+ char _wholeData[kWholeSize];
79
+ };
80
+
81
+ //! \}
82
+
83
+ //! \name Construction & Destruction
84
+ //! \{
85
+
86
+ inline ZoneString() noexcept { reset(); }
87
+ inline void reset() noexcept { _base.reset(); }
88
+
89
+ //! \}
90
+
91
+ //! \name Accessors
92
+ //! \{
93
+
94
+ //! Tests whether the string is empty.
95
+ inline bool empty() const noexcept { return _base._size == 0; }
96
+
97
+ //! Returns the string data.
98
+ inline const char* data() const noexcept { return _base._size <= kMaxEmbeddedSize ? _base._embedded : _base._external; }
99
+ //! Returns the string size.
100
+ inline uint32_t size() const noexcept { return _base._size; }
101
+
102
+ //! Tests whether the string is embedded (e.g. no dynamically allocated).
103
+ inline bool isEmbedded() const noexcept { return _base._size <= kMaxEmbeddedSize; }
104
+
105
+ //! Copies a new `data` of the given `size` to the string.
106
+ //!
107
+ //! If the `size` exceeds the internal buffer the given `zone` will be used to duplicate the data, otherwise
108
+ //! the internal buffer will be used as a storage.
109
+ inline Error setData(Zone* zone, const char* data, size_t size) noexcept {
110
+ return _base.setData(zone, kMaxEmbeddedSize, data, size);
111
+ }
112
+
113
+ //! \}
114
+ };
115
+
116
+ //! \}
117
+
118
+ ASMJIT_END_NAMESPACE
119
+
120
+ #endif // ASMJIT_CORE_ZONESTRING_H_INCLUDED
@@ -0,0 +1,99 @@
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
+ #include "../core/api-build_p.h"
7
+ #include "../core/support.h"
8
+ #include "../core/zone.h"
9
+ #include "../core/zonetree.h"
10
+
11
+ ASMJIT_BEGIN_NAMESPACE
12
+
13
+ // ZoneTreeBase - Tests
14
+ // ====================
15
+
16
+ #if defined(ASMJIT_TEST)
17
+ template<typename NodeT>
18
+ struct ZoneRBUnit {
19
+ typedef ZoneTree<NodeT> Tree;
20
+
21
+ static void verifyTree(Tree& tree) noexcept {
22
+ EXPECT(checkHeight(static_cast<NodeT*>(tree._root)) > 0);
23
+ }
24
+
25
+ // Check whether the Red-Black tree is valid.
26
+ static int checkHeight(NodeT* node) noexcept {
27
+ if (!node) return 1;
28
+
29
+ NodeT* ln = node->left();
30
+ NodeT* rn = node->right();
31
+
32
+ // Invalid tree.
33
+ EXPECT(ln == nullptr || *ln < *node);
34
+ EXPECT(rn == nullptr || *rn > *node);
35
+
36
+ // Red violation.
37
+ EXPECT(!node->isRed() ||
38
+ (!ZoneTreeNode::_isValidRed(ln) && !ZoneTreeNode::_isValidRed(rn)));
39
+
40
+ // Black violation.
41
+ int lh = checkHeight(ln);
42
+ int rh = checkHeight(rn);
43
+ EXPECT(!lh || !rh || lh == rh);
44
+
45
+ // Only count black links.
46
+ return (lh && rh) ? lh + !node->isRed() : 0;
47
+ }
48
+ };
49
+
50
+ class MyRBNode : public ZoneTreeNodeT<MyRBNode> {
51
+ public:
52
+ ASMJIT_NONCOPYABLE(MyRBNode)
53
+
54
+ inline explicit MyRBNode(uint32_t key) noexcept
55
+ : _key(key) {}
56
+
57
+ inline bool operator<(const MyRBNode& other) const noexcept { return _key < other._key; }
58
+ inline bool operator>(const MyRBNode& other) const noexcept { return _key > other._key; }
59
+
60
+ inline bool operator<(uint32_t queryKey) const noexcept { return _key < queryKey; }
61
+ inline bool operator>(uint32_t queryKey) const noexcept { return _key > queryKey; }
62
+
63
+ uint32_t _key;
64
+ };
65
+
66
+ UNIT(zone_rbtree) {
67
+ uint32_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 10000;
68
+
69
+ Zone zone(4096);
70
+ ZoneTree<MyRBNode> rbTree;
71
+
72
+ uint32_t key;
73
+ INFO("Inserting %u elements to RBTree and validating each operation", unsigned(kCount));
74
+ for (key = 0; key < kCount; key++) {
75
+ rbTree.insert(zone.newT<MyRBNode>(key));
76
+ ZoneRBUnit<MyRBNode>::verifyTree(rbTree);
77
+ }
78
+
79
+ uint32_t count = kCount;
80
+ INFO("Removing %u elements from RBTree and validating each operation", unsigned(kCount));
81
+ do {
82
+ MyRBNode* node;
83
+
84
+ for (key = 0; key < count; key++) {
85
+ node = rbTree.get(key);
86
+ EXPECT(node != nullptr);
87
+ EXPECT(node->_key == key);
88
+ }
89
+
90
+ node = rbTree.get(--count);
91
+ rbTree.remove(node);
92
+ ZoneRBUnit<MyRBNode>::verifyTree(rbTree);
93
+ } while (count);
94
+
95
+ EXPECT(rbTree.empty());
96
+ }
97
+ #endif
98
+
99
+ ASMJIT_END_NAMESPACE
@@ -0,0 +1,380 @@
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_ZONETREE_H_INCLUDED
7
+ #define ASMJIT_CORE_ZONETREE_H_INCLUDED
8
+
9
+ #include "../core/support.h"
10
+
11
+ ASMJIT_BEGIN_NAMESPACE
12
+
13
+ //! \addtogroup asmjit_zone
14
+ //! \{
15
+
16
+ //! RB-Tree node.
17
+ //!
18
+ //! The color is stored in a least significant bit of the `left` node.
19
+ //!
20
+ //! WARNING: Always use accessors to access left and right children.
21
+ class ZoneTreeNode {
22
+ public:
23
+ ASMJIT_NONCOPYABLE(ZoneTreeNode)
24
+
25
+ //! \name Constants
26
+ //! \{
27
+
28
+ enum : uintptr_t {
29
+ kRedMask = 0x1,
30
+ kPtrMask = ~kRedMask
31
+ };
32
+
33
+ //! \}
34
+
35
+ //! \name Members
36
+ //! \{
37
+
38
+ uintptr_t _rbNodeData[2];
39
+
40
+ //! \}
41
+
42
+ //! \name Construction & Destruction
43
+ //! \{
44
+
45
+ inline ZoneTreeNode() noexcept
46
+ : _rbNodeData { 0, 0 } {}
47
+
48
+ //! \}
49
+
50
+ //! \name Accessors
51
+ //! \{
52
+
53
+ inline bool isRed() const noexcept { return static_cast<bool>(_rbNodeData[0] & kRedMask); }
54
+
55
+ inline bool hasChild(size_t i) const noexcept { return _rbNodeData[i] > kRedMask; }
56
+ inline bool hasLeft() const noexcept { return _rbNodeData[0] > kRedMask; }
57
+ inline bool hasRight() const noexcept { return _rbNodeData[1] != 0; }
58
+
59
+ template<typename T = ZoneTreeNode>
60
+ inline T* child(size_t i) const noexcept { return static_cast<T*>(_getChild(i)); }
61
+ template<typename T = ZoneTreeNode>
62
+ inline T* left() const noexcept { return static_cast<T*>(_getLeft()); }
63
+ template<typename T = ZoneTreeNode>
64
+ inline T* right() const noexcept { return static_cast<T*>(_getRight()); }
65
+
66
+ //! \}
67
+
68
+ //! \cond INTERNAL
69
+ //! \name Internal
70
+ //! \{
71
+
72
+ inline ZoneTreeNode* _getChild(size_t i) const noexcept { return (ZoneTreeNode*)(_rbNodeData[i] & kPtrMask); }
73
+ inline ZoneTreeNode* _getLeft() const noexcept { return (ZoneTreeNode*)(_rbNodeData[0] & kPtrMask); }
74
+ inline ZoneTreeNode* _getRight() const noexcept { return (ZoneTreeNode*)(_rbNodeData[1]); }
75
+
76
+ inline void _setChild(size_t i, ZoneTreeNode* node) noexcept { _rbNodeData[i] = (_rbNodeData[i] & kRedMask) | (uintptr_t)node; }
77
+ inline void _setLeft(ZoneTreeNode* node) noexcept { _rbNodeData[0] = (_rbNodeData[0] & kRedMask) | (uintptr_t)node; }
78
+ inline void _setRight(ZoneTreeNode* node) noexcept { _rbNodeData[1] = (uintptr_t)node; }
79
+
80
+ inline void _makeRed() noexcept { _rbNodeData[0] |= kRedMask; }
81
+ inline void _makeBlack() noexcept { _rbNodeData[0] &= kPtrMask; }
82
+
83
+ //! Tests whether the node is RED (RED node must be non-null and must have RED flag set).
84
+ static inline bool _isValidRed(ZoneTreeNode* node) noexcept { return node && node->isRed(); }
85
+
86
+ //! \}
87
+ //! \endcond
88
+ };
89
+
90
+ //! RB-Tree node casted to `NodeT`.
91
+ template<typename NodeT>
92
+ class ZoneTreeNodeT : public ZoneTreeNode {
93
+ public:
94
+ ASMJIT_NONCOPYABLE(ZoneTreeNodeT)
95
+
96
+ //! \name Construction & Destruction
97
+ //! \{
98
+
99
+ inline ZoneTreeNodeT() noexcept
100
+ : ZoneTreeNode() {}
101
+
102
+ //! \}
103
+
104
+ //! \name Accessors
105
+ //! \{
106
+
107
+ inline NodeT* child(size_t i) const noexcept { return static_cast<NodeT*>(_getChild(i)); }
108
+ inline NodeT* left() const noexcept { return static_cast<NodeT*>(_getLeft()); }
109
+ inline NodeT* right() const noexcept { return static_cast<NodeT*>(_getRight()); }
110
+
111
+ //! \}
112
+ };
113
+
114
+ //! RB-Tree.
115
+ template<typename NodeT>
116
+ class ZoneTree {
117
+ public:
118
+ ASMJIT_NONCOPYABLE(ZoneTree)
119
+
120
+ typedef NodeT Node;
121
+ NodeT* _root;
122
+
123
+ //! \name Construction & Destruction
124
+ //! \{
125
+
126
+ inline ZoneTree() noexcept
127
+ : _root(nullptr) {}
128
+
129
+ inline ZoneTree(ZoneTree&& other) noexcept
130
+ : _root(other._root) {}
131
+
132
+ inline void reset() noexcept { _root = nullptr; }
133
+
134
+ //! \}
135
+
136
+ //! \name Accessors
137
+ //! \{
138
+
139
+ inline bool empty() const noexcept { return _root == nullptr; }
140
+ inline NodeT* root() const noexcept { return static_cast<NodeT*>(_root); }
141
+
142
+ //! \}
143
+
144
+ //! \name Utilities
145
+ //! \{
146
+
147
+ inline void swap(ZoneTree& other) noexcept {
148
+ std::swap(_root, other._root);
149
+ }
150
+
151
+ template<typename CompareT = Support::Compare<Support::SortOrder::kAscending>>
152
+ void insert(NodeT* ASMJIT_NONNULL(node), const CompareT& cmp = CompareT()) noexcept {
153
+ // Node to insert must not contain garbage.
154
+ ASMJIT_ASSERT(!node->hasLeft());
155
+ ASMJIT_ASSERT(!node->hasRight());
156
+ ASMJIT_ASSERT(!node->isRed());
157
+
158
+ if (!_root) {
159
+ _root = node;
160
+ return;
161
+ }
162
+
163
+ ZoneTreeNode head; // False root node,
164
+ head._setRight(_root); // having root on the right.
165
+
166
+ ZoneTreeNode* g = nullptr; // Grandparent.
167
+ ZoneTreeNode* p = nullptr; // Parent.
168
+ ZoneTreeNode* t = &head; // Iterator.
169
+ ZoneTreeNode* q = _root; // Query.
170
+
171
+ size_t dir = 0; // Direction for accessing child nodes.
172
+ size_t last = 0; // Not needed to initialize, but makes some tools happy.
173
+
174
+ node->_makeRed(); // New nodes are always red and violations fixed appropriately.
175
+
176
+ // Search down the tree.
177
+ for (;;) {
178
+ if (!q) {
179
+ // Insert new node at the bottom.
180
+ q = node;
181
+ p->_setChild(dir, node);
182
+ }
183
+ else if (_isValidRed(q->_getLeft()) && _isValidRed(q->_getRight())) {
184
+ // Color flip.
185
+ q->_makeRed();
186
+ q->_getLeft()->_makeBlack();
187
+ q->_getRight()->_makeBlack();
188
+ }
189
+
190
+ // Fix red violation.
191
+ if (_isValidRed(q) && _isValidRed(p)) {
192
+ ASMJIT_ASSUME(g != nullptr);
193
+ ASMJIT_ASSUME(p != nullptr);
194
+ t->_setChild(t->_getRight() == g,
195
+ q == p->_getChild(last) ? _singleRotate(g, !last) : _doubleRotate(g, !last));
196
+ }
197
+
198
+ // Stop if found.
199
+ if (q == node)
200
+ break;
201
+
202
+ last = dir;
203
+ dir = cmp(*static_cast<NodeT*>(q), *static_cast<NodeT*>(node)) < 0;
204
+
205
+ // Update helpers.
206
+ if (g) t = g;
207
+
208
+ g = p;
209
+ p = q;
210
+ q = q->_getChild(dir);
211
+ }
212
+
213
+ // Update root and make it black.
214
+ _root = static_cast<NodeT*>(head._getRight());
215
+ _root->_makeBlack();
216
+ }
217
+
218
+ //! Remove node from RBTree.
219
+ template<typename CompareT = Support::Compare<Support::SortOrder::kAscending>>
220
+ void remove(ZoneTreeNode* ASMJIT_NONNULL(node), const CompareT& cmp = CompareT()) noexcept {
221
+ ZoneTreeNode head; // False root node,
222
+ head._setRight(_root); // having root on the right.
223
+
224
+ ZoneTreeNode* g = nullptr; // Grandparent.
225
+ ZoneTreeNode* p = nullptr; // Parent.
226
+ ZoneTreeNode* q = &head; // Query.
227
+
228
+ ZoneTreeNode* f = nullptr; // Found item.
229
+ ZoneTreeNode* gf = nullptr; // Found grandparent.
230
+ size_t dir = 1; // Direction (0 or 1).
231
+
232
+ // Search and push a red down.
233
+ while (q->hasChild(dir)) {
234
+ size_t last = dir;
235
+
236
+ // Update helpers.
237
+ g = p;
238
+ p = q;
239
+ q = q->_getChild(dir);
240
+ dir = cmp(*static_cast<NodeT*>(q), *static_cast<NodeT*>(node)) < 0;
241
+
242
+ // Save found node.
243
+ if (q == node) {
244
+ f = q;
245
+ gf = g;
246
+ }
247
+
248
+ // Push the red node down.
249
+ if (!_isValidRed(q) && !_isValidRed(q->_getChild(dir))) {
250
+ if (_isValidRed(q->_getChild(!dir))) {
251
+ ZoneTreeNode* child = _singleRotate(q, dir);
252
+ p->_setChild(last, child);
253
+ p = child;
254
+ }
255
+ else if (!_isValidRed(q->_getChild(!dir)) && p->_getChild(!last)) {
256
+ ZoneTreeNode* s = p->_getChild(!last);
257
+ if (!_isValidRed(s->_getChild(!last)) && !_isValidRed(s->_getChild(last))) {
258
+ // Color flip.
259
+ p->_makeBlack();
260
+ s->_makeRed();
261
+ q->_makeRed();
262
+ }
263
+ else {
264
+ ASMJIT_ASSUME(g != nullptr);
265
+ ASMJIT_ASSUME(s != nullptr);
266
+
267
+ size_t dir2 = g->_getRight() == p;
268
+ ZoneTreeNode* child = g->_getChild(dir2);
269
+
270
+ if (_isValidRed(s->_getChild(last))) {
271
+ child = _doubleRotate(p, last);
272
+ g->_setChild(dir2, child);
273
+ }
274
+ else if (_isValidRed(s->_getChild(!last))) {
275
+ child = _singleRotate(p, last);
276
+ g->_setChild(dir2, child);
277
+ }
278
+
279
+ // Ensure correct coloring.
280
+ q->_makeRed();
281
+ child->_makeRed();
282
+ child->_getLeft()->_makeBlack();
283
+ child->_getRight()->_makeBlack();
284
+ }
285
+ }
286
+ }
287
+ }
288
+
289
+ // Replace and remove.
290
+ ASMJIT_ASSERT(f != nullptr);
291
+ ASMJIT_ASSERT(f != &head);
292
+ ASMJIT_ASSERT(q != &head);
293
+
294
+ p->_setChild(p->_getRight() == q,
295
+ q->_getChild(q->_getLeft() == nullptr));
296
+
297
+ // NOTE: The original algorithm used a trick to just copy 'key/value' to `f` and mark `q` for deletion. But this
298
+ // is unacceptable here as we really want to destroy the passed `node`. So, we have to make sure that we have
299
+ // really removed `f` and not `q`.
300
+ if (f != q) {
301
+ ASMJIT_ASSERT(f != &head);
302
+ ASMJIT_ASSERT(f != gf);
303
+
304
+ ZoneTreeNode* n = gf ? gf : &head;
305
+ dir = (n == &head) ? 1 : cmp(*static_cast<NodeT*>(n), *static_cast<NodeT*>(node)) < 0;
306
+
307
+ for (;;) {
308
+ if (n->_getChild(dir) == f) {
309
+ n->_setChild(dir, q);
310
+ // RAW copy, including the color.
311
+ q->_rbNodeData[0] = f->_rbNodeData[0];
312
+ q->_rbNodeData[1] = f->_rbNodeData[1];
313
+ break;
314
+ }
315
+
316
+ n = n->_getChild(dir);
317
+
318
+ // Cannot be true as we know that it must reach `f` in few iterations.
319
+ ASMJIT_ASSERT(n != nullptr);
320
+ dir = cmp(*static_cast<NodeT*>(n), *static_cast<NodeT*>(node)) < 0;
321
+ }
322
+ }
323
+
324
+ // Update root and make it black.
325
+ _root = static_cast<NodeT*>(head._getRight());
326
+ if (_root) _root->_makeBlack();
327
+ }
328
+
329
+ template<typename KeyT, typename CompareT = Support::Compare<Support::SortOrder::kAscending>>
330
+ inline NodeT* get(const KeyT& key, const CompareT& cmp = CompareT()) const noexcept {
331
+ ZoneTreeNode* node = _root;
332
+ while (node) {
333
+ auto result = cmp(*static_cast<const NodeT*>(node), key);
334
+ if (result == 0) break;
335
+
336
+ // Go left or right depending on the `result`.
337
+ node = node->_getChild(result < 0);
338
+ }
339
+ return static_cast<NodeT*>(node);
340
+ }
341
+
342
+ //! \}
343
+
344
+ //! \cond INTERNAL
345
+ //! \name Internal
346
+ //! \{
347
+
348
+ static inline bool _isValidRed(ZoneTreeNode* node) noexcept { return ZoneTreeNode::_isValidRed(node); }
349
+
350
+ //! Single rotation.
351
+ static inline ZoneTreeNode* _singleRotate(ZoneTreeNode* ASMJIT_NONNULL(root), size_t dir) noexcept {
352
+ ZoneTreeNode* save = root->_getChild(!dir);
353
+ ASMJIT_ASSUME(save != nullptr);
354
+
355
+ ZoneTreeNode* saveChild = save->_getChild(dir);
356
+ root->_setChild(!dir, saveChild);
357
+ save->_setChild( dir, root);
358
+ root->_makeRed();
359
+ save->_makeBlack();
360
+ return save;
361
+ }
362
+
363
+ //! Double rotation.
364
+ static inline ZoneTreeNode* _doubleRotate(ZoneTreeNode* ASMJIT_NONNULL(root), size_t dir) noexcept {
365
+ ZoneTreeNode* child = root->_getChild(!dir);
366
+ ASMJIT_ASSUME(child != nullptr);
367
+
368
+ root->_setChild(!dir, _singleRotate(child, !dir));
369
+ return _singleRotate(root, dir);
370
+ }
371
+
372
+ //! \}
373
+ //! \endcond
374
+ };
375
+
376
+ //! \}
377
+
378
+ ASMJIT_END_NAMESPACE
379
+
380
+ #endif // ASMJIT_CORE_ZONETREE_H_INCLUDED