From bb50e881410a5f72711c17f35077dce1df8cf588 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 10 Sep 2024 16:14:11 -0700 Subject: [PATCH] eval_visualization layer: builtin view rules, porting of more debug engine code over --- src/dbg_frontend/dbg_frontend_views.c | 2 - .../eval_visualization.mdesk | 30 ++ .../eval_visualization_builtin_view_rules.c | 374 ++++++++++++++++++ .../eval_visualization_builtin_view_rules.h | 17 + ...ualization.c => eval_visualization_core.c} | 103 +++++ ...ualization.h => eval_visualization_core.h} | 23 +- .../eval_visualization_inc.c | 5 + .../eval_visualization_inc.h | 10 + .../generated/eval_visualization.meta.c | 17 + .../generated/eval_visualization.meta.h | 24 ++ src/raddbg/raddbg_main.c | 4 +- 11 files changed, 601 insertions(+), 8 deletions(-) create mode 100644 src/eval_visualization/eval_visualization.mdesk create mode 100644 src/eval_visualization/eval_visualization_builtin_view_rules.c create mode 100644 src/eval_visualization/eval_visualization_builtin_view_rules.h rename src/eval_visualization/{eval_visualization.c => eval_visualization_core.c} (92%) rename src/eval_visualization/{eval_visualization.h => eval_visualization_core.h} (91%) create mode 100644 src/eval_visualization/eval_visualization_inc.c create mode 100644 src/eval_visualization/eval_visualization_inc.h create mode 100644 src/eval_visualization/generated/eval_visualization.meta.c create mode 100644 src/eval_visualization/generated/eval_visualization.meta.h diff --git a/src/dbg_frontend/dbg_frontend_views.c b/src/dbg_frontend/dbg_frontend_views.c index 32acb29d..befb589c 100644 --- a/src/dbg_frontend/dbg_frontend_views.c +++ b/src/dbg_frontend/dbg_frontend_views.c @@ -1009,8 +1009,6 @@ df_watch_view_build(DF_View *view, DF_WatchViewState *ewv, B32 modifiable, U32 d if(state_dirty) { MemoryZeroStruct(&blocks); - D_EvalViewKey eval_view_key = df_eval_view_key_from_eval_watch_view(ewv); - D_EvalView *eval_view = d_eval_view_from_key(eval_view_key); String8 filter = str8(view->query_buffer, view->query_string_size); RDI_SectionKind fzy_target = RDI_SectionKind_UDTs; switch(ewv->fill_kind) diff --git a/src/eval_visualization/eval_visualization.mdesk b/src/eval_visualization/eval_visualization.mdesk new file mode 100644 index 00000000..4b832d86 --- /dev/null +++ b/src/eval_visualization/eval_visualization.mdesk @@ -0,0 +1,30 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +@table(coverage_check name name_lower string ih ex xp vb display_name docs schema description) +EV_ViewRuleTable: +{ + {x Default default "default" - - - x "Default" - "" "" } + {x Array array "array" - - x - "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." } + {x Slice slice "slice" - - x - "Slice" x "" "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer." } + {x ByteSwap bswap "bswap" x - x - "Byte Swap" x "" "Specifies that all integral evaluations should be byte-swapped, such that their endianness is reversed." } + {x Cast cast "cast" - - x - "Cast" x "x:{type}" "Specifies that the expression to which the view rule is applied should be casted to the provided type." } +} + +@enum EV_ViewRuleKind: +{ + @expand(EV_ViewRuleTable a) `$(a.name)`, + COUNT, +} + +@gen +{ + @expand(EV_ViewRuleTable a) `$(a.xp == "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(" .. a.name_lower .. ");")`; + @expand(EV_ViewRuleTable a) `$(a.vb == "x" -> "EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(" .. a.name_lower .. ");")`; +} + +@data(EV_ViewRuleInfo) @c_file ev_builtin_view_rule_info_table: +{ + @expand(EV_ViewRuleTable a) + ```{str8_lit_comp("$(a.string)"), (EV_ViewRuleInfoFlag_Inherited*$(a.ih == "x"))|(EV_ViewRuleInfoFlag_Expandable*$(a.ex == "x"))|(EV_ViewRuleInfoFlag_ExprResolution*$(a.xp == "x"))|(EV_ViewRuleInfoFlag_VizBlockProd*$(a.vb == "x")), $(a.xp == "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME("..a.name_lower..")") $(a.xp != "x" -> 0), $(a.vb == "x" -> "EV_VIEW_RULE_BLOCK_PROD_FUNCTION_NAME("..a.name_lower..")") $(a.vb != "x" -> 0), }```; +} diff --git a/src/eval_visualization/eval_visualization_builtin_view_rules.c b/src/eval_visualization/eval_visualization_builtin_view_rules.c new file mode 100644 index 00000000..2379124c --- /dev/null +++ b/src/eval_visualization/eval_visualization_builtin_view_rules.c @@ -0,0 +1,374 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: View Rule Tree Info Extraction Helpers + +internal U64 +ev_base_offset_from_eval(E_Eval eval) +{ + if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(eval.type_key))) + { + eval = e_value_eval_from_eval(eval); + } + return eval.value.u64; +} + +internal E_Value +ev_value_from_params(MD_Node *params) +{ + Temp scratch = scratch_begin(0, 0); + String8 expr = md_string_from_children(scratch.arena, params); + E_Eval eval = e_eval_from_string(scratch.arena, expr); + E_Eval value_eval = e_value_eval_from_eval(eval); + scratch_end(scratch); + return value_eval.value; +} + +internal E_TypeKey +ev_type_key_from_params(MD_Node *params) +{ + Temp scratch = scratch_begin(0, 0); + String8 expr = md_string_from_children(scratch.arena, params); + E_TokenArray tokens = e_token_array_from_text(scratch.arena, expr); + E_Parse parse = e_parse_type_from_text_tokens(scratch.arena, expr, &tokens); + E_TypeKey type_key = e_type_from_expr(parse.expr); + scratch_end(scratch); + return type_key; +} + +internal E_Value +ev_value_from_params_key(MD_Node *params, String8 key) +{ + Temp scratch = scratch_begin(0, 0); + MD_Node *key_node = md_child_from_string(params, key, 0); + String8 expr = md_string_from_children(scratch.arena, key_node); + E_Eval eval = e_eval_from_string(scratch.arena, expr); + E_Eval value_eval = e_value_eval_from_eval(eval); + scratch_end(scratch); + return value_eval.value; +} + +internal Rng1U64 +ev_range_from_eval_params(E_Eval eval, MD_Node *params) +{ + Temp scratch = scratch_begin(0, 0); + U64 size = ev_value_from_params_key(params, str8_lit("size")).u64; + E_TypeKey type_key = e_type_unwrap(eval.type_key); + E_TypeKind type_kind = e_type_kind_from_key(type_key); + E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(eval.type_key)); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); + if(size == 0 && e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct || + direct_type_kind == E_TypeKind_Union || + direct_type_kind == E_TypeKind_Class || + direct_type_kind == E_TypeKind_Array)) + { + size = e_type_byte_size_from_key(e_type_direct_from_key(e_type_unwrap(eval.type_key))); + } + if(size == 0 && eval.mode == E_Mode_Offset && (type_kind == E_TypeKind_Struct || + type_kind == E_TypeKind_Union || + type_kind == E_TypeKind_Class || + type_kind == E_TypeKind_Array)) + { + size = e_type_byte_size_from_key(e_type_unwrap(eval.type_key)); + } + if(size == 0) + { + size = 16384; + } + Rng1U64 result = {0}; + result.min = ev_base_offset_from_eval(eval); + result.max = result.min + size; + scratch_end(scratch); + return result; +} + +internal Arch +ev_arch_from_eval_params(E_Eval eval, MD_Node *params) +{ + Arch arch = Arch_Null; + MD_Node *arch_node = md_child_from_string(params, str8_lit("arch"), 0); + String8 arch_kind_string = arch_node->first->string; + if(str8_match(arch_kind_string, str8_lit("x64"), StringMatchFlag_CaseInsensitive)) + { + arch = Arch_x64; + } + return arch; +} + +//////////////////////////////// +//~ rjf: default + +EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(default) +{ + Temp scratch = scratch_begin(&arena, 1); + + //////////////////////////// + //- rjf: unpack expression type info + // + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr); + E_TypeKey type_key = e_type_unwrap(irtree.type_key); + E_TypeKind type_kind = e_type_kind_from_key(type_key); + E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(type_key)); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); + + //////////////////////////// + //- rjf: do struct/union/class member block generation + // + if((type_kind == E_TypeKind_Struct || + type_kind == E_TypeKind_Union || + type_kind == E_TypeKind_Class) || + (e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct || + direct_type_kind == E_TypeKind_Union || + direct_type_kind == E_TypeKind_Class))) + { + // rjf: type -> filtered data members + E_MemberArray data_members = e_type_data_members_from_key(arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key); + + // rjf: build blocks for all members, split by sub-expansions + EV_Block *last_vb = ev_block_begin(arena, EV_BlockKind_Members, key, ev_key_make(ev_hash_from_key(key), 0), depth); + { + last_vb->expr = expr; + last_vb->view_rules = view_rules; + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, data_members.count); + last_vb->members = data_members; + } + for(EV_ExpandNode *child = expand_node->first; child != 0; child = child->next) + { + // rjf: unpack expansion info; skip out-of-bounds splits + U64 child_num = child->key.child_num; + U64 child_idx = child_num-1; + E_Expr *child_expr = ev_expr_from_block_index(arena, last_vb, child_idx); + if(child_idx >= last_vb->semantic_idx_range.max) + { + continue; + } + + // rjf: form split: truncate & complete last block; begin next block + last_vb = ev_block_split_and_continue(arena, out, last_vb, child_idx); + + // rjf: build child view rules + EV_ViewRuleList *child_view_rules = ev_view_rule_list_from_inheritance(arena, view_rules); + { + String8 view_rule_string = ev_view_rule_from_key(view, child->key); + 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, key, child->key, str8_zero(), child_expr, child_view_rules, depth, out); + } + ev_block_end(out, last_vb); + } + + //////////////////////////// + //- rjf: do enum member block generation + // + // (just a single block for all enum members; enum members can never be expanded) + // + else if(type_kind == E_TypeKind_Enum || + (e_type_kind_is_pointer_or_ref(type_kind) && direct_type_kind == E_TypeKind_Enum)) + { + E_Type *type = e_type_from_key(arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key); + EV_Block *last_vb = ev_block_begin(arena, EV_BlockKind_EnumMembers, key, ev_key_make(ev_hash_from_key(key), 0), depth); + { + last_vb->expr = expr; + last_vb->view_rules = view_rules; + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, type->count); + last_vb->enum_vals.v = type->enum_vals; + last_vb->enum_vals.count = type->count; + } + ev_block_end(out, last_vb); + } + + //////////////////////////// + //- rjf: do array element block generation + // + else if(type_kind == E_TypeKind_Array || + (e_type_kind_is_pointer_or_ref(type_kind) && direct_type_kind == E_TypeKind_Array)) + { + // rjf: unpack array type info + E_Type *array_type = e_type_from_key(scratch.arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key); + U64 array_count = array_type->count; + B32 need_extra_deref = e_type_kind_is_pointer_or_ref(type_kind); + + // rjf: build blocks for all elements, split by sub-expansions + EV_Block *last_vb = ev_block_begin(arena, EV_BlockKind_Elements, key, ev_key_make(ev_hash_from_key(key), 0), depth); + { + last_vb->expr = need_extra_deref ? e_expr_ref_deref(arena, expr) : expr; + last_vb->view_rules = view_rules; + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, array_count); + } + for(EV_ExpandNode *child = expand_node->first; child != 0; child = child->next) + { + // rjf: unpack expansion info; skip out-of-bounds splits + U64 child_num = child->key.child_num; + U64 child_idx = child_num-1; + E_Expr *child_expr = ev_expr_from_block_index(arena, last_vb, child_idx); + if(child_idx >= last_vb->semantic_idx_range.max) + { + continue; + } + + // rjf: form split: truncate & complete last block; begin next block + last_vb = ev_block_split_and_continue(arena, out, last_vb, child_idx); + + // rjf: build child view rules + EV_ViewRuleList *child_view_rules = ev_view_rule_list_from_inheritance(arena, view_rules); + { + String8 view_rule_string = ev_view_rule_from_key(view, child->key); + 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, key, child->key, str8_zero(), child_expr, child_view_rules, depth, out); + } + ev_block_end(out, last_vb); + } + + //////////////////////////// + //- rjf: do pointer-to-pointer block generation + // + else if(e_type_kind_is_pointer_or_ref(type_kind) && e_type_kind_is_pointer_or_ref(direct_type_kind)) + { + // rjf: compute key + EV_Key child_key = ev_key_make(ev_hash_from_key(key), 1); + + // rjf: build child view rules + EV_ViewRuleList *child_view_rules = ev_view_rule_list_from_inheritance(arena, view_rules); + { + String8 view_rule_string = ev_view_rule_from_key(view, child_key); + if(view_rule_string.size != 0) + { + ev_view_rule_list_push_string(arena, child_view_rules, view_rule_string); + } + } + + // rjf: recurse for child + E_Expr *child_expr = e_expr_ref_deref(arena, expr); + ev_append_expr_blocks__rec(arena, view, key, child_key, str8_zero(), child_expr, child_view_rules, depth, out); + } + + scratch_end(scratch); +} + +//////////////////////////////// +//~ rjf: "array" + +EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(array) +{ + Temp scratch = scratch_begin(&arena, 1); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr); + E_TypeKey type_key = irtree.type_key; + E_TypeKind type_kind = e_type_kind_from_key(type_key); + if(e_type_kind_is_pointer_or_ref(type_kind)) + { + E_Value count = ev_value_from_params(params); + E_TypeKey element_type_key = e_type_ptee_from_key(type_key); + E_TypeKey array_type_key = e_type_key_cons_array(element_type_key, count.u64); + E_TypeKey ptr_type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, array_type_key); + expr = e_expr_ref_cast(arena, ptr_type_key, expr); + } + scratch_end(scratch); + return expr; +} + +//////////////////////////////// +//~ rjf: "slice" + +EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(slice) +{ + Temp scratch = scratch_begin(&arena, 1); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr); + E_TypeKind type_kind = e_type_kind_from_key(irtree.type_key); + if(type_kind == E_TypeKind_Struct || type_kind == E_TypeKind_Class) + { + // rjf: unpack members + E_MemberArray members = e_type_data_members_from_key(scratch.arena, irtree.type_key); + + // rjf: choose base pointer & count members + E_Member *base_ptr_member = 0; + E_Member *count_member = 0; + for(U64 idx = 0; idx < members.count; idx += 1) + { + E_Member *member = &members.v[idx]; + E_TypeKey member_type = e_type_unwrap(member->type_key); + E_TypeKind member_type_kind = e_type_kind_from_key(member_type); + if(count_member == 0 && e_type_kind_is_integer(member_type_kind)) + { + count_member = member; + } + if(base_ptr_member == 0 && e_type_kind_is_pointer_or_ref(member_type_kind)) + { + base_ptr_member = &members.v[idx]; + } + if(count_member != 0 && base_ptr_member != 0) + { + break; + } + } + + // rjf: evaluate count member, determine count + U64 count = 0; + if(count_member != 0) + { + E_Expr *count_member_expr = e_expr_ref_member_access(scratch.arena, expr, count_member->name); + E_Eval count_member_eval = e_eval_from_expr(scratch.arena, count_member_expr); + E_Eval count_member_value_eval = e_value_eval_from_eval(count_member_eval); + count = count_member_value_eval.value.u64; + } + + // rjf: generate new struct slice type + E_TypeKey slice_type_key = zero_struct; + if(base_ptr_member != 0 && count_member != 0) + { + String8 struct_name = e_type_string_from_key(scratch.arena, irtree.type_key); + E_TypeKey element_type_key = e_type_ptee_from_key(base_ptr_member->type_key); + E_TypeKey array_type_key = e_type_key_cons_array(element_type_key, count); + E_TypeKey sized_base_ptr_type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, array_type_key); + E_MemberList slice_type_members = {0}; + e_member_list_push(scratch.arena, &slice_type_members, count_member); + e_member_list_push(scratch.arena, &slice_type_members, &(E_Member){.kind = E_MemberKind_DataField, .type_key = sized_base_ptr_type_key, .name = base_ptr_member->name, .off = base_ptr_member->off}); + E_MemberArray slice_type_members_array = e_member_array_from_list(scratch.arena, &slice_type_members); + slice_type_key = e_type_key_cons(.arch = e_type_state->ctx->primary_module->arch, + .kind = E_TypeKind_Struct, + .name = struct_name, + .members = slice_type_members_array.v, + .count = slice_type_members_array.count); + } + + // rjf: generate new expression tree - addr of struct, cast-to-ptr, deref + if(base_ptr_member != 0 && count_member != 0) + { + expr = e_expr_ref_addr(arena, expr); + expr = e_expr_ref_cast(arena, e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, slice_type_key), expr); + expr = e_expr_ref_deref(arena, expr); + } + } + scratch_end(scratch); + return expr; +} + +//////////////////////////////// +//~ rjf: "bswap" + +EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(bswap) +{ + expr = e_expr_ref_bswap(arena, expr); + return expr; +} + +//////////////////////////////// +//~ rjf: "cast" + +EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(cast) +{ + E_TypeKey type_key = ev_type_key_from_params(params); + expr = e_expr_ref_cast(arena, type_key, expr); + return expr; +} diff --git a/src/eval_visualization/eval_visualization_builtin_view_rules.h b/src/eval_visualization/eval_visualization_builtin_view_rules.h new file mode 100644 index 00000000..1eb1312c --- /dev/null +++ b/src/eval_visualization/eval_visualization_builtin_view_rules.h @@ -0,0 +1,17 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H +#define EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H + +//////////////////////////////// +//~ rjf: View Rule Tree Info Extraction Helpers + +internal U64 ev_base_offset_from_eval(E_Eval eval); +internal E_Value ev_value_from_params(MD_Node *params); +internal E_TypeKey ev_type_key_from_params(MD_Node *params); +internal E_Value ev_value_from_params_key(MD_Node *params, String8 key); +internal Rng1U64 ev_range_from_eval_params(E_Eval eval, MD_Node *params); +internal Arch ev_arch_from_eval_params(E_Eval eval, MD_Node *params); + +#endif // EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H diff --git a/src/eval_visualization/eval_visualization.c b/src/eval_visualization/eval_visualization_core.c similarity index 92% rename from src/eval_visualization/eval_visualization.c rename to src/eval_visualization/eval_visualization_core.c index 2ef09029..29f12879 100644 --- a/src/eval_visualization/eval_visualization.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -1,6 +1,11 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +//////////////////////////////// +//~ rjf: Generated Code + +#include "generated/eval_visualization.meta.c" + //////////////////////////////// //~ rjf: Key Functions @@ -51,6 +56,53 @@ ev_hash_from_key(EV_Key key) return hash; } +//////////////////////////////// +//~ rjf: Type Info Helpers + +//- rjf: type info -> expandability/editablity + +internal B32 +ev_type_key_is_expandable(E_TypeKey type_key) +{ + B32 result = 0; + for(E_TypeKey t = type_key; !result; t = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(t)))) + { + E_TypeKind kind = e_type_kind_from_key(t); + if(kind == E_TypeKind_Null || kind == E_TypeKind_Function) + { + break; + } + if(kind == E_TypeKind_Struct || + kind == E_TypeKind_Union || + kind == E_TypeKind_Class || + kind == E_TypeKind_Array || + kind == E_TypeKind_Enum) + { + result = 1; + } + } + return result; +} + +internal B32 +ev_type_key_is_editable(E_TypeKey type_key) +{ + B32 result = 0; + for(E_TypeKey t = type_key; !result; t = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(t)))) + { + E_TypeKind kind = e_type_kind_from_key(t); + if(kind == E_TypeKind_Null || kind == E_TypeKind_Function) + { + break; + } + if((E_TypeKind_FirstBasic <= kind && kind <= E_TypeKind_LastBasic) || e_type_kind_is_pointer_or_ref(kind)) + { + result = 1; + } + } + return result; +} + //////////////////////////////// //~ rjf: View Functions @@ -262,6 +314,15 @@ ev_view_rule_info_table_push(Arena *arena, EV_ViewRuleInfoTable *table, EV_ViewR n->v.string = push_str8_copy(arena, n->v.string); } +internal void +ev_view_rule_info_table_push_builtins(Arena *arena, EV_ViewRuleInfoTable *table) +{ + for(EachEnumVal(EV_ViewRuleKind, kind)) + { + ev_view_rule_info_table_push(arena, table, &ev_builtin_view_rule_info_table[kind]); + } +} + internal void ev_select_view_rule_info_table(EV_ViewRuleInfoTable *table) { @@ -972,6 +1033,48 @@ ev_expr_string_from_row(Arena *arena, EV_Row *row) return result; } +internal B32 +ev_row_is_expandable(EV_Row *row) +{ + B32 result = 0; + { + // rjf: determine if view rules force expandability + if(!result) + { + for(EV_ViewRuleNode *n = row->view_rules->first; n != 0; n = n->next) + { + EV_ViewRuleInfo *info = ev_view_rule_info_from_string(n->v.root->string); + if(info->flags & EV_ViewRuleInfoFlag_Expandable) + { + result = 1; + break; + } + } + } + + // rjf: determine if type info force expandability + if(!result) + { + Temp scratch = scratch_begin(0, 0); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, row->expr); + result = ev_type_key_is_expandable(irtree.type_key); + scratch_end(scratch); + } + } + return result; +} + +internal B32 +ev_row_is_editable(EV_Row *row) +{ + B32 result = 0; + Temp scratch = scratch_begin(0, 0); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, row->expr); + result = ev_type_key_is_editable(irtree.type_key); + scratch_end(scratch); + return result; +} + //////////////////////////////// //~ rjf: Stringification diff --git a/src/eval_visualization/eval_visualization.h b/src/eval_visualization/eval_visualization_core.h similarity index 91% rename from src/eval_visualization/eval_visualization.h rename to src/eval_visualization/eval_visualization_core.h index 972a884e..21e413fa 100644 --- a/src/eval_visualization/eval_visualization.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -1,8 +1,8 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -#ifndef EVAL_VISUALIZATION_H -#define EVAL_VISUALIZATION_H +#ifndef EVAL_VISUALIZATION_CORE_H +#define EVAL_VISUALIZATION_CORE_H //////////////////////////////// //~ rjf: Key Type (Uniquely Refers To One Tree Node) @@ -81,7 +81,7 @@ struct EV_View #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 *eval_view, \ +EV_View *view, \ EV_Key parent_key, \ EV_Key key, \ EV_ExpandNode *expand_node, \ @@ -135,6 +135,11 @@ struct EV_ViewRuleInfoTable U64 slots_count; }; +//////////////////////////////// +//~ rjf: Generated Code + +#include "generated/eval_visualization.meta.h" + //////////////////////////////// //~ rjf: View Rule Instance Types @@ -284,6 +289,13 @@ internal B32 ev_key_match(EV_Key a, EV_Key b); internal U64 ev_hash_from_seed_string(U64 seed, String8 string); internal U64 ev_hash_from_key(EV_Key key); +//////////////////////////////// +//~ rjf: Type Info Helpers + +//- rjf: type info -> expandability/editablity +internal B32 ev_type_key_is_expandable(E_TypeKey type_key); +internal B32 ev_type_key_is_editable(E_TypeKey type_key); + //////////////////////////////// //~ rjf: View Functions @@ -302,6 +314,7 @@ internal void ev_key_set_view_rule(EV_View *view, EV_Key key, String8 view_rule_ //~ rjf: View Rule Info Table Building / Selection / Lookups internal void ev_view_rule_info_table_push(Arena *arena, EV_ViewRuleInfoTable *table, EV_ViewRuleInfo *info); +internal void ev_view_rule_info_table_push_builtins(Arena *arena, EV_ViewRuleInfoTable *table); internal void ev_select_view_rule_info_table(EV_ViewRuleInfoTable *table); internal EV_ViewRuleInfo *ev_view_rule_info_from_string(String8 string); @@ -347,6 +360,8 @@ internal E_Expr *ev_expr_from_block_index(Arena *arena, EV_Block *block, U64 ind internal EV_Row *ev_row_list_push_new(Arena *arena, EV_View *view, EV_WindowedRowList *rows, EV_Block *block, EV_Key key, E_Expr *expr); internal EV_WindowedRowList ev_windowed_row_list_from_block_list(Arena *arena, EV_View *view, Rng1S64 visible_range, EV_BlockList *blocks); internal String8 ev_expr_string_from_row(Arena *arena, EV_Row *row); +internal B32 ev_row_is_expandable(EV_Row *row); +internal B32 ev_row_is_editable(EV_Row *row); //////////////////////////////// //~ rjf: Stringification @@ -358,4 +373,4 @@ internal String8 ev_string_from_hresult_code(U32 code); internal String8 ev_string_from_simple_typed_eval(Arena *arena, EV_StringFlags flags, U32 radix, E_Eval eval); internal String8 ev_escaped_from_raw_string(Arena *arena, String8 raw); -#endif // EVAL_VISUALIZATION_H +#endif // EVAL_VISUALIZATION_CORE_H diff --git a/src/eval_visualization/eval_visualization_inc.c b/src/eval_visualization/eval_visualization_inc.c new file mode 100644 index 00000000..44e7f6cb --- /dev/null +++ b/src/eval_visualization/eval_visualization_inc.c @@ -0,0 +1,5 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#include "eval_visualization_core.c" +#include "eval_visualization_builtin_view_rules.c" diff --git a/src/eval_visualization/eval_visualization_inc.h b/src/eval_visualization/eval_visualization_inc.h new file mode 100644 index 00000000..2e01e21a --- /dev/null +++ b/src/eval_visualization/eval_visualization_inc.h @@ -0,0 +1,10 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef EVAL_VISUALIZATION_INC_H +#define EVAL_VISUALIZATION_INC_H + +#include "eval_visualization_core.h" +#include "eval_visualization_builtin_view_rules.h" + +#endif // EVAL_VISUALIZATION_INC_H diff --git a/src/eval_visualization/generated/eval_visualization.meta.c b/src/eval_visualization/generated/eval_visualization.meta.c new file mode 100644 index 00000000..ba18e766 --- /dev/null +++ b/src/eval_visualization/generated/eval_visualization.meta.c @@ -0,0 +1,17 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//- GENERATED CODE + +C_LINKAGE_BEGIN +EV_ViewRuleInfo ev_builtin_view_rule_info_table[5] = +{ +{str8_lit_comp("default"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0)|(EV_ViewRuleInfoFlag_ExprResolution*0)|(EV_ViewRuleInfoFlag_VizBlockProd*1), 0, EV_VIEW_RULE_BLOCK_PROD_FUNCTION_NAME(default) , }, +{str8_lit_comp("array"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0)|(EV_ViewRuleInfoFlag_ExprResolution*1)|(EV_ViewRuleInfoFlag_VizBlockProd*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(array) , 0, }, +{str8_lit_comp("slice"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0)|(EV_ViewRuleInfoFlag_ExprResolution*1)|(EV_ViewRuleInfoFlag_VizBlockProd*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(slice) , 0, }, +{str8_lit_comp("bswap"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0)|(EV_ViewRuleInfoFlag_ExprResolution*1)|(EV_ViewRuleInfoFlag_VizBlockProd*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(bswap) , 0, }, +{str8_lit_comp("cast"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0)|(EV_ViewRuleInfoFlag_ExprResolution*1)|(EV_ViewRuleInfoFlag_VizBlockProd*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(cast) , 0, }, +}; + +C_LINKAGE_END + diff --git a/src/eval_visualization/generated/eval_visualization.meta.h b/src/eval_visualization/generated/eval_visualization.meta.h new file mode 100644 index 00000000..cf79536f --- /dev/null +++ b/src/eval_visualization/generated/eval_visualization.meta.h @@ -0,0 +1,24 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//- GENERATED CODE + +#ifndef EVAL_VISUALIZATION_META_H +#define EVAL_VISUALIZATION_META_H + +typedef enum EV_ViewRuleKind +{ +EV_ViewRuleKind_Default, +EV_ViewRuleKind_Array, +EV_ViewRuleKind_Slice, +EV_ViewRuleKind_ByteSwap, +EV_ViewRuleKind_Cast, +EV_ViewRuleKind_COUNT, +} EV_ViewRuleKind; + +EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(array); +EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(slice); +EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(bswap); +EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(cast); +EV_VIEW_RULE_BLOCK_PROD_FUNCTION_DEF(default); +#endif // EVAL_VISUALIZATION_META_H diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index da29d900..b28ee1cc 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -533,7 +533,7 @@ #include "fuzzy_search/fuzzy_search.h" #include "demon/demon_inc.h" #include "eval/eval_inc.h" -#include "eval_visualization/eval_visualization.h" +#include "eval_visualization/eval_visualization_inc.h" #include "ctrl/ctrl_inc.h" #include "font_provider/font_provider_inc.h" #include "render/render_inc.h" @@ -573,7 +573,7 @@ #include "fuzzy_search/fuzzy_search.c" #include "demon/demon_inc.c" #include "eval/eval_inc.c" -#include "eval_visualization/eval_visualization.c" +#include "eval_visualization/eval_visualization_inc.c" #include "ctrl/ctrl_inc.c" #include "font_provider/font_provider_inc.c" #include "render/render_inc.c"