asmjit 0.2.0 → 0.2.1

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