From abd33f7160b3bd0342eeb144c44d6edf00dd66ea Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 11 Apr 2025 11:58:43 -0700 Subject: [PATCH] new (and successful :) ) story for 'parent/overridden irtrees'. basically, if we have a rule which maps some eval X's type from A -> B, we preserve the original ir-tree compilation of A in the 'history' when we inevitably produce the ir-tree compilation of B. this can be used for accesses on overridden evaluations, and it allows us to implement $ in auto view rules. --- src/eval/eval_core.h | 1 + src/eval/eval_ir.c | 102 +++++++++++++++++++++++++-------------- src/eval/eval_ir.h | 3 ++ src/mule/mule_main.cpp | 2 +- src/raddbg/raddbg_core.c | 6 +++ 5 files changed, 78 insertions(+), 36 deletions(-) diff --git a/src/eval/eval_core.h b/src/eval/eval_core.h index a3b7f9de..5aea7d7e 100644 --- a/src/eval/eval_core.h +++ b/src/eval/eval_core.h @@ -271,6 +271,7 @@ struct E_IRTreeAndType void *user_data; E_Mode mode; E_MsgList msgs; + E_IRTreeAndType *prev; }; //////////////////////////////// diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index c3e9efcc..7ce01ff4 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -896,12 +896,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) } // rjf: bad conditions? -> error if applicable, exit - if(l.root == &e_irnode_nil || - e_type_key_match(e_type_key_zero(), check_type_key)) - { - break; - } - else if(exprr->kind != E_ExprKind_LeafIdentifier) + if(exprr->kind != E_ExprKind_LeafIdentifier) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprl->location, "Expected member name."); break; @@ -911,6 +906,11 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprr->location, "Could not find a member named `%S`.", exprr->string); break; } + else if(l.root == &e_irnode_nil || + e_type_key_match(e_type_key_zero(), check_type_key)) + { + break; + } else if(check_type_kind != E_TypeKind_Struct && check_type_kind != E_TypeKind_Class && check_type_kind != E_TypeKind_Union && @@ -1074,8 +1074,10 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) { Task *next; E_Expr *expr; + E_IRTreeAndType *prev; }; - Task start_task = {0, root_expr}; + E_IRTreeAndType *start_prev = e_ir_state->overridden_irtree; + Task start_task = {0, root_expr, e_ir_state->overridden_irtree}; Task *first_task = &start_task; Task *last_task = first_task; for(Task *t = first_task; t != 0; t = t->next) @@ -1085,11 +1087,18 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) //- rjf: poison the expression we are about to use, so we don't recursively use it e_expr_poison(expr); + //- rjf: select the task's previous ir-tree-and-type as the overridden tree + if(t->prev != 0) + { + e_ir_state->overridden_irtree = t->prev; + } + //- rjf: do expr -> irtree generation for this expression if(expr->kind == E_ExprKind_Ref) { expr = expr->ref; } + B32 allow_autohooks = 1; E_ExprKind kind = expr->kind; switch(kind) { @@ -1103,32 +1112,42 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) E_Expr *lhs = expr->first; E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); - // rjf: gather inherited lenses from the left-hand-side + // rjf: try all IR trees in chain + for(E_IRTreeAndType *lhs_irtree_try = &lhs_irtree; lhs_irtree_try != 0; lhs_irtree_try = lhs_irtree_try->prev) { - E_TypeKey k = lhs_irtree.type_key; - E_TypeKind kind = e_type_kind_from_key(k); - for(;kind == E_TypeKind_Lens;) + // rjf: gather inherited lenses from the left-hand-side { - E_Type *lens_type = e_type_from_key__cached(k); - if(lens_type->flags & E_TypeFlag_InheritedOnAccess) + E_TypeKey k = lhs_irtree_try->type_key; + E_TypeKind kind = e_type_kind_from_key(k); + for(;kind == E_TypeKind_Lens;) { - e_type_key_list_push_front(scratch.arena, &inherited_lenses, k); + E_Type *lens_type = e_type_from_key__cached(k); + if(lens_type->flags & E_TypeFlag_InheritedOnAccess) + { + e_type_key_list_push_front(scratch.arena, &inherited_lenses, k); + } + k = e_type_direct_from_key(k); + kind = e_type_kind_from_key(k); } - k = e_type_direct_from_key(k); - kind = e_type_kind_from_key(k); + } + + // rjf: pick access hook based on type + E_Type *lhs_type = e_type_from_key__cached(lhs_irtree_try->type_key); + E_TypeAccessFunctionType *lhs_access = lhs_type->access; + if(lhs_access == 0) + { + lhs_access = E_TYPE_ACCESS_FUNCTION_NAME(default); + } + + // rjf: call into hook to do access + result = lhs_access(arena, expr, lhs_irtree_try); + + // rjf: end chain if we found a result + if(result.root != &e_irnode_nil) + { + break; } } - - // rjf: pick access hook based on type - E_Type *lhs_type = e_type_from_key__cached(lhs_irtree.type_key); - E_TypeAccessFunctionType *lhs_access = lhs_type->access; - if(lhs_access == 0) - { - lhs_access = E_TYPE_ACCESS_FUNCTION_NAME(default); - } - - // rjf: call into hook to do access - result = lhs_access(arena, expr, &lhs_irtree); }break; //- rjf: dereference @@ -2037,17 +2056,16 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) } } - //- rjf: try to map name as parent expression signifier ('$') -#if 0 - if(!string_mapped && str8_match(string, str8_lit("$"), 0) && e_ir_state->top_parent != 0) + //- rjf: try to map name as overridden expression signifier ('$') + if(!string_mapped && str8_match(string, str8_lit("$"), 0) && e_ir_state->overridden_irtree != 0) { - E_OpList oplist = e_oplist_from_irtree(arena, e_ir_state->top_parent->v.root); + E_OpList oplist = e_oplist_from_irtree(arena, e_ir_state->overridden_irtree->root); string_mapped = 1; mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = e_ir_state->top_parent->v.mode; - mapped_type_key = e_ir_state->top_parent->v.type_key; + mapped_bytecode_mode = e_ir_state->overridden_irtree->mode; + mapped_type_key = e_ir_state->overridden_irtree->type_key; + allow_autohooks = 0; } -#endif //- rjf: try globals if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("global"), 0))) @@ -2368,7 +2386,7 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) }break; } - //- rjf: if the evaluated type has a hook for an extra layer of ir generation, + //- rjf: if the evaluated type has a hook for an extra layer of ir extension, // call into it E_Type *type = e_type_from_key__cached(result.type_key); if(type->kind != E_TypeKind_LensSpec && type->irext != 0) @@ -2382,7 +2400,14 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) result.user_data = ext.user_data; } + //- rjf: equip previous task's irtree + if(t->prev != 0) + { + result.prev = t->prev; + } + //- rjf: find any auto hooks according to this generation's type + if(allow_autohooks) { E_ExprList exprs = e_auto_hook_exprs_from_type_key__cached(result.type_key); for(E_ExprNode *n = exprs.first; n != 0; n = n->next) @@ -2395,6 +2420,8 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) Task *task = push_array(scratch.arena, Task, 1); SLLQueuePush(first_task, last_task, task); task->expr = e; + task->prev = push_array(arena, E_IRTreeAndType, 1); + task->prev[0] = result; break; } } @@ -2402,6 +2429,11 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) } } + ////////////////////////////// + //- rjf: reset the overridden irtree to whatever it was before this task list + // + e_ir_state->overridden_irtree = start_prev; + ////////////////////////////// //- rjf: unpoison the tags we used // diff --git a/src/eval/eval_ir.h b/src/eval/eval_ir.h index 134f26dc..ea560063 100644 --- a/src/eval/eval_ir.h +++ b/src/eval/eval_ir.h @@ -152,6 +152,9 @@ struct E_IRState // rjf: unpacked ctx RDI_Procedure *thread_ip_procedure; + // rjf: overridden irtree + E_IRTreeAndType *overridden_irtree; + // rjf: caches E_UsedExprMap *used_expr_map; E_TypeAutoHookCacheMap *type_auto_hook_cache_map; diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index b3da6013..fde022df 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -1624,7 +1624,7 @@ struct Bitmap int width; int height; }; -// raddbg_auto_view_rule(Bitmap, bitmap(base, width, height)); +raddbg_auto_view_rule(Bitmap, lens:bitmap($.base, $.width, $.height)); static unsigned int mule_bswap_u32(unsigned int x) diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 9ba31be5..347d2168 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -4056,7 +4056,10 @@ rd_view_ui(Rng2F32 rect) } // rjf: view ui contents + E_IRTreeAndType *prev_overridden_irtree = e_ir_state->overridden_irtree; + e_ir_state->overridden_irtree = cell_info.eval.irtree.prev; cell_info.view_ui_rule->ui(cell_info.eval, cell_rect); + e_ir_state->overridden_irtree = prev_overridden_irtree; // rjf: loading fill UI_Parent(loading_overlay_container) @@ -4475,7 +4478,10 @@ rd_view_ui(Rng2F32 rect) Temp scratch = scratch_begin(0, 0); RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(view_name); E_Eval expr_eval = e_eval_from_string(scratch.arena, expr_string); + E_IRTreeAndType *prev_overridden_irtree = e_ir_state->overridden_irtree; + e_ir_state->overridden_irtree = expr_eval.irtree.prev; view_ui_rule->ui(expr_eval, rect); + e_ir_state->overridden_irtree = prev_overridden_irtree; scratch_end(scratch); } }