From 90c86dc812341a79225a80c54bcaf74bf5c7e4ff Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 4 Feb 2025 13:20:25 -0800 Subject: [PATCH] eval/eval-viz: pull out rules for mapping exprs/irtrees -> lookup/expansion rules; use this path in the single-line value string generator; eliminate old non-view-rulified string generation paths --- src/eval/eval_ir.c | 78 ++- src/eval/eval_ir.h | 23 +- .../eval_visualization_core.c | 111 ++-- .../eval_visualization_core.h | 15 + src/raddbg/raddbg_core.c | 553 +++++++++--------- src/raddbg/raddbg_views.c | 17 +- src/raddbg/raddbg_views.h | 6 +- 7 files changed, 455 insertions(+), 348 deletions(-) diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 099ea486..cfa03ed4 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -710,22 +710,26 @@ e_auto_hook_map_make(Arena *arena, U64 slots_count) } internal void -e_auto_hook_map_insert_new(Arena *arena, E_AutoHookMap *map, String8 pattern, String8 tag_expr_string) +e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params) { Temp scratch = scratch_begin(&arena, 1); - E_TokenArray tokens = e_token_array_from_text(scratch.arena, pattern); - E_Parse parse = e_parse_type_from_text_tokens(scratch.arena, pattern, &tokens); - E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, parse.expr); - E_TypeKey type_key = irtree.type_key; + E_TypeKey type_key = params->type_key; + if(params->type_pattern.size != 0) + { + E_TokenArray tokens = e_token_array_from_text(scratch.arena, params->type_pattern); + E_Parse parse = e_parse_type_from_text_tokens(scratch.arena, params->type_pattern, &tokens); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, parse.expr); + type_key = irtree.type_key; + } E_AutoHookNode *node = push_array(arena, E_AutoHookNode, 1); node->type_key = type_key; U8 pattern_split = '?'; - node->type_pattern_parts = str8_split(arena, pattern, &pattern_split, 1, 0); - node->tag_expr = e_parse_expr_from_text(arena, push_str8_copy(arena, tag_expr_string)); + node->type_pattern_parts = str8_split(arena, params->type_pattern, &pattern_split, 1, 0); + node->tag_expr = e_parse_expr_from_text(arena, push_str8_copy(arena, params->tag_expr_string)); if(!e_type_key_match(e_type_key_zero(), type_key)) { U64 hash = e_hash_from_string(5381, str8_struct(&type_key)); - U64 slot_idx = map->slots_count; + U64 slot_idx = hash%map->slots_count; SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next); } else @@ -2291,3 +2295,61 @@ e_irtree_and_type_from_expr__cached(E_Expr *expr) } return result; } + +//////////////////////////////// +//~ rjf: Expression & IR-Tree => Lookup Rule + +internal E_LookupRuleTagPair +e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree) +{ + E_LookupRuleTagPair result = {&e_lookup_rule__default, &e_expr_nil}; + { + // rjf: first try explicitly-stored tags + if(result.rule == &e_lookup_rule__default) + { + for(E_Expr *tag = expr->first_tag; tag != &e_expr_nil; tag = tag->next) + { + E_LookupRule *candidate = e_lookup_rule_from_string(tag->string); + if(candidate != &e_lookup_rule__nil) + { + result.rule = candidate; + result.tag = tag; + break; + } + } + } + + // rjf: next try implicit set name -> rule mapping + if(result.rule == &e_lookup_rule__default) + { + E_TypeKind type_kind = e_type_kind_from_key(irtree->type_key); + if(type_kind == E_TypeKind_Set) + { + E_Type *type = e_type_from_key__cached(irtree->type_key); + String8 name = type->name; + E_LookupRule *candidate = e_lookup_rule_from_string(name); + if(candidate != &e_lookup_rule__nil) + { + result.rule = candidate; + } + } + } + + // rjf: next try auto hook map + if(result.rule == &e_lookup_rule__default) + { + E_ExprList tags = e_auto_hook_tag_exprs_from_type_key__cached(irtree->type_key); + for(E_ExprNode *n = tags.first; n != 0; n = n->next) + { + E_LookupRule *candidate = e_lookup_rule_from_string(n->v->string); + if(candidate != &e_lookup_rule__nil) + { + result.rule = candidate; + result.tag = n->v; + break; + } + } + } + } + return result; +} diff --git a/src/eval/eval_ir.h b/src/eval/eval_ir.h index dbd901b9..0e26ed6e 100644 --- a/src/eval/eval_ir.h +++ b/src/eval/eval_ir.h @@ -135,6 +135,13 @@ struct E_LookupRuleMap U64 slots_count; }; +typedef struct E_LookupRuleTagPair E_LookupRuleTagPair; +struct E_LookupRuleTagPair +{ + E_LookupRule *rule; + E_Expr *tag; +}; + //////////////////////////////// //~ rjf: IR Generation Hooks @@ -201,6 +208,14 @@ struct E_AutoHookMap E_AutoHookNode *last_pattern; }; +typedef struct E_AutoHookParams E_AutoHookParams; +struct E_AutoHookParams +{ + E_TypeKey type_key; + String8 type_pattern; + String8 tag_expr_string; +}; + //////////////////////////////// //~ rjf: Used Tag Map Data Structure @@ -360,7 +375,8 @@ internal E_IRGenRule *e_irgen_rule_from_string(String8 string); //~ rjf: Auto Hooks internal E_AutoHookMap e_auto_hook_map_make(Arena *arena, U64 slots_count); -internal void e_auto_hook_map_insert_new(Arena *arena, E_AutoHookMap *map, String8 pattern, String8 tag_expr_string); +internal void e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params); +#define e_auto_hook_map_insert_new(arena, map, ...) e_auto_hook_map_insert_new_((arena), (map), &(E_AutoHookParams){.type_key = zero_struct, __VA_ARGS__}) internal E_ExprList e_auto_hook_tag_exprs_from_type_key(Arena *arena, E_TypeKey type_key); internal E_ExprList e_auto_hook_tag_exprs_from_type_key__cached(E_TypeKey type_key); @@ -408,4 +424,9 @@ internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist); internal E_IRTreeAndType e_irtree_and_type_from_expr__cached(E_Expr *expr); +//////////////////////////////// +//~ rjf: Expression & IR-Tree => Lookup Rule + +internal E_LookupRuleTagPair e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree); + #endif // EVAL_IR_H diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index ed606b9c..15e80648 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -504,51 +504,15 @@ ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 str // rjf: unpack expr E_IRTreeAndType expr_irtree = e_irtree_and_type_from_expr(scratch.arena, t->expr); - // rjf: get expansion view rule info - E_LookupRule *lookup_rule = &e_lookup_rule__default; - EV_ViewRuleInfo *expand_rule = default_expand_view_rule_info; - E_Expr *lookup_rule_tag = &e_expr_nil; - E_Expr *expand_rule_tag = &e_expr_nil; - for(E_Expr *tag = t->expr->first_tag; tag != &e_expr_nil; tag = tag->next) - { - E_LookupRule *lookup_rule_candidate = e_lookup_rule_from_string(tag->string); - EV_ViewRuleInfo *expand_rule_candidate = ev_view_rule_info_from_string(tag->string); - if(lookup_rule_candidate != &e_lookup_rule__nil) - { - lookup_rule = lookup_rule_candidate; - lookup_rule_tag = tag; - } - if(expand_rule_candidate != &ev_nil_view_rule_info) - { - expand_rule = expand_rule_candidate; - expand_rule_tag = tag; - } - } + // rjf: get expr's lookup rule + E_LookupRuleTagPair lookup_rule_and_tag = e_lookup_rule_tag_pair_from_expr_irtree(t->expr, &expr_irtree); + E_LookupRule *lookup_rule = lookup_rule_and_tag.rule; + E_Expr *lookup_rule_tag = lookup_rule_and_tag.tag; - // rjf: for set types, try to use the set's name to lookup rules, if we don't - // have any - if(lookup_rule == &e_lookup_rule__default || - expand_rule == default_expand_view_rule_info) - { - E_TypeKey expr_type_key = expr_irtree.type_key; - E_TypeKind expr_type_kind = e_type_kind_from_key(expr_type_key); - if(expr_type_kind == E_TypeKind_Set) - { - E_Type *expr_type = e_type_from_key__cached(expr_type_key); - if(lookup_rule == &e_lookup_rule__default) - { - lookup_rule = e_lookup_rule_from_string(expr_type->name); - } - if(expand_rule == default_expand_view_rule_info) - { - expand_rule = ev_view_rule_info_from_string(expr_type->name); - if(expand_rule == &ev_nil_view_rule_info) - { - expand_rule = default_expand_view_rule_info; - } - } - } - } + // rjf: get expr's expansion rule + EV_ExpandRuleTagPair expand_rule_and_tag = ev_expand_rule_tag_pair_from_expr_irtree(t->expr, &expr_irtree); + EV_ViewRuleInfo *expand_rule = expand_rule_and_tag.rule; + E_Expr *expand_rule_tag = expand_rule_and_tag.tag; // rjf: get top-level lookup/expansion info E_LookupInfo lookup_info = lookup_rule->info(arena, &expr_irtree, filter); @@ -1510,3 +1474,62 @@ ev_escaped_from_raw_string(Arena *arena, String8 raw) scratch_end(scratch); return result; } + +//////////////////////////////// +//~ rjf: Expression & IR-Tree => Expand Rule + +internal EV_ExpandRuleTagPair +ev_expand_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree) +{ + EV_ViewRuleInfo *default_expand_view_rule = ev_view_rule_info_from_string(str8_lit("default")); + EV_ExpandRuleTagPair result = {default_expand_view_rule, &e_expr_nil}; + { + // rjf: first try explicitly-stored tags + if(result.rule == default_expand_view_rule) + { + for(E_Expr *tag = expr->first_tag; tag != &e_expr_nil; tag = tag->next) + { + EV_ViewRuleInfo *candidate = ev_view_rule_info_from_string(tag->string); + if(candidate != &ev_nil_view_rule_info) + { + result.rule = candidate; + result.tag = tag; + break; + } + } + } + + // rjf: next try implicit set name -> rule mapping + if(result.rule == default_expand_view_rule) + { + E_TypeKind type_kind = e_type_kind_from_key(irtree->type_key); + if(type_kind == E_TypeKind_Set) + { + E_Type *type = e_type_from_key__cached(irtree->type_key); + String8 name = type->name; + EV_ViewRuleInfo *candidate = ev_view_rule_info_from_string(name); + if(candidate != &ev_nil_view_rule_info) + { + result.rule = candidate; + } + } + } + + // rjf: next try auto hook map + if(result.rule == default_expand_view_rule) + { + E_ExprList tags = e_auto_hook_tag_exprs_from_type_key__cached(irtree->type_key); + for(E_ExprNode *n = tags.first; n != 0; n = n->next) + { + EV_ViewRuleInfo *candidate = ev_view_rule_info_from_string(n->v->string); + if(candidate != &ev_nil_view_rule_info) + { + result.rule = candidate; + result.tag = n->v; + break; + } + } + } + } + return result; +} diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index e931cbcf..044dd6a1 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -128,6 +128,16 @@ struct EV_ViewRuleInfoTable U64 slots_count; }; +//////////////////////////////// +//~ rjf: Expansion Rule Types + +typedef struct EV_ExpandRuleTagPair EV_ExpandRuleTagPair; +struct EV_ExpandRuleTagPair +{ + EV_ViewRuleInfo *rule; + E_Expr *tag; +}; + //////////////////////////////// //~ rjf: Blocks @@ -368,4 +378,9 @@ internal String8 ev_string_from_hresult_code(U32 code); internal String8 ev_string_from_simple_typed_eval(Arena *arena, EV_StringFlags flags, U32 radix, U32 min_digits, E_Eval eval); internal String8 ev_escaped_from_raw_string(Arena *arena, String8 raw); +//////////////////////////////// +//~ rjf: Expression & IR-Tree => Expand Rule + +internal EV_ExpandRuleTagPair ev_expand_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree); + #endif // EVAL_VISUALIZATION_CORE_H diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index e5774a0a..82d1c93d 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -9327,242 +9327,283 @@ rd_append_value_strings_from_eval(Arena *arena, EV_StringFlags flags, U32 defaul } //- rjf: value/offset evaluations - else if(max_size > 0) switch(e_type_kind_from_key(e_type_unwrap(eval.type_key))) + else if(max_size > 0) { - //- rjf: default - leaf cases - default: + E_TypeKey type_key = e_type_unwrap(eval.type_key); + E_TypeKind kind = e_type_kind_from_key(type_key); + switch(kind) { - E_Eval value_eval = e_value_eval_from_eval(eval); - String8 string = ev_string_from_simple_typed_eval(arena, flags, radix, min_digits, value_eval); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string).x; - str8_list_push(arena, out, string); - }break; - - //- rjf: pointers - case E_TypeKind_Function: - case E_TypeKind_Ptr: - case E_TypeKind_LRef: - case E_TypeKind_RRef: - { - // rjf: unpack type info - E_TypeKind type_kind = e_type_kind_from_key(e_type_unwrap(eval.type_key)); - E_TypeKey direct_type_key = e_type_unwrap(e_type_ptee_from_key(e_type_unwrap(eval.type_key))); - E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - - // rjf: unpack info about pointer destination - E_Eval value_eval = e_value_eval_from_eval(eval); - B32 ptee_has_content = (direct_type_kind != E_TypeKind_Null && direct_type_kind != E_TypeKind_Void); - B32 ptee_has_string = ((E_TypeKind_Char8 <= direct_type_kind && direct_type_kind <= E_TypeKind_UChar32) || - direct_type_kind == E_TypeKind_S8 || - direct_type_kind == E_TypeKind_U8); - CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->thread); - CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); - String8 symbol_name = d_symbol_name_from_process_vaddr(arena, process, value_eval.value.u64, 1); - - // rjf: special case: push strings for textual string content - B32 did_content = 0; - B32 did_string = 0; - if(!did_content && ptee_has_string && !no_string) + //- rjf: default - leaf cases + default: { - did_content = 1; - did_string = 1; - U64 string_memory_addr = value_eval.value.u64; - U64 element_size = e_type_byte_size_from_key(direct_type_key); - U64 string_buffer_size = 256; - U8 *string_buffer = push_array(arena, U8, string_buffer_size); - for(U64 try_size = string_buffer_size; try_size >= 16; try_size /= 2) - { - B32 read_good = e_space_read(eval.space, string_buffer, r1u64(string_memory_addr, string_memory_addr+try_size)); - if(read_good) - { - break; - } - } - string_buffer[string_buffer_size-1] = 0; - String8 string = {0}; - switch(element_size) - { - default:{string = str8_cstring((char *)string_buffer);}break; - case 2: {string = str8_from_16(arena, str16_cstring((U16 *)string_buffer));}break; - case 4: {string = str8_from_32(arena, str32_cstring((U32 *)string_buffer));}break; - } - String8 string_escaped = ev_escaped_from_raw_string(arena, string); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string_escaped).x; - space_taken += 2*fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("\"")).x; - if(!no_addr || depth > 0) - { - str8_list_push(arena, out, str8_lit("\"")); - } - str8_list_push(arena, out, string_escaped); - if(!no_addr || depth > 0) - { - str8_list_push(arena, out, str8_lit("\"")); - } - } - - // rjf: special case: push strings for symbols - if(value_eval.value.u64 != 0 && - !did_content && symbol_name.size != 0 && - flags & EV_StringFlag_ReadOnlyDisplayRules && - ((type_kind == E_TypeKind_Ptr && direct_type_kind == E_TypeKind_Void) || - (type_kind == E_TypeKind_Ptr && direct_type_kind == E_TypeKind_Function) || - (type_kind == E_TypeKind_Function))) - { - did_content = 1; - str8_list_push(arena, out, symbol_name); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, symbol_name).x; - } - - // rjf: special case: need symbol name, don't have one - if(value_eval.value.u64 != 0 && - !did_content && symbol_name.size == 0 && - flags & EV_StringFlag_ReadOnlyDisplayRules && - ((type_kind == E_TypeKind_Ptr && direct_type_kind == E_TypeKind_Function) || - (type_kind == E_TypeKind_Function)) && - (flags & EV_StringFlag_ReadOnlyDisplayRules)) - { - did_content = 1; - String8 string = str8_lit("???"); - str8_list_push(arena, out, string); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string).x; - } - - // rjf: push pointer value - B32 did_ptr_value = 0; - if(!no_addr || value_eval.value.u64 == 0) - { - did_ptr_value = 1; - if(did_content) - { - String8 left_paren = str8_lit(" ("); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, left_paren).x; - str8_list_push(arena, out, left_paren); - } + E_Eval value_eval = e_value_eval_from_eval(eval); String8 string = ev_string_from_simple_typed_eval(arena, flags, radix, min_digits, value_eval); space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string).x; str8_list_push(arena, out, string); - if(did_content) - { - String8 right_paren = str8_lit(")"); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, right_paren).x; - str8_list_push(arena, out, right_paren); - } - } + }break; - // rjf: descend for all other cases - B32 did_arrow = 0; - if(value_eval.value.u64 != 0 && !did_content && ptee_has_content && (flags & EV_StringFlag_ReadOnlyDisplayRules)) + //- rjf: pointers + case E_TypeKind_Function: + case E_TypeKind_Ptr: + case E_TypeKind_LRef: + case E_TypeKind_RRef: { - if(did_ptr_value && !did_arrow) - { - did_arrow = 1; - String8 arrow = str8_lit(" -> "); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, arrow).x; - str8_list_push(arena, out, arrow); - } - did_content = 1; - if(depth < 4) - { - E_Expr *deref_expr = e_expr_ref_deref(scratch.arena, eval.expr); - E_Eval deref_eval = e_eval_from_expr(scratch.arena, deref_expr); - space_taken += rd_append_value_strings_from_eval(arena, flags, radix, font, font_size, max_size-space_taken, depth+1, deref_eval, out); - } - else - { - String8 ellipses = str8_lit("..."); - str8_list_push(arena, out, ellipses); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; - } - } - }break; - - //- rjf: arrays - case E_TypeKind_Array: - { - // rjf: unpack type info - E_Type *eval_type = e_type_from_key__cached(e_type_unwrap(eval.type_key)); - E_TypeKey direct_type_key = e_type_unwrap(eval_type->direct_type_key); - E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - U64 array_count = eval_type->count; - - // rjf: get pointed-at type - B32 array_is_string = ((E_TypeKind_Char8 <= direct_type_kind && direct_type_kind <= E_TypeKind_UChar32) || - direct_type_kind == E_TypeKind_S8 || - direct_type_kind == E_TypeKind_U8); - - // rjf: special case: push strings for textual string content - B32 did_content = 0; - if(!did_content && array_is_string && !no_string) - { - U64 element_size = e_type_byte_size_from_key(direct_type_key); - did_content = 1; - U64 string_buffer_size = Clamp(1, array_count, 1024); - U8 *string_buffer = push_array(arena, U8, string_buffer_size); - switch(eval.mode) - { - default:{}break; - case E_Mode_Offset: - { - U64 string_memory_addr = eval.value.u64; - B32 read_good = e_space_read(eval.space, string_buffer, r1u64(string_memory_addr, string_memory_addr+string_buffer_size)); - }break; - case E_Mode_Value: - { - MemoryCopy(string_buffer, &eval.value.u512[0], Min(string_buffer_size, sizeof(eval.value))); - }break; - } - String8 string = {0}; - switch(element_size) - { - default:{string = str8_cstring_capped(string_buffer, string_buffer + string_buffer_size);}break; - case 2: {string = str8_from_16(arena, str16_cstring_capped(string_buffer, string_buffer + string_buffer_size));}break; - case 4: {string = str8_from_32(arena, str32_cstring((U32 *)string_buffer));}break; - } - String8 string_escaped = ev_escaped_from_raw_string(arena, string); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string_escaped).x; - space_taken += 2*fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("\"")).x; - if(!no_addr || depth > 0) - { - str8_list_push(arena, out, str8_lit("\"")); - } - str8_list_push(arena, out, string_escaped); - if(!no_addr || depth > 0) - { - str8_list_push(arena, out, str8_lit("\"")); - } - } - - // rjf: descend in all other cases - if(!did_content && (flags & EV_StringFlag_ReadOnlyDisplayRules)) - { - did_content = 1; + // rjf: unpack type info + E_TypeKind type_kind = e_type_kind_from_key(e_type_unwrap(eval.type_key)); + E_TypeKey direct_type_key = e_type_unwrap(e_type_ptee_from_key(e_type_unwrap(eval.type_key))); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - // rjf: [ + // rjf: unpack info about pointer destination + E_Eval value_eval = e_value_eval_from_eval(eval); + B32 ptee_has_content = (direct_type_kind != E_TypeKind_Null && direct_type_kind != E_TypeKind_Void); + B32 ptee_has_string = ((E_TypeKind_Char8 <= direct_type_kind && direct_type_kind <= E_TypeKind_UChar32) || + direct_type_kind == E_TypeKind_S8 || + direct_type_kind == E_TypeKind_U8); + E_Space space = value_eval.space; + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); + CTRL_Entity *process = ctrl_process_from_entity(entity); + if(process == &ctrl_entity_nil) { - String8 bracket = str8_lit("["); - str8_list_push(arena, out, bracket); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, bracket).x; + process = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->process); + } + String8 symbol_name = d_symbol_name_from_process_vaddr(arena, process, value_eval.value.u64, 1); + + // rjf: special case: push strings for textual string content + B32 did_content = 0; + B32 did_string = 0; + if(!did_content && ptee_has_string && !no_string) + { + did_content = 1; + did_string = 1; + U64 string_memory_addr = value_eval.value.u64; + U64 element_size = e_type_byte_size_from_key(direct_type_key); + U64 string_buffer_size = 1024; + U8 *string_buffer = push_array(arena, U8, string_buffer_size); + for(U64 try_size = string_buffer_size; try_size >= 16; try_size /= 2) + { + B32 read_good = e_space_read(eval.space, string_buffer, r1u64(string_memory_addr, string_memory_addr+try_size)); + if(read_good) + { + break; + } + } + string_buffer[string_buffer_size-1] = 0; + String8 string = {0}; + switch(element_size) + { + default:{string = str8_cstring((char *)string_buffer);}break; + case 2: {string = str8_from_16(arena, str16_cstring((U16 *)string_buffer));}break; + case 4: {string = str8_from_32(arena, str32_cstring((U32 *)string_buffer));}break; + } + String8 string_escaped = ev_escaped_from_raw_string(arena, string); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string_escaped).x; + space_taken += 2*fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("\"")).x; + if(!no_addr || depth > 0) + { + str8_list_push(arena, out, str8_lit("\"")); + } + str8_list_push(arena, out, string_escaped); + if(!no_addr || depth > 0) + { + str8_list_push(arena, out, str8_lit("\"")); + } + } + + // rjf: special case: push strings for symbols + if(value_eval.value.u64 != 0 && + !did_content && symbol_name.size != 0 && + flags & EV_StringFlag_ReadOnlyDisplayRules && + ((type_kind == E_TypeKind_Ptr && direct_type_kind == E_TypeKind_Void) || + (type_kind == E_TypeKind_Ptr && direct_type_kind == E_TypeKind_Function) || + (type_kind == E_TypeKind_Function))) + { + did_content = 1; + str8_list_push(arena, out, symbol_name); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, symbol_name).x; + } + + // rjf: special case: need symbol name, don't have one + if(value_eval.value.u64 != 0 && + !did_content && symbol_name.size == 0 && + flags & EV_StringFlag_ReadOnlyDisplayRules && + ((type_kind == E_TypeKind_Ptr && direct_type_kind == E_TypeKind_Function) || + (type_kind == E_TypeKind_Function)) && + (flags & EV_StringFlag_ReadOnlyDisplayRules)) + { + did_content = 1; + String8 string = str8_lit("???"); + str8_list_push(arena, out, string); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string).x; + } + + // rjf: push pointer value + B32 did_ptr_value = 0; + if(!no_addr || value_eval.value.u64 == 0) + { + did_ptr_value = 1; + if(did_content) + { + String8 left_paren = str8_lit(" ("); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, left_paren).x; + str8_list_push(arena, out, left_paren); + } + String8 string = ev_string_from_simple_typed_eval(arena, flags, radix, min_digits, value_eval); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string).x; + str8_list_push(arena, out, string); + if(did_content) + { + String8 right_paren = str8_lit(")"); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, right_paren).x; + str8_list_push(arena, out, right_paren); + } + } + + // rjf: descend for all other cases + B32 did_arrow = 0; + if(value_eval.value.u64 != 0 && !did_content && ptee_has_content && (flags & EV_StringFlag_ReadOnlyDisplayRules)) + { + if(did_ptr_value && !did_arrow) + { + did_arrow = 1; + String8 arrow = str8_lit(" -> "); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, arrow).x; + str8_list_push(arena, out, arrow); + } + did_content = 1; + if(depth < 4) + { + E_Expr *deref_expr = e_expr_ref_deref(scratch.arena, eval.expr); + E_Eval deref_eval = e_eval_from_expr(scratch.arena, deref_expr); + space_taken += rd_append_value_strings_from_eval(arena, flags, radix, font, font_size, max_size-space_taken, depth+1, deref_eval, out); + } + else + { + String8 ellipses = str8_lit("..."); + str8_list_push(arena, out, ellipses); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; + } + } + }break; + + //- rjf: arrays + case E_TypeKind_Array: + { + // rjf: unpack type info + E_Type *eval_type = e_type_from_key__cached(e_type_unwrap(eval.type_key)); + E_TypeKey direct_type_key = e_type_unwrap(eval_type->direct_type_key); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); + U64 array_count = eval_type->count; + + // rjf: get pointed-at type + B32 array_is_string = ((E_TypeKind_Char8 <= direct_type_kind && direct_type_kind <= E_TypeKind_UChar32) || + direct_type_kind == E_TypeKind_S8 || + direct_type_kind == E_TypeKind_U8); + + // rjf: special case: push strings for textual string content + B32 did_content = 0; + if(!did_content && array_is_string && !no_string) + { + U64 element_size = e_type_byte_size_from_key(direct_type_key); + did_content = 1; + U64 string_buffer_size = Clamp(1, array_count, 1024); + U8 *string_buffer = push_array(arena, U8, string_buffer_size); + switch(eval.mode) + { + default:{}break; + case E_Mode_Offset: + { + U64 string_memory_addr = eval.value.u64; + B32 read_good = e_space_read(eval.space, string_buffer, r1u64(string_memory_addr, string_memory_addr+string_buffer_size)); + }break; + case E_Mode_Value: + { + MemoryCopy(string_buffer, &eval.value.u512[0], Min(string_buffer_size, sizeof(eval.value))); + }break; + } + String8 string = {0}; + switch(element_size) + { + default:{string = str8_cstring_capped(string_buffer, string_buffer + string_buffer_size);}break; + case 2: {string = str8_from_16(arena, str16_cstring_capped(string_buffer, string_buffer + string_buffer_size));}break; + case 4: {string = str8_from_32(arena, str32_cstring((U32 *)string_buffer));}break; + } + String8 string_escaped = ev_escaped_from_raw_string(arena, string); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string_escaped).x; + space_taken += 2*fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("\"")).x; + if(!no_addr || depth > 0) + { + str8_list_push(arena, out, str8_lit("\"")); + } + str8_list_push(arena, out, string_escaped); + if(!no_addr || depth > 0) + { + str8_list_push(arena, out, str8_lit("\"")); + } + } + + // rjf: if we did not do any special content, then go to the regular arrays/structs/sets case + if(!did_content) + { + goto arrays_and_sets_and_structs; + } + }break; + + //- rjf: non-string-arrays/structs/sets + case E_TypeKind_Struct: + case E_TypeKind_Union: + case E_TypeKind_Class: + case E_TypeKind_IncompleteStruct: + case E_TypeKind_IncompleteUnion: + case E_TypeKind_IncompleteClass: + case E_TypeKind_Set: + arrays_and_sets_and_structs: + { + String8 opener_string = str8_lit("{"); + String8 closer_string = str8_lit("}"); + if(kind == E_TypeKind_Array) + { + opener_string = str8_lit("["); + closer_string = str8_lit("]"); + } + + // rjf: opener ({, [) + { + str8_list_push(arena, out, opener_string); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, opener_string).x; } // rjf: build contents if(depth < 4) { - for(U64 idx = 0; idx < array_count && max_size > space_taken; idx += 1) + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, eval.expr); + E_LookupRuleTagPair lookup_rule_and_tag = e_lookup_rule_tag_pair_from_expr_irtree(eval.expr, &irtree); + E_LookupRule *lookup_rule = lookup_rule_and_tag.rule; + E_Expr *lookup_rule_tag = lookup_rule_and_tag.tag; + E_LookupInfo lookup_info = lookup_rule->info(arena, &irtree, str8_zero()); + U64 total_possible_child_count = Max(lookup_info.idxed_expr_count, lookup_info.named_expr_count); + B32 is_first = 1; + for(U64 idx = 0; idx < total_possible_child_count && max_size > space_taken; idx += 1) { - E_Expr *element_expr = e_expr_ref_array_index(scratch.arena, eval.expr, idx); - E_Eval element_eval = e_eval_from_expr(scratch.arena, element_expr); - space_taken += rd_append_value_strings_from_eval(arena, flags, radix, font, font_size, max_size-space_taken, depth+1, element_eval, out); - if(idx+1 < array_count) + E_Expr *expr = &e_expr_nil; + String8 expr_string = {0}; + lookup_rule->range(scratch.arena, eval.expr, r1u64(idx, idx+1), &expr, &expr_string, lookup_info.user_data); + if(expr != &e_expr_nil) { - String8 comma = str8_lit(", "); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, comma).x; - str8_list_push(arena, out, comma); - } - if(space_taken > max_size && idx+1 < array_count) - { - String8 ellipses = str8_lit("..."); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; - str8_list_push(arena, out, ellipses); + if(!is_first) + { + String8 comma = str8_lit(", "); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, comma).x; + str8_list_push(arena, out, comma); + } + is_first = 0; + E_Eval child_eval = e_eval_from_expr(scratch.arena, expr); + space_taken += rd_append_value_strings_from_eval(arena, flags, radix, font, font_size, max_size-space_taken, depth+1, child_eval, out); + if(space_taken > max_size && idx+1 < total_possible_child_count) + { + String8 ellipses = str8_lit(", ..."); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; + str8_list_push(arena, out, ellipses); + } } } } @@ -9573,75 +9614,13 @@ rd_append_value_strings_from_eval(Arena *arena, EV_StringFlags flags, U32 defaul space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; } - // rjf: ] + // rjf: closer (}, ]) { - String8 bracket = str8_lit("]"); - str8_list_push(arena, out, bracket); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, bracket).x; + str8_list_push(arena, out, closer_string); + space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, closer_string).x; } - } - }break; - - //- rjf: structs - case E_TypeKind_Struct: - case E_TypeKind_Union: - case E_TypeKind_Class: - case E_TypeKind_IncompleteStruct: - case E_TypeKind_IncompleteUnion: - case E_TypeKind_IncompleteClass: - { - ProfBegin("struct"); - - // rjf: open brace - { - String8 brace = str8_lit("{"); - str8_list_push(arena, out, brace); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, brace).x; - } - - // rjf: content - if(depth < 4) - { - E_MemberArray data_members = e_type_data_members_from_key__cached(e_type_unwrap(eval.type_key)); - for(U64 member_idx = 0; member_idx < data_members.count && max_size > space_taken; member_idx += 1) - { - E_Member *mem = &data_members.v[member_idx]; - ProfScope("member %.*s", str8_varg(mem->name)) - { - E_Expr *dot_expr = e_expr_ref_member_access(scratch.arena, eval.expr, mem->name); - E_Eval dot_eval = e_eval_from_expr(scratch.arena, dot_expr); - space_taken += rd_append_value_strings_from_eval(arena, flags, radix, font, font_size, max_size-space_taken, depth+1, dot_eval, out); - if(member_idx+1 < data_members.count) - { - String8 comma = str8_lit(", "); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, comma).x; - str8_list_push(arena, out, comma); - } - if(space_taken > max_size && member_idx+1 < data_members.count) - { - String8 ellipses = str8_lit("..."); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; - str8_list_push(arena, out, ellipses); - } - } - } - } - else - { - String8 ellipses = str8_lit("..."); - str8_list_push(arena, out, ellipses); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; - } - - // rjf: close brace - { - String8 brace = str8_lit("}"); - str8_list_push(arena, out, brace); - space_taken += fnt_dim_from_tag_size_string(font, font_size, 0, 0, brace).x; - } - - ProfEnd(); - }break; + }break; + } } scratch_end(scratch); @@ -12993,7 +12972,7 @@ rd_frame(void) e_string2expr_map_insert(scratch.arena, ctx->macro_map, str8_lit("current_module"), expr); } } - e_auto_hook_map_insert_new(scratch.arena, ctx->auto_hook_map, name, name); + e_auto_hook_map_insert_new(scratch.arena, ctx->auto_hook_map, .type_key = type_key, .tag_expr_string = name); } //- rjf: add macro for collections with specific lookup rules diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 79412bca..ec82da74 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -973,11 +973,11 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) } // rjf: fill row's cells - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .string = str8_lit("expression"), .pct = 0.25f); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .pct = 0.20f); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("typeof($expr)"), .pct = 0.15f); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("sizeof($expr)"), .pct = 0.15f); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .string = str8_lit("view_rule"), .pct = 0.25f); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .pct = 0.25f); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .pct = 0.35f); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("typeof($expr)"), .pct = 0.15f); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Tag, .pct = 0.25f); + // rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("sizeof($expr)"), .pct = 0.15f); di_scope_close(di_scope); scratch_end(scratch); @@ -1210,6 +1210,13 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, RD_WatchRowInfo *row_info scratch_end(scratch); }break; + + //- rjf: tag cells -> look up attached tag + case RD_WatchCellKind_Tag: + { + EV_View *ev_view = rd_view_eval_view(); + result.string = ev_view_rule_from_key(ev_view, row->key); + }break; } return result; } diff --git a/src/raddbg/raddbg_views.h b/src/raddbg/raddbg_views.h index 841045e1..f334c5ac 100644 --- a/src/raddbg/raddbg_views.h +++ b/src/raddbg/raddbg_views.h @@ -43,9 +43,9 @@ struct RD_CodeViewBuildResult typedef enum RD_WatchCellKind { - RD_WatchCellKind_String, // plain text - RD_WatchCellKind_Expr, // strings for forming expression, under some key; `expression` for expression, `view_rule` for view rule - RD_WatchCellKind_Eval, // an evaluation of the expression, with some optional modification - e.g. `$expr.some_member`, or `typeof($expr)~ + RD_WatchCellKind_Expr, // strings to represent expression itself + RD_WatchCellKind_Tag, // strings to represent attached tags at row-granularity + RD_WatchCellKind_Eval, // an evaluation of the expression, with some optional modification - e.g. `$expr.some_member`, or `typeof($expr)` } RD_WatchCellKind;