Files
raddebugger/src/dbg_frontend/dbg_frontend_view_rules.c
T

501 lines
20 KiB
C

// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: default
D_VIEW_RULE_VIZ_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);
E_MemberArray filtered_data_members = d_filtered_data_members_from_members_cfg_table(arena, data_members, cfg_table);
// rjf: build blocks for all members, split by sub-expansions
D_EvalVizBlock *last_vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Members, key, d_expand_key_make(df_hash_from_expand_key(key), 0), depth);
{
last_vb->expr = expr;
last_vb->cfg_table = cfg_table;
last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, filtered_data_members.count);
last_vb->members = filtered_data_members;
}
for(D_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 = d_expr_from_eval_viz_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 = d_eval_viz_block_split_and_continue(arena, out, last_vb, child_idx);
// rjf: build child config table
D_CfgTable *child_cfg_table = push_array(arena, D_CfgTable, 1);
*child_cfg_table = d_cfg_table_from_inheritance(arena, cfg_table);
{
String8 view_rule_string = d_eval_view_rule_from_key(eval_view, child->key);
if(view_rule_string.size != 0)
{
d_cfg_table_push_unparsed_string(arena, child_cfg_table, view_rule_string, D_CfgSrc_User);
}
}
// rjf: recurse for child
d_append_expr_eval_viz_blocks__rec(arena, eval_view, key, child->key, str8_zero(), child_expr, child_cfg_table, depth, out);
}
d_eval_viz_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);
D_EvalVizBlock *last_vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_EnumMembers, key, d_expand_key_make(df_hash_from_expand_key(key), 0), depth);
{
last_vb->expr = expr;
last_vb->cfg_table = cfg_table;
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;
}
d_eval_viz_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
D_EvalVizBlock *last_vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Elements, key, d_expand_key_make(df_hash_from_expand_key(key), 0), depth);
{
last_vb->expr = need_extra_deref ? e_expr_ref_deref(arena, expr) : expr;
last_vb->cfg_table = cfg_table;
last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, array_count);
}
for(D_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 = d_expr_from_eval_viz_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 = d_eval_viz_block_split_and_continue(arena, out, last_vb, child_idx);
// rjf: build child config table
D_CfgTable *child_cfg_table = push_array(arena, D_CfgTable, 1);
*child_cfg_table = d_cfg_table_from_inheritance(arena, cfg_table);
{
String8 view_rule_string = d_eval_view_rule_from_key(eval_view, child->key);
if(view_rule_string.size != 0)
{
d_cfg_table_push_unparsed_string(arena, child_cfg_table, view_rule_string, D_CfgSrc_User);
}
}
// rjf: recurse for child
d_append_expr_eval_viz_blocks__rec(arena, eval_view, key, child->key, str8_zero(), child_expr, child_cfg_table, depth, out);
}
d_eval_viz_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
D_ExpandKey child_key = d_expand_key_make(df_hash_from_expand_key(key), 1);
// rjf: build child config table
D_CfgTable *child_cfg_table = push_array(arena, D_CfgTable, 1);
*child_cfg_table = d_cfg_table_from_inheritance(arena, cfg_table);
{
String8 view_rule_string = d_eval_view_rule_from_key(eval_view, child_key);
if(view_rule_string.size != 0)
{
d_cfg_table_push_unparsed_string(arena, child_cfg_table, view_rule_string, D_CfgSrc_User);
}
}
// rjf: recurse for child
E_Expr *child_expr = e_expr_ref_deref(arena, expr);
d_append_expr_eval_viz_blocks__rec(arena, eval_view, key, child_key, str8_zero(), child_expr, child_cfg_table, depth, out);
}
scratch_end(scratch);
}
////////////////////////////////
//~ rjf: "array"
D_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 = d_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"
D_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: "list"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(list){}
DF_VIEW_RULE_VIZ_ROW_PROD_FUNCTION_DEF(list){}
////////////////////////////////
//~ rjf: "bswap"
D_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(bswap)
{
expr = e_expr_ref_bswap(arena, expr);
return expr;
}
////////////////////////////////
//~ rjf: "cast"
D_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(cast)
{
E_TypeKey type_key = d_type_key_from_params(params);
expr = e_expr_ref_cast(arena, type_key, expr);
return expr;
}
////////////////////////////////
//~ rjf: "dec"
DF_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(dec){}
////////////////////////////////
//~ rjf: "bin"
DF_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(bin){}
////////////////////////////////
//~ rjf: "oct"
DF_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(oct){}
////////////////////////////////
//~ rjf: "hex"
DF_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(hex){}
////////////////////////////////
//~ rjf: "only"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(only){}
DF_VIEW_RULE_VIZ_ROW_PROD_FUNCTION_DEF(only){}
DF_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(only){}
////////////////////////////////
//~ rjf: "omit"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(omit){}
DF_VIEW_RULE_VIZ_ROW_PROD_FUNCTION_DEF(omit){}
DF_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(omit){}
////////////////////////////////
//~ rjf: "no_addr"
DF_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(no_addr){}
////////////////////////////////
//~ rjf: "checkbox"
DF_VIEW_RULE_ROW_UI_FUNCTION_DEF(checkbox)
{
Temp scratch = scratch_begin(0, 0);
E_Eval eval = e_eval_from_string(scratch.arena, string);
E_Eval value_eval = e_value_eval_from_eval(eval);
if(ui_clicked(df_icon_buttonf(value_eval.value.u64 == 0 ? DF_IconKind_CheckHollow : DF_IconKind_CheckFilled, 0, "###check")))
{
d_commit_eval_value_string(eval, value_eval.value.u64 == 0 ? str8_lit("1") : str8_lit("0"));
}
scratch_end(scratch);
}
////////////////////////////////
//~ rjf: "rgba"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(color_rgba)
{
D_EvalVizBlock *vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Canvas, key, d_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->string = string;
vb->expr = expr;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
vb->cfg_table = cfg_table;
d_eval_viz_block_end(out, vb);
}
DF_VIEW_RULE_ROW_UI_FUNCTION_DEF(color_rgba)
{
Temp scratch = scratch_begin(0, 0);
E_Eval eval = e_eval_from_string(scratch.arena, string);
Vec4F32 rgba = df_rgba_from_eval_params(eval, params);
Vec4F32 hsva = hsva_from_rgba(rgba);
//- rjf: build text box
UI_Box *text_box = &ui_g_nil_box;
UI_WidthFill DF_Font(DF_FontSlot_Code)
{
text_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero());
DR_FancyStringList fancy_strings = {0};
{
DR_FancyString open_paren = {ui_top_font(), str8_lit("("), ui_top_palette()->text, ui_top_font_size(), 0, 0};
DR_FancyString comma = {ui_top_font(), str8_lit(", "), ui_top_palette()->text, ui_top_font_size(), 0, 0};
DR_FancyString r_fstr = {ui_top_font(), push_str8f(scratch.arena, "%.2f", rgba.x), v4f32(1.f, 0.25f, 0.25f, 1.f), ui_top_font_size(), 4.f, 0};
DR_FancyString g_fstr = {ui_top_font(), push_str8f(scratch.arena, "%.2f", rgba.y), v4f32(0.25f, 1.f, 0.25f, 1.f), ui_top_font_size(), 4.f, 0};
DR_FancyString b_fstr = {ui_top_font(), push_str8f(scratch.arena, "%.2f", rgba.z), v4f32(0.25f, 0.25f, 1.f, 1.f), ui_top_font_size(), 4.f, 0};
DR_FancyString a_fstr = {ui_top_font(), push_str8f(scratch.arena, "%.2f", rgba.w), v4f32(1.f, 1.f, 1.f, 1.f), ui_top_font_size(), 4.f, 0};
DR_FancyString clse_paren = {ui_top_font(), str8_lit(")"), ui_top_palette()->text, ui_top_font_size(), 0, 0};
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &open_paren);
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &r_fstr);
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &comma);
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &g_fstr);
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &comma);
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &b_fstr);
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &comma);
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &a_fstr);
dr_fancy_string_list_push(scratch.arena, &fancy_strings, &clse_paren);
}
ui_box_equip_display_fancy_strings(text_box, &fancy_strings);
}
//- rjf: build color box
UI_Box *color_box = &ui_g_nil_box;
UI_PrefWidth(ui_em(1.875f, 1.f)) UI_ChildLayoutAxis(Axis2_Y)
{
color_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "color_box");
UI_Parent(color_box) UI_PrefHeight(ui_em(1.875f, 1.f)) UI_Padding(ui_pct(1, 0))
{
UI_Palette(ui_build_palette(ui_top_palette(), .background = rgba)) UI_CornerRadius(ui_top_font_size()*0.5f)
ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, ui_key_zero());
}
}
//- rjf: space
ui_spacer(ui_em(0.375f, 1.f));
//- rjf: hover color box -> show components
UI_Signal sig = ui_signal_from_box(color_box);
if(ui_hovering(sig))
{
ui_do_color_tooltip_hsva(hsva);
}
scratch_end(scratch);
}
////////////////////////////////
//~ rjf: "text"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(text)
{
D_EvalVizBlock *vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Canvas, key, d_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->string = string;
vb->expr = expr;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
vb->cfg_table = cfg_table;
d_eval_viz_block_end(out, vb);
}
////////////////////////////////
//~ rjf: "disasm"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(disasm)
{
D_EvalVizBlock *vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Canvas, key, d_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->string = string;
vb->expr = expr;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
vb->cfg_table = cfg_table;
d_eval_viz_block_end(out, vb);
}
////////////////////////////////
//~ rjf: "memory"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(memory)
{
D_EvalVizBlock *vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Canvas, key, d_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->string = string;
vb->expr = expr;
vb->visual_idx_range = r1u64(0, 16);
vb->semantic_idx_range = r1u64(0, 1);
vb->cfg_table = cfg_table;
d_eval_viz_block_end(out, vb);
}
////////////////////////////////
//~ rjf: "graph"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(graph)
{
D_EvalVizBlock *vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Canvas, key, d_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->string = string;
vb->expr = expr;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
vb->cfg_table = cfg_table;
d_eval_viz_block_end(out, vb);
}
////////////////////////////////
//~ rjf: "bitmap"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(bitmap)
{
D_EvalVizBlock *vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Canvas, key, d_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->string = string;
vb->expr = expr;
vb->visual_idx_range = r1u64(0, 8);
vb->semantic_idx_range = r1u64(0, 1);
vb->cfg_table = cfg_table;
d_eval_viz_block_end(out, vb);
}
////////////////////////////////
//~ rjf: "geo3d"
D_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(geo3d)
{
D_EvalVizBlock *vb = d_eval_viz_block_begin(arena, D_EvalVizBlockKind_Canvas, key, d_expand_key_make(df_hash_from_expand_key(key), 1), depth);
vb->string = string;
vb->expr = expr;
vb->visual_idx_range = r1u64(0, 16);
vb->semantic_idx_range = r1u64(0, 1);
vb->cfg_table = cfg_table;
d_eval_viz_block_end(out, vb);
}