From 432e70caf66669f3aa93b40e7655f8c0361a4306 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 20 Sep 2024 12:04:13 -0700 Subject: [PATCH] begin sketching out 'collections', which are the formal mechanism in the eval/eval-viz systems for visualizing synthetic structures/arrays/trees produced by the debugger, rather than ad-hocing / hardwiring the correct ev-block production for each kind of view - the views can still stay, but this is an important feature for other cases --- src/eval/eval.mdesk | 1 + src/eval/eval_types.c | 12 +- src/eval/generated/eval.meta.c | 6 +- src/eval/generated/eval.meta.h | 5 +- .../eval_visualization_builtin_view_rules.c | 6 +- .../eval_visualization_core.c | 18 +- .../eval_visualization_core.h | 11 +- src/raddbg/raddbg_core.c | 265 +++++++++++++++++- src/raddbg/raddbg_core.h | 4 + src/raddbg/raddbg_views.c | 17 +- 10 files changed, 301 insertions(+), 44 deletions(-) diff --git a/src/eval/eval.mdesk b/src/eval/eval.mdesk index 28c485ec..11a57186 100644 --- a/src/eval/eval.mdesk +++ b/src/eval/eval.mdesk @@ -71,6 +71,7 @@ E_TypeKindTable: {IncompleteEnum "enum" 0 } {Bitfield "" 0 } {Variadic "" 0 } + {Collection "" 0 } } @table(name op_kind precedence string op_pre op_sep op_pos) diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index ecdb645b..be722c7d 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -506,15 +506,18 @@ e_hash_from_type_key(E_TypeKey key) str8_serial_push_struct(scratch.arena, &strings, &type->byte_size); str8_serial_push_struct(scratch.arena, &strings, &type->count); str8_serial_push_struct(scratch.arena, &strings, &type->off); - U64 direct_hash = e_hash_from_type_key(type->direct_type_key); - U64 owner_hash = e_hash_from_type_key(type->direct_type_key); + String8 direct_type_string = e_type_string_from_key(scratch.arena, type->direct_type_key); + String8 owner_type_string = e_type_string_from_key(scratch.arena, type->owner_type_key); + U64 direct_hash = e_hash_from_string(5381, direct_type_string); + U64 owner_hash = e_hash_from_string(5381, owner_type_string); str8_serial_push_struct(scratch.arena, &strings, &direct_hash); str8_serial_push_struct(scratch.arena, &strings, &owner_hash); if(type->param_type_keys != 0) { for EachIndex(idx, type->count) { - U64 param_type_hash = e_hash_from_type_key(type->param_type_keys[idx]); + String8 param_type_string = e_type_string_from_key(scratch.arena, type->param_type_keys[idx]); + U64 param_type_hash = e_hash_from_string(5381, param_type_string); str8_serial_push_struct(scratch.arena, &strings, ¶m_type_hash); } } @@ -522,7 +525,8 @@ e_hash_from_type_key(E_TypeKey key) { for EachIndex(idx, type->count) { - U64 member_type_hash = e_hash_from_type_key(type->members[idx].type_key); + String8 member_type_string = e_type_string_from_key(scratch.arena, type->members[idx].type_key); + U64 member_type_hash = e_hash_from_string(5381, member_type_string); str8_serial_push_struct(scratch.arena, &strings, &type->members[idx].off); str8_serial_push_struct(scratch.arena, &strings, &member_type_hash); } diff --git a/src/eval/generated/eval.meta.c b/src/eval/generated/eval.meta.c index 8d376138..e484a225 100644 --- a/src/eval/generated/eval.meta.c +++ b/src/eval/generated/eval.meta.c @@ -127,7 +127,7 @@ E_OpInfo e_expr_kind_op_info_table[45] = { E_OpKind_Binary, 13, str8_lit_comp(""), str8_lit_comp("="), str8_lit_comp("Define") }, }; -U8 e_kind_basic_byte_size_table[55] = +U8 e_kind_basic_byte_size_table[56] = { 0, 0, @@ -184,9 +184,10 @@ U8 e_kind_basic_byte_size_table[55] = 0, 0, 0, +0, }; -String8 e_kind_basic_string_table[55] = +String8 e_kind_basic_string_table[56] = { str8_lit_comp(""), str8_lit_comp("void"), @@ -243,6 +244,7 @@ str8_lit_comp("class"), str8_lit_comp("enum"), str8_lit_comp(""), str8_lit_comp(""), +str8_lit_comp(""), }; C_LINKAGE_END diff --git a/src/eval/generated/eval.meta.h b/src/eval/generated/eval.meta.h index 44e07e9c..8bbb319a 100644 --- a/src/eval/generated/eval.meta.h +++ b/src/eval/generated/eval.meta.h @@ -74,6 +74,7 @@ E_TypeKind_IncompleteClass, E_TypeKind_IncompleteEnum, E_TypeKind_Bitfield, E_TypeKind_Variadic, +E_TypeKind_Collection, E_TypeKind_COUNT, E_TypeKind_FirstBasic = E_TypeKind_Void, E_TypeKind_LastBasic = E_TypeKind_ComplexF128, @@ -159,8 +160,8 @@ extern String8 e_token_kind_strings[6]; extern String8 e_expr_kind_strings[45]; extern String8 e_interpretation_code_display_strings[11]; extern E_OpInfo e_expr_kind_op_info_table[45]; -extern U8 e_kind_basic_byte_size_table[55]; -extern String8 e_kind_basic_string_table[55]; +extern U8 e_kind_basic_byte_size_table[56]; +extern String8 e_kind_basic_string_table[56]; C_LINKAGE_END diff --git a/src/eval_visualization/eval_visualization_builtin_view_rules.c b/src/eval_visualization/eval_visualization_builtin_view_rules.c index bda1f397..e279931c 100644 --- a/src/eval_visualization/eval_visualization_builtin_view_rules.c +++ b/src/eval_visualization/eval_visualization_builtin_view_rules.c @@ -165,7 +165,7 @@ EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(default) } // rjf: recurse for child - ev_append_expr_blocks__rec(arena, view, key, child->key, str8_zero(), child_expr, child_view_rules, depth, out); + ev_append_expr_blocks__rec(arena, view, filter, key, child->key, str8_zero(), child_expr, child_view_rules, depth, out); } ev_block_end(out, last_vb); } @@ -240,7 +240,7 @@ EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(default) } // rjf: recurse for child - ev_append_expr_blocks__rec(arena, view, key, child->key, str8_zero(), child_expr, child_view_rules, depth, out); + ev_append_expr_blocks__rec(arena, view, filter, key, child->key, str8_zero(), child_expr, child_view_rules, depth, out); } ev_block_end(out, last_vb); } @@ -272,7 +272,7 @@ EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(default) } // rjf: recurse for child - ev_append_expr_blocks__rec(arena, view, key, child_key, str8_zero(), child_expr, child_view_rules, depth, out); + ev_append_expr_blocks__rec(arena, view, filter, key, child_key, str8_zero(), child_expr, child_view_rules, depth, out); } scratch_end(scratch); diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index 61b75031..21df6c85 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -501,7 +501,6 @@ ev_block_begin(Arena *arena, EV_BlockKind kind, EV_Key parent_key, EV_Key key, S n->v.key = key; n->v.depth = depth; n->v.expr = &e_expr_nil; - n->v.expr_raw = &e_expr_nil; n->v.view_rules = &ev_nil_view_rule_list; return &n->v; } @@ -515,7 +514,6 @@ ev_block_split_and_continue(Arena *arena, EV_BlockList *list, EV_Block *split_bl EV_Block *continue_block = ev_block_begin(arena, split_block->kind, split_block->parent_key, split_block->key, split_block->depth); continue_block->string = split_block->string; continue_block->expr = split_block->expr; - continue_block->expr_raw = split_block->expr_raw; continue_block->visual_idx_range = continue_block->semantic_idx_range = r1u64(split_idx+1, total_count); continue_block->view_rules = split_block->view_rules; continue_block->members = split_block->members; @@ -536,7 +534,7 @@ ev_block_end(EV_BlockList *list, EV_Block *block) } internal void -ev_append_expr_blocks__rec(Arena *arena, EV_View *view, EV_Key parent_key, EV_Key key, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules, S32 depth, EV_BlockList *list_out) +ev_append_expr_blocks__rec(Arena *arena, EV_View *view, String8 filter, EV_Key parent_key, EV_Key key, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules, S32 depth, EV_BlockList *list_out) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); @@ -554,7 +552,6 @@ ev_append_expr_blocks__rec(Arena *arena, EV_View *view, EV_Key parent_key, EV_Ke EV_Block *block = ev_block_begin(arena, EV_BlockKind_Root, parent_key, key, depth); block->string = string; block->expr = expr; - block->expr_raw = expr_raw; block->view_rules = view_rules; block->visual_idx_range = r1u64(key.child_num-1, key.child_num+0); block->semantic_idx_range = r1u64(key.child_num-1, key.child_num+0); @@ -581,7 +578,7 @@ ev_append_expr_blocks__rec(Arena *arena, EV_View *view, EV_Key parent_key, EV_Ke //- rjf: do view rule children block generation, if we have an applicable view rule if(parent_is_expanded && block_prod_view_rule_info != &ev_nil_view_rule_info) { - block_prod_view_rule_info->block_prod(arena, view, parent_key, key, node, string, expr, view_rules, block_prod_view_rule_params, depth+1, list_out); + block_prod_view_rule_info->block_prod(arena, view, filter, parent_key, key, node, string, expr, view_rules, block_prod_view_rule_params, depth+1, list_out); } scratch_end(scratch); @@ -589,7 +586,7 @@ ev_append_expr_blocks__rec(Arena *arena, EV_View *view, EV_Key parent_key, EV_Ke } internal EV_BlockList -ev_block_list_from_view_expr_keys(Arena *arena, EV_View *view, EV_ViewRuleList *view_rules, String8 expr, EV_Key parent_key, EV_Key key) +ev_block_list_from_view_expr_keys(Arena *arena, EV_View *view, String8 filter, EV_ViewRuleList *view_rules, String8 expr, EV_Key parent_key, EV_Key key, S32 depth) { ProfBeginFunction(); EV_BlockList blocks = {0}; @@ -641,7 +638,7 @@ ev_block_list_from_view_expr_keys(Arena *arena, EV_View *view, EV_ViewRuleList * ev_view_rule_list_push_string(arena, view_rule_list, n->string); } ev_view_rule_list_push_string(arena, view_rule_list, view_rule_string); - ev_append_expr_blocks__rec(arena, view, parent_key, key, expr, parse.expr, view_rule_list, 0, &blocks); + ev_append_expr_blocks__rec(arena, view, filter, parent_key, key, expr, parse.expr, view_rule_list, depth, &blocks); } ProfEnd(); return blocks; @@ -951,7 +948,6 @@ ev_row_list_push_new(Arena *arena, EV_View *view, EV_WindowedRowList *rows, EV_B row->size_in_rows = 1; row->string = block->string; row->expr = expr_resolved; - row->expr_raw = expr; if(row->expr->kind == E_ExprKind_MemberAccess) { Temp scratch = scratch_begin(&arena, 1); @@ -1044,7 +1040,7 @@ ev_windowed_row_list_from_block_list(Arena *arena, EV_View *view, Rng1S64 visibl case EV_BlockKind_Null: case EV_BlockKind_Root: { - ev_row_list_push_new(arena, view, &list, block, block->key, block->expr_raw); + ev_row_list_push_new(arena, view, &list, block, block->key, block->expr); }break; ////////////////////////////// @@ -1067,9 +1063,7 @@ ev_windowed_row_list_from_block_list(Arena *arena, EV_View *view, Rng1S64 visibl for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1) { FZY_Item *item = &block->fzy_backing_items.v[idx]; - EV_Key parent_key = block->parent_key; - EV_Key key = block->key; - key.child_num = block->fzy_backing_items.v[idx].idx; + EV_Key key = ev_key_make(ev_hash_from_key(block->parent_key), block->fzy_backing_items.v[idx].idx); E_Expr *row_expr = ev_expr_from_block_index(arena, block, idx); ev_row_list_push_new(arena, view, &list, block, key, row_expr); }break; diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index f3e1d504..c47da3cb 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -109,7 +109,7 @@ typedef enum EV_BlockKind EV_BlockKind_EnumMembers, // members of enum EV_BlockKind_Elements, // elements of array EV_BlockKind_Canvas, // escape hatch for arbitrary UI - EV_BlockKind_DebugInfoTable, // block of filtered debug info table elements + EV_BlockKind_DebugInfoTable, // block of filtered debug info table elements EV_BlockKind_COUNT, } EV_BlockKind; @@ -126,7 +126,6 @@ struct EV_Block // rjf: evaluation info String8 string; E_Expr *expr; - E_Expr *expr_raw; // rjf: info about ranges that this block spans Rng1U64 visual_idx_range; @@ -173,7 +172,8 @@ struct EV_BlockArray #define EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(name) ev_view_rule_expr_resolution__##name #define EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_SIG(EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(name)) #define EV_VIEW_RULE_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, \ -EV_View *view, \ +EV_View *view, \ +String8 filter, \ EV_Key parent_key, \ EV_Key key, \ EV_ExpandNode *expand_node, \ @@ -285,7 +285,6 @@ struct EV_Row String8 string; E_Member *member; E_Expr *expr; - E_Expr *expr_raw; // rjf: view rule attachments EV_ViewRuleList *view_rules; @@ -374,8 +373,8 @@ internal E_Expr *ev_expr_from_expr_view_rules(Arena *arena, E_Expr *expr, EV_Vie internal EV_Block *ev_block_begin(Arena *arena, EV_BlockKind kind, EV_Key parent_key, EV_Key key, S32 depth); internal EV_Block *ev_block_split_and_continue(Arena *arena, EV_BlockList *list, EV_Block *split_block, U64 split_idx); internal void ev_block_end(EV_BlockList *list, EV_Block *block); -internal void ev_append_expr_blocks__rec(Arena *arena, EV_View *view, EV_Key parent_key, EV_Key key, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules, S32 depth, EV_BlockList *list_out); -internal EV_BlockList ev_block_list_from_view_expr_keys(Arena *arena, EV_View *view, EV_ViewRuleList *view_rules, String8 expr, EV_Key parent_key, EV_Key key); +internal void ev_append_expr_blocks__rec(Arena *arena, EV_View *view, String8 filter, EV_Key parent_key, EV_Key key, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules, S32 depth, EV_BlockList *list_out); +internal EV_BlockList ev_block_list_from_view_expr_keys(Arena *arena, EV_View *view, String8 filter, EV_ViewRuleList *view_rules, String8 expr, EV_Key parent_key, EV_Key key, S32 depth); internal void ev_block_list_concat__in_place(EV_BlockList *dst, EV_BlockList *to_push); //////////////////////////////// diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index eb51bdf2..4b2bfb16 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -5804,7 +5804,7 @@ rd_window_frame(RD_Window *ws) EV_View *ev_view = rd_ev_view_from_key(d_hash_from_string(ev_view_key_string)); EV_Key parent_key = ev_key_make(5381, 1); EV_Key key = ev_key_make(ev_hash_from_key(parent_key), 1); - EV_BlockList viz_blocks = ev_block_list_from_view_expr_keys(scratch.arena, ev_view, &top_level_view_rules, expr, parent_key, key); + EV_BlockList viz_blocks = ev_block_list_from_view_expr_keys(scratch.arena, ev_view, str8_zero(), &top_level_view_rules, expr, parent_key, key, 0); CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); U32 default_radix = (entity->kind == CTRL_EntityKind_Thread ? 16 : 10); EV_WindowedRowList viz_rows = ev_windowed_row_list_from_block_list(scratch.arena, ev_view, r1s64(0, 50), &viz_blocks); @@ -7851,6 +7851,213 @@ rd_window_frame(RD_Window *ws) //////////////////////////////// //~ rjf: Eval Visualization +EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(rd_collection_block_prod) +{ + ////////////////////////////// + //- rjf: locals + // + if(str8_match(string, str8_lit("locals"), 0)) + { + Temp scratch = scratch_begin(&arena, 1); + E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_parse_ctx->locals_map); + e_string2num_map_node_array_sort__in_place(&nodes); + EV_ViewRuleList top_level_view_rules = {0}; + for(U64 idx = 0; idx < nodes.count; idx += 1) + { + E_String2NumMapNode *n = nodes.v[idx]; + String8 root_expr_string = n->string; + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, root_expr_string); + if(matches.count == matches.needle_part_count) + { + EV_Key local_parent_key = key; + EV_Key local_key = ev_key_make(ev_hash_from_key(local_parent_key), idx+1); + EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(arena, view, str8_zero(), &top_level_view_rules, root_expr_string, local_parent_key, local_key, depth); + ev_block_list_concat__in_place(out, &root_blocks); + } + } + scratch_end(scratch); + } + + ////////////////////////////// + //- rjf: registers + // + else if(str8_match(string, str8_lit("registers"), 0)) + { + Temp scratch = scratch_begin(&arena, 1); + CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->thread); + Arch arch = thread->arch; + U64 reg_count = regs_reg_code_count_from_arch(arch); + String8 *reg_strings = regs_reg_code_string_table_from_arch(arch); + U64 alias_count = regs_alias_code_count_from_arch(arch); + String8 *alias_strings = regs_alias_code_string_table_from_arch(arch); + U64 num = 1; + EV_ViewRuleList top_level_view_rules = {0}; + ev_view_rule_list_push_string(arena, &top_level_view_rules, str8_lit("hex")); + for(U64 reg_idx = 1; reg_idx < reg_count; reg_idx += 1, num += 1) + { + String8 root_expr_string = push_str8f(arena, "reg:%S", reg_strings[reg_idx]); + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, root_expr_string); + if(matches.count == matches.needle_part_count) + { + EV_Key reg_parent_key = key; + EV_Key reg_key = ev_key_make(ev_hash_from_key(reg_parent_key), num); + EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(arena, view, str8_zero(), &top_level_view_rules, root_expr_string, reg_parent_key, reg_key, depth); + ev_block_list_concat__in_place(out, &root_blocks); + } + } + for(U64 alias_idx = 1; alias_idx < alias_count; alias_idx += 1, num += 1) + { + String8 root_expr_string = push_str8f(arena, "reg:%S", alias_strings[alias_idx]); + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, root_expr_string); + if(matches.count == matches.needle_part_count) + { + EV_Key reg_parent_key = ev_key_make(5381, 0); + EV_Key reg_key = ev_key_make(ev_hash_from_key(reg_parent_key), num); + EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(arena, view, str8_zero(), &top_level_view_rules, root_expr_string, reg_parent_key, reg_key, depth); + ev_block_list_concat__in_place(out, &root_blocks); + } + } + scratch_end(scratch); + } + + ////////////////////////////// + //- rjf: debug info tables + // + else if(str8_match(string, str8_lit("globals"), 0) || + str8_match(string, str8_lit("thread_locals"), 0) || + str8_match(string, str8_lit("types"), 0) || + str8_match(string, str8_lit("procedures"), 0)) + { + Temp scratch = scratch_begin(&arena, 1); + EV_ViewRuleList top_level_view_rules = {0}; + RDI_SectionKind fzy_target = (str8_match(string, str8_lit("globals"), 0) ? RDI_SectionKind_GlobalVariables : + str8_match(string, str8_lit("thread_locals"), 0) ? RDI_SectionKind_ThreadVariables : + str8_match(string, str8_lit("types"), 0) ? RDI_SectionKind_UDTs : + str8_match(string, str8_lit("procedures"), 0) ? RDI_SectionKind_Procedures : + RDI_SectionKind_NULL); + if(fzy_target != RDI_SectionKind_NULL) + { + U64 endt_us = os_now_microseconds()+200; + + //- rjf: unpack context + DI_KeyList dbgi_keys_list = d_push_active_dbgi_key_list(scratch.arena); + DI_KeyArray dbgi_keys = di_key_array_from_list(scratch.arena, &dbgi_keys_list); + U64 rdis_count = dbgi_keys.count; + RDI_Parsed **rdis = push_array(scratch.arena, RDI_Parsed *, rdis_count); + for(U64 idx = 0; idx < rdis_count; idx += 1) + { + rdis[idx] = di_rdi_from_key(rd_state->frame_di_scope, &dbgi_keys.v[idx], endt_us); + } + + //- rjf: calculate top-level keys, expand root-level, grab root expansion node + EV_ExpandNode *root_node = ev_expand_node_from_key(view, key); + + //- rjf: query all filtered items from dbgi searching system + U128 fuzzy_search_key = {rd_regs()->view.u64[0], rd_regs()->view.u64[1]}; + B32 items_stale = 0; + FZY_Params params = {fzy_target, dbgi_keys}; + FZY_ItemArray items = fzy_items_from_key_params_query(rd_state->frame_fzy_scope, fuzzy_search_key, ¶ms, filter, endt_us, &items_stale); + if(items_stale) + { + rd_request_frame(); + } + + //- rjf: gather unsorted child expansion keys + // + // Nodes are sorted in the underlying expansion tree data structure, but + // ONLY by THEIR ORDER IN THE UNDERLYING DEBUG INFO TABLE. This is + // because debug info watch rows use the DEBUG INFO TABLE INDEX to form + // their key - this provides more stable/predictable behavior as rows + // are reordered, filtered, and shuffled around, as the user filters. + // + // When we actually build viz blocks, however, we want to produce viz + // blocks BY THE ORDER OF SUB-EXPANSIONS IN THE FILTERED ITEM ARRAY + // SPACE, so that all of the expansions come out in the right order. + // + EV_Key *sub_expand_keys = 0; + U64 *sub_expand_item_idxs = 0; + U64 sub_expand_keys_count = 0; + { + for(EV_ExpandNode *child = root_node->first; child != 0; child = child->next) + { + sub_expand_keys_count += 1; + } + sub_expand_keys = push_array(scratch.arena, EV_Key, sub_expand_keys_count); + sub_expand_item_idxs = push_array(scratch.arena, U64, sub_expand_keys_count); + U64 idx = 0; + for(EV_ExpandNode *child = root_node->first; child != 0; child = child->next) + { + U64 item_num = fzy_item_num_from_array_element_idx__linear_search(&items, child->key.child_num); + if(item_num != 0) + { + sub_expand_keys[idx] = child->key; + sub_expand_item_idxs[idx] = item_num-1; + idx += 1; + } + else + { + sub_expand_keys_count -= 1; + } + } + } + + //- rjf: sort child expansion keys + { + for(U64 idx1 = 0; idx1 < sub_expand_keys_count; idx1 += 1) + { + U64 min_idx2 = 0; + U64 min_item_idx = sub_expand_item_idxs[idx1]; + for(U64 idx2 = idx1+1; idx2 < sub_expand_keys_count; idx2 += 1) + { + if(sub_expand_item_idxs[idx2] < min_item_idx) + { + min_idx2 = idx2; + min_item_idx = sub_expand_item_idxs[idx2]; + } + } + if(min_idx2 != 0) + { + Swap(EV_Key, sub_expand_keys[idx1], sub_expand_keys[min_idx2]); + Swap(U64, sub_expand_item_idxs[idx1], sub_expand_item_idxs[min_idx2]); + } + } + } + + //- rjf: build blocks for all table items, split by sorted sub-expansions + EV_Block *last_vb = ev_block_begin(arena, EV_BlockKind_DebugInfoTable, parent_key, key, depth); + { + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, items.count); + last_vb->fzy_target = fzy_target; + last_vb->fzy_backing_items = items; + } + for(U64 sub_expand_idx = 0; sub_expand_idx < sub_expand_keys_count; sub_expand_idx += 1) + { + FZY_Item *item = &items.v[sub_expand_item_idxs[sub_expand_idx]]; + E_Expr *child_expr = ev_expr_from_block_index(arena, last_vb, sub_expand_item_idxs[sub_expand_idx]); + + // rjf: form split: truncate & complete last block; begin next block + last_vb = ev_block_split_and_continue(arena, out, last_vb, sub_expand_item_idxs[sub_expand_idx]); + + // rjf: build child view rules + EV_ViewRuleList *child_view_rules = ev_view_rule_list_from_inheritance(arena, &top_level_view_rules); + { + String8 view_rule_string = ev_view_rule_from_key(view, sub_expand_keys[sub_expand_idx]); + if(view_rule_string.size != 0) + { + ev_view_rule_list_push_string(arena, child_view_rules, view_rule_string); + } + } + + // rjf: recurse for child + ev_append_expr_blocks__rec(arena, view, str8_zero(), key, sub_expand_keys[sub_expand_idx], str8_zero(), child_expr, child_view_rules, depth, out); + } + ev_block_end(out, last_vb); + } + scratch_end(scratch); + } + +} + internal EV_View * rd_ev_view_from_key(U64 key) { @@ -9929,7 +10136,6 @@ internal void rd_frame(void) { Temp scratch = scratch_begin(0, 0); - DI_Scope *di_scope = di_scope_open(); local_persist S32 depth = 0; log_scope_begin(); @@ -9950,6 +10156,11 @@ rd_frame(void) rd_state->hover_regs = push_array(rd_frame_arena(), RD_Regs, 1); rd_state->hover_regs_slot = RD_RegSlot_Null; } + if(depth == 0) + { + rd_state->frame_di_scope = di_scope_open(); + rd_state->frame_fzy_scope = fzy_scope_open(); + } ////////////////////////////// //- rjf: get events from the OS @@ -10208,7 +10419,7 @@ rd_frame(void) CTRL_Entity *m = n->v; DI_Key dbgi_key = ctrl_dbgi_key_from_module(m); eval_modules[eval_module_idx].arch = m->arch; - eval_modules[eval_module_idx].rdi = di_rdi_from_key(di_scope, &dbgi_key, 0); + eval_modules[eval_module_idx].rdi = di_rdi_from_key(rd_state->frame_di_scope, &dbgi_key, 0); eval_modules[eval_module_idx].vaddr_range = m->vaddr_range; eval_modules[eval_module_idx].space = rd_eval_space_from_ctrl_entity(ctrl_entity_ancestor_from_kind(m, CTRL_EntityKind_Process), RD_EvalSpaceKind_CtrlEntity); if(module == m) @@ -10227,7 +10438,7 @@ rd_frame(void) for(CTRL_EntityNode *n = all_modules.first; n != 0; n = n->next, idx += 1) { DI_Key dbgi_key = ctrl_dbgi_key_from_module(n->v); - rdis[idx] = di_rdi_from_key(di_scope, &dbgi_key, 0); + rdis[idx] = di_rdi_from_key(rd_state->frame_di_scope, &dbgi_key, 0); rdis_vaddr_ranges[idx] = n->v->vaddr_range; if(n->v == module) { @@ -10274,13 +10485,35 @@ rd_frame(void) //////////////////////////// //- rjf: build eval IR context // + E_TypeKey collection_type_key = e_type_key_cons(.kind = E_TypeKind_Collection, .name = str8_lit("collection")); + E_TypeKey meta_eval_type_key = e_type_key_cons_base(type(CTRL_MetaEval), str8_lit("entity")); E_IRCtx *ir_ctx = push_array(scratch.arena, E_IRCtx, 1); { - E_TypeKey meta_eval_type_key = e_type_key_cons_base(type(CTRL_MetaEval), str8_lit("RADDBG_Entity")); E_IRCtx *ctx = ir_ctx; ctx->macro_map = push_array(scratch.arena, E_String2ExprMap, 1); ctx->macro_map[0] = e_string2expr_map_make(scratch.arena, 512); + //- rjf: add macros for collections + { + String8 collection_names[] = + { + str8_lit_comp("locals"), + str8_lit_comp("registers"), + str8_lit_comp("globals"), + str8_lit_comp("thread_locals"), + str8_lit_comp("types"), + str8_lit_comp("procedures"), + }; + for EachElement(idx, collection_names) + { + E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, 0); + expr->space = e_space_make(RD_EvalSpaceKind_MetaCollection); + expr->mode = E_Mode_Null; + expr->type_key = collection_type_key; + e_string2expr_map_insert(scratch.arena, ctx->macro_map, collection_names[idx], expr); + } + } + //- rjf: add macros for all evallable debugger frontend entities { RD_EntityKind evallable_kinds[] = @@ -10379,6 +10612,17 @@ rd_frame(void) EV_ViewRuleInfoTable *view_rule_info_table = push_array(scratch.arena, EV_ViewRuleInfoTable, 1); { ev_view_rule_info_table_push_builtins(scratch.arena, view_rule_info_table); + + // rjf: collection view rule + { + EV_ViewRuleInfo info = {0}; + info.string = str8_lit("collection"); + info.flags = EV_ViewRuleInfoFlag_Expandable; + info.block_prod = EV_VIEW_RULE_BLOCK_PROD_FUNCTION_NAME(rd_collection_block_prod); + ev_view_rule_info_table_push(scratch.arena, view_rule_info_table, &info); + } + + // rjf: raddbg-layer view rules for EachEnumVal(RD_ViewRuleKind, k) { RD_ViewRuleInfo *src_info = &rd_view_rule_kind_info_table[k]; @@ -10400,6 +10644,7 @@ rd_frame(void) EV_AutoViewRuleTable *auto_view_rule_table = push_array(scratch.arena, EV_AutoViewRuleTable, 1); { ev_auto_view_rule_table_push_new(scratch.arena, auto_view_rule_table, e_type_key_cons_base(type(CTRL_MetaEvalFrameArray), str8_zero()), str8_lit("slice")); + ev_auto_view_rule_table_push_new(scratch.arena, auto_view_rule_table, collection_type_key, str8_lit("collection")); } ev_select_auto_view_rule_table(auto_view_rule_table); @@ -14752,6 +14997,14 @@ rd_frame(void) } } - di_scope_close(di_scope); + ////////////////////////////// + //- rjf: close scopes + // + if(depth == 0) + { + di_scope_close(rd_state->frame_di_scope); + fzy_scope_close(rd_state->frame_fzy_scope); + } + scratch_end(scratch); } diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 288f5b63..bcaad677 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -38,6 +38,7 @@ enum RD_EvalSpaceKind_CtrlEntity = E_SpaceKind_FirstUserDefined, RD_EvalSpaceKind_MetaEntity, RD_EvalSpaceKind_MetaCtrlEntity, + RD_EvalSpaceKind_MetaCollection, }; //////////////////////////////// @@ -789,6 +790,8 @@ struct RD_State // rjf: frame parameters F32 frame_dt; + DI_Scope *frame_di_scope; + FZY_Scope *frame_fzy_scope; // rjf: registers stack RD_RegsNode base_regs; @@ -1275,6 +1278,7 @@ internal void rd_window_frame(RD_Window *ws); //////////////////////////////// //~ rjf: Eval Visualization +EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(rd_collection_block_prod); internal EV_View *rd_ev_view_from_key(U64 key); internal F32 rd_append_value_strings_from_eval(Arena *arena, EV_StringFlags flags, U32 default_radix, FNT_Tag font, F32 font_size, F32 max_size, S32 depth, E_Eval eval, E_Member *member, EV_ViewRuleList *view_rules, String8List *out); internal String8 rd_value_string_from_eval(Arena *arena, EV_StringFlags flags, U32 default_radix, FNT_Tag font, F32 font_size, F32 max_size, E_Eval eval, E_Member *member, EV_ViewRuleList *view_rules); diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 99d8cbc1..0aeb9434 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -1040,7 +1040,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, B32 modifiable, U32 default_radix, R FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, expr_string); if(matches.count == matches.needle_part_count) { - EV_BlockList watch_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, &top_level_view_rules, expr_string, parent_key, key); + EV_BlockList watch_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, str8_zero(), &top_level_view_rules, expr_string, parent_key, key, 0); ev_block_list_concat__in_place(&blocks, &watch_blocks); } } @@ -1069,7 +1069,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, B32 modifiable, U32 default_radix, R if(matches.count == matches.needle_part_count) { String8 expr_string = push_str8f(scratch.arena, "$%I64u", bp->id); - EV_BlockList watch_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, &top_level_view_rules, expr_string, parent_key, key); + EV_BlockList watch_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, str8_zero(), &top_level_view_rules, expr_string, parent_key, key, 0); ev_block_list_concat__in_place(&blocks, &watch_blocks); } } @@ -1096,7 +1096,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, B32 modifiable, U32 default_radix, R if(matches.count == matches.needle_part_count) { String8 expr_string = push_str8f(scratch.arena, "$%I64u", wp->id); - EV_BlockList watch_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, &top_level_view_rules, expr_string, parent_key, key); + EV_BlockList watch_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, str8_zero(), &top_level_view_rules, expr_string, parent_key, key, 0); ev_block_list_concat__in_place(&blocks, &watch_blocks); } } @@ -1198,7 +1198,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, B32 modifiable, U32 default_radix, R { EV_Key parent_key = ev_key_make(5381, 0); EV_Key key = ev_key_make(ev_hash_from_key(parent_key), num); - EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, &top_level_view_rules, root_expr_string, parent_key, key); + EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, str8_zero(), &top_level_view_rules, root_expr_string, parent_key, key, 0); ev_block_list_concat__in_place(&blocks, &root_blocks); } } @@ -1210,7 +1210,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, B32 modifiable, U32 default_radix, R { EV_Key parent_key = ev_key_make(5381, 0); EV_Key key = ev_key_make(ev_hash_from_key(parent_key), num); - EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, &top_level_view_rules, root_expr_string, parent_key, key); + EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, str8_zero(), &top_level_view_rules, root_expr_string, parent_key, key, 0); ev_block_list_concat__in_place(&blocks, &root_blocks); } } @@ -1232,7 +1232,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, B32 modifiable, U32 default_radix, R { EV_Key parent_key = ev_key_make(5381, 0); EV_Key key = ev_key_make(ev_hash_from_key(parent_key), idx+1); - EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, &top_level_view_rules, root_expr_string, parent_key, key); + EV_BlockList root_blocks = ev_block_list_from_view_expr_keys(scratch.arena, eval_view, str8_zero(), &top_level_view_rules, root_expr_string, parent_key, key, 0); ev_block_list_concat__in_place(&blocks, &root_blocks); } } @@ -1362,7 +1362,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, B32 modifiable, U32 default_radix, R } // rjf: recurse for child - ev_append_expr_blocks__rec(scratch.arena, eval_view, parent_key, sub_expand_keys[sub_expand_idx], str8_zero(), child_expr, child_view_rules, 0, &blocks); + ev_append_expr_blocks__rec(scratch.arena, eval_view, str8_zero(), parent_key, sub_expand_keys[sub_expand_idx], str8_zero(), child_expr, child_view_rules, 0, &blocks); } ev_block_end(&blocks, last_vb); }break; @@ -2511,8 +2511,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, B32 modifiable, U32 default_radix, R cell_autocomp_flags = RD_AutoCompListerFlag_ViewRules; if(cell_pre_edit_string.size == 0) { - E_IRTreeAndType raw_irtree = e_irtree_and_type_from_expr(scratch.arena, row->expr_raw); - cell_ghost_text = ev_auto_view_rule_from_type_key(raw_irtree.type_key); + cell_ghost_text = ev_auto_view_rule_from_type_key(row_eval.type_key); } }break; case RD_WatchViewColumnKind_FrameSelection: