From 312ddd589982eb056580daf5b8e43fab554cc4b2 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 11 Feb 2025 15:25:42 -0800 Subject: [PATCH] fix array-index ir tree generation - was incorrectly applying array value rules to address value evaluations; plug in ir-generation hooks for slices, arrays, etc.; eliminate old view rule code --- src/eval/eval_ir.c | 110 ++++++++++-------- src/eval/eval_types.c | 7 +- .../eval_visualization_builtin_view_rules.c | 106 ----------------- .../eval_visualization_builtin_view_rules.h | 17 --- .../eval_visualization_core.c | 3 +- .../eval_visualization_inc.c | 1 - .../eval_visualization_inc.h | 1 - src/raddbg/generated/raddbg.meta.c | 4 +- src/raddbg/generated/raddbg.meta.h | 2 +- src/raddbg/raddbg.mdesk | 2 + src/raddbg/raddbg_core.c | 4 +- 11 files changed, 77 insertions(+), 180 deletions(-) delete mode 100644 src/eval_visualization/eval_visualization_builtin_view_rules.c delete mode 100644 src/eval_visualization/eval_visualization_builtin_view_rules.h diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index b2fce86d..f87ee218 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -146,15 +146,18 @@ E_LOOKUP_INFO_FUNCTION_DEF(default) { E_Type *type = e_type_from_key__cached(lhs_type_key); lookup_info.idxed_expr_count = type->count; - E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(lhs->type_key)); - E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - if(direct_type_kind == E_TypeKind_Struct || - direct_type_kind == E_TypeKind_Class || - direct_type_kind == E_TypeKind_Union || - direct_type_kind == E_TypeKind_Enum) + if(type->count == 1) { - E_Type *direct_type = e_type_from_key__cached(direct_type_key); - lookup_info.named_expr_count = direct_type->count; + E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(lhs->type_key)); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); + if(direct_type_kind == E_TypeKind_Struct || + direct_type_kind == E_TypeKind_Class || + direct_type_kind == E_TypeKind_Union || + direct_type_kind == E_TypeKind_Enum) + { + E_Type *direct_type = e_type_from_key__cached(direct_type_key); + lookup_info.named_expr_count = direct_type->count; + } } } else if(lhs_type_kind == E_TypeKind_Struct || @@ -361,57 +364,54 @@ E_LOOKUP_ACCESS_FUNCTION_DEF(default) // rjf: generate E_IRNode *new_tree = &e_irnode_nil; + E_Mode mode = l.mode; { - switch(l.mode) + // rjf: reading from an array value -> read from stack value + if(l.mode == E_Mode_Value && l_restype_kind == E_TypeKind_Array) { - // rjf: offsets -> read from base offset - default: - case E_Mode_Null: - case E_Mode_Offset: + // rjf: ops to compute the offset + E_IRNode *offset_tree = e_irtree_resolve_to_value(arena, r.mode, r.root, r_restype); + if(direct_type_size > 1) { - // rjf: ops to compute the offset - E_IRNode *offset_tree = e_irtree_resolve_to_value(arena, r.mode, r.root, r_restype); - if(direct_type_size > 1) - { - E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); - offset_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, offset_tree, const_tree); - } - - // rjf: ops to compute the base offset (resolve to value if addr-of-pointer) - E_IRNode *base_tree = l.root; - if(l_restype_kind == E_TypeKind_Ptr && l.mode != E_Mode_Value) - { - base_tree = e_irtree_resolve_to_value(arena, l.mode, base_tree, l_restype); - } - - // rjf: ops to compute the final address - new_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Add, offset_tree, base_tree); - }break; + E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); + offset_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, offset_tree, const_tree); + } - // rjf: values -> read from stack value - case E_Mode_Value: + // rjf: ops to push stack value, push offset, + read from stack value + new_tree = e_push_irnode(arena, RDI_EvalOp_ValueRead); + new_tree->value.u64 = direct_type_size; + e_irnode_push_child(new_tree, offset_tree); + e_irnode_push_child(new_tree, l.root); + } + + // rjf: all other cases -> read from base offset + else + { + // rjf: ops to compute the offset + E_IRNode *offset_tree = e_irtree_resolve_to_value(arena, r.mode, r.root, r_restype); + if(direct_type_size > 1) { - // rjf: ops to compute the offset - E_IRNode *offset_tree = e_irtree_resolve_to_value(arena, r.mode, r.root, r_restype); - if(direct_type_size > 1) - { - E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); - offset_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, offset_tree, const_tree); - } - - // rjf: ops to push stack value, push offset, + read from stack value - new_tree = e_push_irnode(arena, RDI_EvalOp_ValueRead); - new_tree->value.u64 = direct_type_size; - e_irnode_push_child(new_tree, offset_tree); - e_irnode_push_child(new_tree, l.root); - }break; + E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); + offset_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, offset_tree, const_tree); + } + + // rjf: ops to compute the base offset (resolve to value if addr-of-pointer) + E_IRNode *base_tree = l.root; + if(l_restype_kind == E_TypeKind_Ptr && l.mode != E_Mode_Value) + { + base_tree = e_irtree_resolve_to_value(arena, l.mode, base_tree, l_restype); + } + + // rjf: ops to compute the final address + new_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Add, offset_tree, base_tree); + mode = E_Mode_Offset; } } // rjf: fill result.irtree_and_type.root = new_tree; result.irtree_and_type.type_key = direct_type; - result.irtree_and_type.mode = l.mode; + result.irtree_and_type.mode = mode; }break; } return result; @@ -607,7 +607,10 @@ E_IRGEN_FUNCTION_DEF(slice) } // rjf: overwrite type - irtree.type_key = slice_type_key; + if(!e_type_key_match(slice_type_key, e_type_key_zero())) + { + irtree.type_key = slice_type_key; + } } scratch_end(scratch); return irtree; @@ -662,6 +665,11 @@ e_irgen_rule_map_make(Arena *arena, U64 slots_count) E_IRGenRuleMap map = {0}; map.slots_count = slots_count; map.slots = push_array(arena, E_IRGenRuleSlot, map.slots_count); + e_irgen_rule_map_insert_new(arena, &map, str8_lit("cast"), .irgen = E_IRGEN_FUNCTION_NAME(cast)); + e_irgen_rule_map_insert_new(arena, &map, str8_lit("bswap"), .irgen = E_IRGEN_FUNCTION_NAME(bswap)); + e_irgen_rule_map_insert_new(arena, &map, str8_lit("array"), .irgen = E_IRGEN_FUNCTION_NAME(array)); + e_irgen_rule_map_insert_new(arena, &map, str8_lit("slice"), .irgen = E_IRGEN_FUNCTION_NAME(slice)); + e_irgen_rule_map_insert_new(arena, &map, str8_lit("wrap"), .irgen = E_IRGEN_FUNCTION_NAME(wrap)); return map; } @@ -2018,6 +2026,10 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr) ProfScope("irgen rule '%.*s'", str8_varg(t->rule->name)) { result = t->rule->irgen(arena, expr, t->tag); + if(result.root == &e_irnode_nil && t->rule != &e_irgen_rule__default) + { + result = e_irgen_rule__default.irgen(arena, expr, &e_expr_nil); + } } // rjf: find any auto hooks according to this generation's type diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index fa5fd05d..6a06b71f 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -460,7 +460,7 @@ e_type_key_cons_array(E_TypeKey element_type_key, U64 count) internal E_TypeKey e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, U64 count, E_TypeFlags flags) { - E_TypeKey key = e_type_key_cons(.arch = arch, .kind = E_TypeKind_Ptr, .flags = flags, .direct_key = element_type_key); + E_TypeKey key = e_type_key_cons(.arch = arch, .kind = E_TypeKind_Ptr, .flags = flags, .direct_key = element_type_key, .count = count); return key; } @@ -1683,6 +1683,11 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr E_TypeKey direct = e_type_direct_from_key(key); e_type_lhs_string_from_key(arena, direct, out, 1, skip_return); str8_list_push(arena, out, str8_lit("*")); + E_Type *type = e_type_from_key__cached(key); + if(type->count != 1) + { + str8_list_pushf(arena, out, ".%I64u", type->count); + } }break; case E_TypeKind_SpacePtr: diff --git a/src/eval_visualization/eval_visualization_builtin_view_rules.c b/src/eval_visualization/eval_visualization_builtin_view_rules.c deleted file mode 100644 index b8d293c7..00000000 --- a/src/eval_visualization/eval_visualization_builtin_view_rules.c +++ /dev/null @@ -1,106 +0,0 @@ -// 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.last_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: "list" - -EV_EXPAND_RULE_INFO_FUNCTION_DEF(list) -{ - EV_ExpandInfo info = {0}; - return info; -} diff --git a/src/eval_visualization/eval_visualization_builtin_view_rules.h b/src/eval_visualization/eval_visualization_builtin_view_rules.h deleted file mode 100644 index 1eb1312c..00000000 --- a/src/eval_visualization/eval_visualization_builtin_view_rules.h +++ /dev/null @@ -1,17 +0,0 @@ -// 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_core.c b/src/eval_visualization/eval_visualization_core.c index 0490511a..226d1a24 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -451,9 +451,8 @@ ev_keyed_expr_push_tags(Arena *arena, EV_View *view, EV_Block *block, EV_Key key { // rjf: push inherited tags first (we want these to be found first, since tags are applied // in order, and explicit ones should always be strongest) - for(EV_Block *b = block; b != &ev_nil_block; b = b->parent) { - for(E_Expr *src_tag = b->expr->first_tag; src_tag != &e_expr_nil; src_tag = src_tag->next) + for(E_Expr *src_tag = block->expr->first_tag; src_tag != &e_expr_nil; src_tag = src_tag->next) { e_expr_push_tag(expr, e_expr_copy(arena, src_tag)); } diff --git a/src/eval_visualization/eval_visualization_inc.c b/src/eval_visualization/eval_visualization_inc.c index 44e7f6cb..d944d937 100644 --- a/src/eval_visualization/eval_visualization_inc.c +++ b/src/eval_visualization/eval_visualization_inc.c @@ -2,4 +2,3 @@ // 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 index 2e01e21a..11c9b212 100644 --- a/src/eval_visualization/eval_visualization_inc.h +++ b/src/eval_visualization/eval_visualization_inc.h @@ -5,6 +5,5 @@ #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/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 76ff60a7..66bcbe91 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -28,7 +28,7 @@ RD_CmdKind_Null, RD_CmdKind_Null, }; -RD_VocabularyInfo rd_vocabulary_info_table[64] = +RD_VocabularyInfo rd_vocabulary_info_table[66] = { {str8_lit_comp("auto_view_rule"), str8_lit_comp("auto_view_rules"), str8_lit_comp("Auto View Rule"), str8_lit_comp("Auto View Rules"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, @@ -94,6 +94,8 @@ RD_VocabularyInfo rd_vocabulary_info_table[64] = {str8_lit_comp("disabled"), str8_lit_comp(""), str8_lit_comp("Disabled"), str8_lit_comp("Disabled"), RD_IconKind_Null}, {str8_lit_comp("debug_subprocesses"), str8_lit_comp(""), str8_lit_comp("Debug Subprocesses"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("environment"), str8_lit_comp("environments"), str8_lit_comp("Environment"), str8_lit_comp("Environments"), RD_IconKind_Null}, +{str8_lit_comp("frozen"), str8_lit_comp(""), str8_lit_comp("Frozen"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("id"), str8_lit_comp("ids"), str8_lit_comp("ID"), str8_lit_comp("IDs"), RD_IconKind_Null}, }; RD_NameSchemaInfo rd_name_schema_info_table[10] = diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 797b8bc7..9ea1d068 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -570,7 +570,7 @@ C_LINKAGE_BEGIN extern String8 rd_cfg_src_string_table[4]; extern RD_CmdKind rd_cfg_src_load_cmd_kind_table[4]; extern RD_CmdKind rd_cfg_src_write_cmd_kind_table[4]; -extern RD_VocabularyInfo rd_vocabulary_info_table[64]; +extern RD_VocabularyInfo rd_vocabulary_info_table[66]; extern RD_NameSchemaInfo rd_name_schema_info_table[10]; extern Rng1U64 rd_reg_slot_range_table[38]; extern RD_StringBindingPair rd_default_binding_table[111]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index 4a5be8d2..a87d7e23 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -115,6 +115,8 @@ RD_VocabularyMap: {disabled "" "Disabled" "Disabled" Null } {debug_subprocesses "" "Debug Subprocesses" "" Null } {environment _ "Environment" _ Null } + {frozen "" "Frozen" "" Null } + {id _ "ID" _ Null } } @struct RD_VocabularyInfo: diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 3b0b832c..aa8e5188 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -9050,7 +9050,7 @@ E_LOOKUP_ACCESS_FUNCTION_DEF(thread) { E_Eval eval = e_eval_from_expr(scratch.arena, lhs); CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); - result.irtree_and_type.root = e_irtree_leaf_u128(arena, u128_make(entity->handle.machine_id, entity->handle.dmn_handle.u64[0])); + result.irtree_and_type.root = e_irtree_set_space(arena, eval.space, e_irtree_leaf_u128(arena, u128_make(entity->handle.machine_id, entity->handle.dmn_handle.u64[0]))); result.irtree_and_type.type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("call_stack")); result.irtree_and_type.mode = E_Mode_Offset; } @@ -13076,6 +13076,8 @@ rd_frame(void) ctx->macro_map[0] = e_string2expr_map_make(scratch.arena, 512); ctx->lookup_rule_map = push_array(scratch.arena, E_LookupRuleMap, 1); ctx->lookup_rule_map[0] = e_lookup_rule_map_make(scratch.arena, 512); + ctx->irgen_rule_map = push_array(scratch.arena, E_IRGenRuleMap, 1); + ctx->irgen_rule_map[0] = e_irgen_rule_map_make(scratch.arena, 512); ctx->auto_hook_map = push_array(scratch.arena, E_AutoHookMap, 1); ctx->auto_hook_map[0] = e_auto_hook_map_make(scratch.arena, 512);