From ba7e37e84e95402234023877111a8f26d134e670 Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Sat, 1 Nov 2025 02:54:51 +0300 Subject: [PATCH] Added some upgrades to red-black tree generator --- src/l1/core/uint_segments.h | 38 +++- .../codegen/all_set_map_templ_util_inst.h | 9 + .../codegen/rb_tree_set_map_template_inst.h | 188 +++++++++++++----- src/l2/margaret/vulkan_memory_claire.h | 41 +++- src/l2/tests/data_structures/t0_2.c | 0 5 files changed, 210 insertions(+), 66 deletions(-) create mode 100644 src/l2/tests/data_structures/t0_2.c diff --git a/src/l1/core/uint_segments.h b/src/l1/core/uint_segments.h index 8e57260..12c23e4 100644 --- a/src/l1/core/uint_segments.h +++ b/src/l1/core/uint_segments.h @@ -8,22 +8,44 @@ typedef struct { U64 len; } U64Segment; -bool U64Segment_equal_U64Segment(const U64Segment* A, const U64Segment* B){ - return A->start == B->start && A->len == B->len; -} - -bool U64Segment_equal_by_start(const U64Segment* A, const U64Segment* B){ +bool U64Segment_equal_by_start(const U64Segment* A, const U64Segment* B) { return A->start == B->start; } -bool U64Segment_less_by_start(const U64Segment* A, const U64Segment* B){ +bool U64Segment_less_by_start(const U64Segment* A, const U64Segment* B) { return A->start < B->start; } -bool U64Segment_less_by_len_and_start(const U64Segment* A, const U64Segment* B){ +bool U64Segment_equal_U64Segment(const U64Segment* A, const U64Segment* B) { + return A->start == B->start && A->len == B->len; +} + +bool U64Segment_less_by_len_and_start(const U64Segment* A, const U64Segment* B) { if (A->len == B->len) return A->start < B->start; return A->len < B->len; } -#endif \ No newline at end of file +U64 U64Segment_get_length_resp_alignment(const U64Segment* self, U8 alignment_exp) { + if (self->start & ((1ull << alignment_exp) - 1)) { + U64 pad_left = (1ull << alignment_exp) - (self->start & ((1ull << alignment_exp) - 1)); + return self->len >= pad_left ? self->len - pad_left : 0; + } + return self->len; +} + +bool U64Segment_equal_U64Segment_resp_align(const U64Segment* A, const U64Segment* B, U8 alignment_exp) { + U64 len_A = U64Segment_get_length_resp_alignment(A, alignment_exp); + U64 len_B = U64Segment_get_length_resp_alignment(B, alignment_exp); + return len_A == len_B && A->start == B->start; +} + +bool U64Segment_less_by_len_and_start_resp_align(const U64Segment* A, const U64Segment* B, U8 alignment_exp) { + U64 len_A = U64Segment_get_length_resp_alignment(A, alignment_exp); + U64 len_B = U64Segment_get_length_resp_alignment(B, alignment_exp); + if (len_A == len_B) + return A->start < B->start; + return len_A < len_B; +} + +#endif diff --git a/src/l1_5/codegen/all_set_map_templ_util_inst.h b/src/l1_5/codegen/all_set_map_templ_util_inst.h index 6b2b0fa..c621e46 100644 --- a/src/l1_5/codegen/all_set_map_templ_util_inst.h +++ b/src/l1_5/codegen/all_set_map_templ_util_inst.h @@ -13,6 +13,11 @@ typedef struct { SpanU8 alternative_equal; SpanU8 alternative_less; SpanU8 alternative_comp_set_name_embed; + + /* GT. You probably want it to be a pointer or an integer parameter. + * Leave empty if you don't need guest data (GT = void) + * GT must be primitive */ + SpanU8 guest_data_T; } set_instantiation_op; void set_instantiation_op_fix(set_instantiation_op* self){ @@ -30,6 +35,10 @@ void set_instantiation_op_fix(set_instantiation_op* self){ )||( self->alternative_comp_set_name_embed.len != 0 && (self->alternative_less.len != 0 || self->alternative_equal.len != 0))); + if (self->guest_data_T.len > 0) { + assert(self->alternative_comp_set_name_embed.len > 0); + assert(self->alternative_equal.len > 0 && self->alternative_less.len > 0); + } } #endif diff --git a/src/l1_5/codegen/rb_tree_set_map_template_inst.h b/src/l1_5/codegen/rb_tree_set_map_template_inst.h index 4900119..4e6485f 100644 --- a/src/l1_5/codegen/rb_tree_set_map_template_inst.h +++ b/src/l1_5/codegen/rb_tree_set_map_template_inst.h @@ -5,47 +5,92 @@ /* When key is given by value into some method of Buff_RBTreeSet */ NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiation_op op){ + if (op.guest_data_T.len > 0) { + assert(op.alternative_equal.len > 0); + if (op.t_integer) + return VecU8_fmt("!%s(key, self->el.buf[cur - 1], self->guest)", op.alternative_equal); + return VecU8_fmt("!%s(&key, &self->el.buf[cur - 1], self->guest)", op.alternative_equal); + } + if (op.alternative_equal.len > 0) { + if (op.t_integer) + return VecU8_fmt("!%s(key, self->el.buf[cur - 1])", op.alternative_equal); + return VecU8_fmt("!%s(&key, &self->el.buf[cur - 1])", op.alternative_equal); + } if (op.t_integer) return VecU8_fmt("key != self->el.buf[cur - 1]"); - if (op.alternative_equal.len != 0) - return VecU8_fmt("!%s(&key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("!%s_equal_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); } /* When key is given by value into some method of Buff_RBTreeSet */ NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op op){ + if (op.guest_data_T.len > 0) { + assert(op.alternative_less.len > 0); + if (op.t_integer) + return VecU8_fmt("%s(key, self->el.buf[cur - 1], self->guest)", op.alternative_less); + return VecU8_fmt("%s(&key, &self->el.buf[cur - 1], self->guest)", op.alternative_less); + } + if (op.alternative_less.len > 0) { + if (op.t_integer) + return VecU8_fmt("%s(key, self->el.buf[cur - 1])", op.alternative_less); + return VecU8_fmt("%s(&key, &self->el.buf[cur - 1])", op.alternative_less); + } if (op.t_integer) return VecU8_fmt("key < self->el.buf[cur - 1]"); - if (op.alternative_less.len != 0) - return VecU8_fmt("%s(&key, &self->el.buf[cur - 1])", op.alternative_less); return VecU8_fmt("%s_less_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); } /* When key is given by ref into some method of Buff_RBTreeSet * Ofk when op.T is integer, argument is still taken by a value */ NODISCARD VecU8 codegen_rb_tree_set_key_ref_NOT_EQUAL_element(set_instantiation_op op){ + if (op.guest_data_T.len > 0) { + assert(op.alternative_equal.len > 0); + if (op.t_integer) + return VecU8_fmt("!%s(key, self->el.buf[cur - 1], self->guest)", op.alternative_equal); + return VecU8_fmt("!%s(key, &self->el.buf[cur - 1], self->guest)", op.alternative_equal); + } + if (op.alternative_equal.len > 0) { + if (op.t_integer) + return VecU8_fmt("!%s(key, self->el.buf[cur - 1])", op.alternative_equal); + return VecU8_fmt("!%s(key, &self->el.buf[cur - 1])", op.alternative_equal); + } if (op.t_integer) return VecU8_fmt("key != self->el.buf[cur - 1]"); - if (op.alternative_equal.len != 0) - return VecU8_fmt("!%s(key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("!%s_equal_%s(key, &self->el.buf[cur - 1])", op.T, op.T); } /* When key is given by a pointer into some method of Buff_RBTreeSet */ NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op op){ + if (op.guest_data_T.len > 0) { + assert(op.alternative_equal.len > 0); + if (op.t_integer) + return VecU8_fmt("%s(key, self->el.buf[cur - 1], self->guest)", op.alternative_equal); + return VecU8_fmt("%s(key, &self->el.buf[cur - 1], self->guest)", op.alternative_equal); + } + if (op.alternative_equal.len > 0) { + if (op.t_integer) + return VecU8_fmt("%s(key, self->el.buf[cur - 1])", op.alternative_equal); + return VecU8_fmt("%s(key, &self->el.buf[cur - 1])", op.alternative_equal); + } if (op.t_integer) return VecU8_fmt("key == self->el.buf[cur - 1]"); - if (op.alternative_equal.len != 0) - return VecU8_fmt("%s(key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("%s_equal_%s(ref, &self->el.buf[cur - 1])", op.T, op.T); } /* When key is given by a pointer into some method of Buff_RBTreeSet */ NODISCARD VecU8 codegen_rb_tree_set_key_ref_LESS_element(set_instantiation_op op){ + if (op.guest_data_T.len > 0) { + assert(op.alternative_less.len > 0); + if (op.t_integer) + return VecU8_fmt("%s(key, self->el.buf[cur - 1], self->guest)", op.alternative_less); + return VecU8_fmt("%s(key, &self->el.buf[cur - 1], self->guest)", op.alternative_less); + } + if (op.alternative_less.len > 0) { + if (op.t_integer) + return VecU8_fmt("%s(key, self->el.buf[cur - 1])", op.alternative_less); + return VecU8_fmt("%s(key, &self->el.buf[cur - 1])", op.alternative_less); + } if (op.t_integer) return VecU8_fmt("key < self->el.buf[cur - 1]"); - if (op.alternative_less.len != 0) - return VecU8_fmt("%s(key, &self->el.buf[cur - 1])", op.alternative_less); return VecU8_fmt("%s_less_%s(key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -190,38 +235,7 @@ void codegen_append_rb_tree_set_erase_kind_method( SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" SPACE "}\n" "%v" /* saving_prev */ - SPACE "U64 z = cur;\n" - SPACE "U64 y = (self->tree.buf[z].left == 0 || self->tree.buf[z].right == 0) ? z : RBTree_minimum_in_subtree(self->tree.buf, self->tree.buf[z].right);\n" - SPACE "U64 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].right;\n" - SPACE "assert(x != y && x != z);\n" - SPACE "U64 x_adopter = self->tree.buf[y].parent;\n" - SPACE "self->tree.buf[x].parent = x_adopter;\n" - SPACE "if (x_adopter == 0)\n" - SPACE SPACE "self->root = x;\n" - SPACE "else if (self->tree.buf[x_adopter].left == y)\n" - SPACE SPACE "self->tree.buf[x_adopter].left = x;\n" - SPACE "else\n" - SPACE SPACE "self->tree.buf[x_adopter].right = x;\n" - SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" - SPACE "if (z != y) {\n" - SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\n" - SPACE SPACE "if (x_adopter == z)\n" - SPACE SPACE SPACE "x_adopter = y;\n" - SPACE "}\n" - SPACE "U64 L = self->el.len;\n" - SPACE "if (L != z) {\n" - SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" - SPACE SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" - SPACE SPACE "if (L == x)\n" - SPACE SPACE SPACE "x = z;\n" - SPACE SPACE "else if (L == x_adopter) \n" - SPACE SPACE SPACE "x_adopter = z;\n" - SPACE "}\n" - SPACE "self->tree.buf[x].parent = x_adopter;\n" - SPACE "self->tree.len--;\n" - SPACE "self->el.len--;\n" - SPACE "if (y_org_clr == RBTree_black)\n" - SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" + SPACE "%s_empty_index_erase(self, cur);\n" /* set */ "%v" /* ret_found_case */ "}\n\n", RT, set, method_name, set, codegen_rb_tree_set_taking_ref_t_argument(op), @@ -229,6 +243,7 @@ void codegen_append_rb_tree_set_erase_kind_method( codegen_rb_tree_set_key_ref_EQUAL_element(op), codegen_rb_tree_set_key_ref_LESS_element(op), saving_prev, + set, ret_found_case )); } @@ -245,13 +260,37 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op "typedef struct {\n" SPACE "VecRBTreeNode tree;\n" SPACE "U64 root;\n" - SPACE "Vec%s el;\n" - "} %s;\n\n", op.T, set)); - + SPACE "Vec%s el;\n", + op.T)); + if (op.guest_data_T.len > 0) { + VecU8_append_vec(&res, VecU8_fmt(SPACE "%s guest;\n", op.guest_data_T)); + } VecU8_append_vec(&res, VecU8_fmt( - "NODISCARD %s %s_new() {\n" - SPACE "return (%s){.tree = VecRBTreeNode_new_zeroinit(1), .root = 0, .el = Vec%s_new()};\n" - "}\n\n", set, set, set, op.T)); + "} %s;\n\n", set)); + + if (op.guest_data_T.len > 0) { + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s %s_new(%s guest) {\n" /* set, set, op.guest_data_T */ + SPACE "return (%s){.tree = VecRBTreeNode_new_zeroinit(1), .root = 0, .el = Vec%s_new(), .guest = guest};\n" /* set, op.T */ + "}\n\n", set, set, set, op.T)); + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s %s_new_reserved(%s guest, size_t size) {\n" /* set, set, op.guest_data_T */ + SPACE "return (%s){.tree = (VecRBTreeNode){\n" + SPACE SPACE ".buf = (RBTreeNode*)safe_calloc(size + 1, sizeof(RBTreeNode)), .len = 1, .capacity = size + 1},\n" + SPACE SPACE ".root = 0, .el = Vec%s_new_reserved(size), .guest = guest};\n" /* set, op.T */ + "}\n\n", set, set, op.guest_data_T, set, op.T)); + } else { + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s %s_new() {\n" /* set, set */ + SPACE "return (%s){.tree = VecRBTreeNode_new_zeroinit(1), .root = 0, .el = Vec%s_new()};\n" /* set, op.T */ + "}\n\n", set, set, set, op.T)); + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s %s_new_reserved(size_t size) {\n" /* set, set */ + SPACE "return (%s){.tree = (VecRBTreeNode){\n" + SPACE SPACE ".buf = (RBTreeNode*)safe_calloc(size + 1, sizeof(RBTreeNode)), .len = 1, .capacity = size + 1},\n" + SPACE SPACE ".root = 0, .el = Vec%s_new_reserved(size)};\n" /* set, op.T */ + "}\n\n", set, set, set, op.T)); + } VecU8_append_vec(&res, VecU8_fmt( "void %s_drop(%s self) {\n" @@ -295,6 +334,46 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op op.T, codegen_rb_tree_set_some_t(op, cstr("old")))); } + /* Erasing time!!!! */ + + VecU8_append_vec(&res, VecU8_fmt( + "/* UNSAFE. Use when you dropped the symbol that is about to be deleted */\n" + "void %s_empty_index_erase(%s* self, U64 z) {\n" /* set, set */ + SPACE "assert(z != 0 && z < self->tree.len);\n" + SPACE "U64 y = (self->tree.buf[z].left == 0 || self->tree.buf[z].right == 0) ? z : RBTree_minimum_in_subtree(self->tree.buf, self->tree.buf[z].right);\n" + SPACE "U64 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].right;\n" + SPACE "assert(x != y && x != z);\n" + SPACE "U64 x_adopter = self->tree.buf[y].parent;\n" + SPACE "self->tree.buf[x].parent = x_adopter;\n" + SPACE "if (x_adopter == 0)\n" + SPACE SPACE "self->root = x;\n" + SPACE "else if (self->tree.buf[x_adopter].left == y)\n" + SPACE SPACE "self->tree.buf[x_adopter].left = x;\n" + SPACE "else\n" + SPACE SPACE "self->tree.buf[x_adopter].right = x;\n" + SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" + SPACE "if (z != y) {\n" + SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\n" + SPACE SPACE "if (x_adopter == z)\n" + SPACE SPACE SPACE "x_adopter = y;\n" + SPACE "}\n" + SPACE "U64 L = self->el.len;\n" + SPACE "if (L != z) {\n" + SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" + SPACE SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" + SPACE SPACE "if (L == x)\n" + SPACE SPACE SPACE "x = z;\n" + SPACE SPACE "else if (L == x_adopter) \n" + SPACE SPACE SPACE "x_adopter = z;\n" + SPACE "}\n" + SPACE "self->tree.buf[x].parent = x_adopter;\n" + SPACE "self->tree.len--;\n" + SPACE "self->el.len--;\n" + SPACE "if (y_org_clr == RBTree_black)\n" + SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" + "}\n\n", + set, set)); + codegen_append_rb_tree_set_erase_kind_method(&res, op, set, cstr("erase"), vcstr("bool"), vcstr("return false;\n"), op.t_primitive ? vcstr("") : VecU8_fmt("%s_drop(self->el.buf[cur - 1]);\n", op.T), @@ -309,6 +388,8 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op ); } + /* We erased enough */ + VecU8_append_vec(&res, VecU8_fmt( "U64 %s_find(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ SPACE "U64 cur = self->root;\n" @@ -350,10 +431,13 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op } VecU8_append_vec(&res, VecU8_fmt( - "NODISCARD %s %s_clone(const %s* self){\n" - SPACE "return (%s){.tree = VecRBTreeNode_clone(&self->tree), .root = self->root,\n" - SPACE SPACE "Vec%s_clone(&self->el)};\n" - "}\n\n", set, set, set, set, op.T)); + "NODISCARD %s %s_clone(const %s* self){\n" /* set, set, set */ + SPACE "return (%s){.tree = VecRBTreeNode_clone(&self->tree), .root = self->root,\n" /* set */ + SPACE SPACE ".el = Vec%s_clone(&self->el)%s};\n" /* op.T, whether to clone guest or no */ + "}\n\n", + set, set, set, + set, + op.T, op.guest_data_T.len > 0 ? cstr(", .guest = self->guest") : cstr(""))); VecU8_append_vec(&res, VecU8_fmt( "U64 %s_find_next(const %s* self, U64 x){\n" diff --git a/src/l2/margaret/vulkan_memory_claire.h b/src/l2/margaret/vulkan_memory_claire.h index b3e6645..d6eff6b 100644 --- a/src/l2/margaret/vulkan_memory_claire.h +++ b/src/l2/margaret/vulkan_memory_claire.h @@ -177,6 +177,8 @@ /* MargaretMemAllocator assumes that your application tolerates existence of several * 'quiet' time phases, when no frames are in flight and all you do is relocate and defragment your memory */ +/* ======== End of MargaretMemAllocator backend interface ======== */ + typedef struct { VkBufferUsageFlags usage_flags; VkMemoryPropertyFlags memory_properties; @@ -247,14 +249,10 @@ typedef struct { } MargaretMemAllocatorRequest; /* That is our guy! */ -typedef struct { - -} MargaretMemAllocator; +typedef struct MargaretMemAllocator MargaretMemAllocator; /* Vibe check */ -bool MargaretMemAllocator_request_needs_silence(MargaretMemAllocator* self, MargaretMemAllocatorRequest req){ - return false; -} +bool MargaretMemAllocator_request_needs_silence(MargaretMemAllocator* self, MargaretMemAllocatorRequest req); /* Appends copying commands into cmd_buff. It may append none. Defragmentation, device memory relocation * need copying commands, but buffer resize may also require copying. @@ -263,6 +261,37 @@ bool MargaretMemAllocator_request_needs_silence(MargaretMemAllocator* self, Marg * silence anyway, you can pass `silence=true`. * Returned value: true if some_commands were appended to cmd_buff and need to be executed before any further * actions with memory managed by Self would make any sense */ +bool MargaretMemAllocator_carry_out_request(MargaretMemAllocator* self, VkCommandBuffer cmd_buff, bool silence); + +// todo: add same shit for images in host visible buffer +char* MargaretMemAllocator_get_host_visible_buffer_ptr( + const MargaretMemAllocator* self, const MargaretMemAllocatorBufferPosition* pos); + +/* ======= End of MargaretMemAllocator client interface ======== */ + +#define MARGARET_ALLOC_LIMIT_ALIGNMENT_EXP 30 + +typedef struct { + +} MargaretMemAllocatorOneBlock; + +typedef struct { + +} MargaretMemAllocatorOneType; + +struct MargaretMemAllocator { + +}; + +bool MargaretMemAllocator_request_needs_silence(MargaretMemAllocator* self, MargaretMemAllocatorRequest req){ + return false; +} + bool MargaretMemAllocator_carry_out_request(MargaretMemAllocator* self, VkCommandBuffer cmd_buff, bool silence){ return false; } + +char* MargaretMemAllocator_get_host_visible_buffer_ptr( + const MargaretMemAllocator* self, const MargaretMemAllocatorBufferPosition* pos){ + return NULL; +} \ No newline at end of file diff --git a/src/l2/tests/data_structures/t0_2.c b/src/l2/tests/data_structures/t0_2.c new file mode 100644 index 0000000..e69de29