checkpoint in switching to new call-style of view rules for everything

This commit is contained in:
Ryan Fleury
2025-04-07 08:02:11 -07:00
parent 0c999d70dc
commit 710828c67d
7 changed files with 115 additions and 136 deletions
-2
View File
@@ -321,8 +321,6 @@ struct E_Expr
{
E_Expr *first;
E_Expr *last;
E_Expr *first_tag;
E_Expr *last_tag;
E_Expr *next;
E_Expr *prev;
E_Expr *ref;
+86 -96
View File
@@ -77,9 +77,9 @@ e_select_ir_ctx(E_IRCtx *ctx)
if(ctx->macro_map == 0) { ctx->macro_map = push_array(e_ir_state->arena, E_String2ExprMap, 1); ctx->macro_map[0] = e_string2expr_map_make(e_ir_state->arena, 512); }
e_ir_state->ctx = ctx;
e_ir_state->thread_ip_procedure = rdi_procedure_from_voff(ctx->primary_module->rdi, ctx->thread_ip_voff);
e_ir_state->used_tag_map = push_array(e_ir_state->arena, E_UsedTagMap, 1);
e_ir_state->used_tag_map->slots_count = 64;
e_ir_state->used_tag_map->slots = push_array(e_ir_state->arena, E_UsedTagSlot, e_ir_state->used_tag_map->slots_count);
e_ir_state->used_expr_map = push_array(e_ir_state->arena, E_UsedExprMap, 1);
e_ir_state->used_expr_map->slots_count = 64;
e_ir_state->used_expr_map->slots = push_array(e_ir_state->arena, E_UsedExprSlot, e_ir_state->used_expr_map->slots_count);
e_ir_state->type_auto_hook_cache_map = push_array(e_ir_state->arena, E_TypeAutoHookCacheMap, 1);
e_ir_state->type_auto_hook_cache_map->slots_count = 256;
e_ir_state->type_auto_hook_cache_map->slots = push_array(e_ir_state->arena, E_TypeAutoHookCacheSlot, e_ir_state->type_auto_hook_cache_map->slots_count);
@@ -1304,7 +1304,7 @@ e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *
}
internal E_ExprList
e_auto_hook_tag_exprs_from_type_key(Arena *arena, E_TypeKey type_key)
e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key)
{
ProfBeginFunction();
E_ExprList exprs = {0};
@@ -1371,7 +1371,7 @@ 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)
e_auto_hook_exprs_from_type_key__cached(E_TypeKey type_key)
{
E_ExprList exprs = {0};
if(e_ir_state != 0 && e_ir_state->ctx != 0 && e_ir_state->type_auto_hook_cache_map != 0 && e_ir_state->type_auto_hook_cache_map->slots_count != 0)
@@ -1393,7 +1393,7 @@ e_auto_hook_tag_exprs_from_type_key__cached(E_TypeKey type_key)
node = push_array(e_ir_state->arena, E_TypeAutoHookCacheNode, 1);
SLLQueuePush(e_ir_state->type_auto_hook_cache_map->slots[slot_idx].first, e_ir_state->type_auto_hook_cache_map->slots[slot_idx].last, node);
node->key = type_key;
node->exprs = e_auto_hook_tag_exprs_from_type_key(e_type_state->arena, type_key);
node->exprs = e_auto_hook_exprs_from_type_key(e_type_state->arena, type_key);
}
exprs = node->exprs;
}
@@ -1759,14 +1759,14 @@ e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_Type
//- rjf: rule tag poison checking
internal B32
e_tag_is_poisoned(E_Expr *tag)
e_expr_is_poisoned(E_Expr *expr)
{
B32 tag_is_poisoned = 0;
U64 hash = e_hash_from_string(5381, str8_struct(&tag));
U64 slot_idx = hash%e_ir_state->used_tag_map->slots_count;
for(E_UsedTagNode *n = e_ir_state->used_tag_map->slots[slot_idx].first; n != 0; n = n->next)
U64 hash = e_hash_from_string(5381, str8_struct(&expr));
U64 slot_idx = hash%e_ir_state->used_expr_map->slots_count;
for(E_UsedExprNode *n = e_ir_state->used_expr_map->slots[slot_idx].first; n != 0; n = n->next)
{
if(n->tag == tag)
if(n->expr == expr)
{
tag_is_poisoned = 1;
break;
@@ -1776,25 +1776,25 @@ e_tag_is_poisoned(E_Expr *tag)
}
internal void
e_tag_poison(E_Expr *tag)
e_expr_poison(E_Expr *expr)
{
U64 hash = e_hash_from_string(5381, str8_struct(&tag));
U64 slot_idx = hash%e_ir_state->used_tag_map->slots_count;
E_UsedTagNode *n = push_array(e_ir_state->arena, E_UsedTagNode, 1);
n->tag = tag;
DLLPushBack(e_ir_state->used_tag_map->slots[slot_idx].first, e_ir_state->used_tag_map->slots[slot_idx].last, n);
U64 hash = e_hash_from_string(5381, str8_struct(&expr));
U64 slot_idx = hash%e_ir_state->used_expr_map->slots_count;
E_UsedExprNode *n = push_array(e_ir_state->arena, E_UsedExprNode, 1);
n->expr = expr;
DLLPushBack(e_ir_state->used_expr_map->slots[slot_idx].first, e_ir_state->used_expr_map->slots[slot_idx].last, n);
}
internal void
e_tag_unpoison(E_Expr *tag)
e_expr_unpoison(E_Expr *expr)
{
U64 hash = e_hash_from_string(5381, str8_struct(&tag));
U64 slot_idx = hash%e_ir_state->used_tag_map->slots_count;
for(E_UsedTagNode *n = e_ir_state->used_tag_map->slots[slot_idx].first; n != 0; n = n->next)
U64 hash = e_hash_from_string(5381, str8_struct(&expr));
U64 slot_idx = hash%e_ir_state->used_expr_map->slots_count;
for(E_UsedExprNode *n = e_ir_state->used_expr_map->slots[slot_idx].first; n != 0; n = n->next)
{
if(n->tag == tag)
if(n->expr == expr)
{
DLLRemove(e_ir_state->used_tag_map->slots[slot_idx].first, e_ir_state->used_tag_map->slots[slot_idx].last, n);
DLLRemove(e_ir_state->used_expr_map->slots[slot_idx].first, e_ir_state->used_expr_map->slots[slot_idx].last, n);
break;
}
}
@@ -1818,14 +1818,14 @@ E_IRGEN_FUNCTION_DEF(default)
E_Expr *lhs = expr->first;
E_Expr *rhs = lhs->next;
E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(scratch.arena, lhs);
E_LookupRuleTagPair lhs_lookup_rule_and_tag = e_lookup_rule_tag_pair_from_expr_irtree(lhs, &lhs_irtree);
ProfScope("lookup via rule '%.*s'", str8_varg(lhs_lookup_rule_and_tag.rule->name))
E_LookupRule *lookup_rule = e_lookup_rule_from_irtree(&lhs_irtree);
ProfScope("lookup via rule '%.*s'", str8_varg(lhs_lookup_rule->name))
{
e_tag_poison(lhs_lookup_rule_and_tag.tag);
e_expr_poison(lhs_lookup_rule_and_tag.tag);
E_LookupInfo lookup_info = lhs_lookup_rule_and_tag.rule->info(arena, &lhs_irtree, lhs_lookup_rule_and_tag.tag, str8_zero());
E_LookupAccess lookup_access = lhs_lookup_rule_and_tag.rule->access(arena, expr->kind, lhs, rhs, lhs_lookup_rule_and_tag.tag, lookup_info.user_data);
result = lookup_access.irtree_and_type;
e_tag_unpoison(lhs_lookup_rule_and_tag.tag);
e_expr_unpoison(lhs_lookup_rule_and_tag.tag);
}
scratch_end(scratch);
}break;
@@ -2425,26 +2425,30 @@ E_IRGEN_FUNCTION_DEF(default)
{
E_Expr *lhs = expr->first;
E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs);
E_TypeKey lhs_type_key = lhs_irtree.type_key;
E_Type *lhs_type = e_type_from_key__cached(lhs_type_key);
if(lhs_type->kind == E_TypeKind_Stub)
// rjf: map callee -> ir-generation rule
E_IRGenRule *irgen_rule = &e_irgen_rule__default;
{
Temp scratch = scratch_begin(&arena, 1);
E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs_irtree.root);
String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist);
E_Interpretation interp = e_interpret(bytecode);
String8 name = e_string_from_id(interp.value.u64);
E_IRGenRule *irgen_rule = e_irgen_rule_from_string(name);
if(irgen_rule != &e_irgen_rule__default)
E_TypeKey type_key = lhs_irtree.type_key;
E_Type *type = e_type_from_key__cached(type_key);
if(type->kind == E_TypeKind_Stub)
{
result = irgen_rule->irgen(arena, expr);
}
else
{
e_msgf(arena, &result.msgs, E_MsgKind_InterpretationError, expr->location, "There is no rule named `%S`.", name);
E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs_irtree.root);
String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist);
E_Interpretation interp = e_interpret(bytecode);
String8 name = e_string_from_id(interp.value.u64);
irgen_rule = e_irgen_rule_from_string(name);
}
scratch_end(scratch);
}
// rjf: if we have a non-default ir-generation rule, then we can use that
// to generate the resultant IR tree
if(irgen_rule != &e_irgen_rule__default)
{
result = irgen_rule->irgen(arena, expr);
}
else
{
e_msgf(arena, &result.msgs, E_MsgKind_InterpretationError, expr->location, "Calling this type is not currently supported.");
@@ -3024,76 +3028,38 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr)
expr = expr->ref;
}
//- rjf: pick the ir-generation rule from explicitly-stored expressions
B32 default_is_forced = 0;
E_IRGenRule *explicit_irgen_rule = &e_irgen_rule__default;
E_Expr *explicit_irgen_rule_tag = &e_expr_nil;
for(E_Expr *tag = expr->first_tag; tag != &e_expr_nil; tag = tag->next)
{
String8 name = tag->string;
E_IRGenRule *irgen_rule_candidate = e_irgen_rule_from_string(name);
if(str8_match(name, e_irgen_rule__default.name, 0))
{
default_is_forced = 1;
break;
}
if(irgen_rule_candidate != &e_irgen_rule__default)
{
B32 tag_is_poisoned = e_tag_is_poisoned(tag);
if(!tag_is_poisoned)
{
explicit_irgen_rule = irgen_rule_candidate;
explicit_irgen_rule_tag = tag;
}
}
}
//- rjf: apply all ir-generation steps
typedef struct Task Task;
struct Task
{
Task *next;
E_IRGenRule *rule;
E_Expr *tag;
E_Expr *expr;
};
Task start_task = {0, explicit_irgen_rule, explicit_irgen_rule_tag};
Task start_task = {0, expr};
Task *first_task = &start_task;
Task *last_task = first_task;
for(Task *t = first_task; t != 0; t = t->next)
{
// rjf: poison the tag we are about to use, so we don't recursively use it
e_tag_poison(t->tag);
e_expr_poison(t->expr);
// rjf: do this rule's generation
ProfScope("irgen rule '%.*s'", str8_varg(t->rule->name))
{
result = t->rule->irgen(arena, expr);
if(result.root == &e_irnode_nil && t->rule != &e_irgen_rule__default)
{
result = e_irgen_rule__default.irgen(arena, expr);
}
}
result = e_irgen_rule__default.irgen(arena, t->expr);
// rjf: find any auto hooks according to this generation's type
if(!default_is_forced)
{
E_ExprList exprs = e_auto_hook_tag_exprs_from_type_key__cached(result.type_key);
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)
{
for(E_Expr *tag = n->v; tag != &e_expr_nil; tag = tag->next)
for(E_Expr *e = n->v; e != &e_expr_nil; e = e->next)
{
B32 tag_is_poisoned = e_tag_is_poisoned(tag);
if(!tag_is_poisoned)
B32 e_is_poisoned = e_expr_is_poisoned(e);
if(!e_is_poisoned)
{
E_IRGenRule *rule = e_irgen_rule_from_string(tag->string);
if(rule != &e_irgen_rule__default)
{
Task *task = push_array(scratch.arena, Task, 1);
SLLQueuePush(first_task, last_task, task);
task->rule = rule;
task->tag = tag;
break;
}
Task *task = push_array(scratch.arena, Task, 1);
SLLQueuePush(first_task, last_task, task);
task->expr = e;
break;
}
}
}
@@ -3103,7 +3069,7 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr)
//- rjf: unpoison the tags we used
for(Task *t = first_task; t != 0; t = t->next)
{
e_tag_unpoison(t->tag);
e_expr_unpoison(t->expr);
}
scratch_end(scratch);
@@ -3378,7 +3344,31 @@ e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_Type
}
////////////////////////////////
//~ rjf: Expression & IR-Tree => Lookup Rule
//~ rjf: Expression & IR-Tree => Rules
internal E_LookupRule *
e_lookup_rule_from_irtree(E_IRTreeAndType *irtree)
{
E_LookupRule *rule = &e_lookup_rule__default;
E_TypeKey type_key = irtree->type_key;
E_Type *type = e_type_from_key__cached(type_key);
// rjf: first try implicit stub name -> rule mapping
if(rule == &e_lookup_rule__default && type->kind == E_TypeKind_Stub)
{
String8 name = type->name;
rule = e_lookup_rule_from_string(name);
}
// rjf: try auto hook map
if(rule == &e_lookup_rule__default)
{
E_ExprList tags = e_auto_hook_exprs_from_type_key__cached(irtree->type_key);
}
return rule;
}
internal E_LookupRuleTagPair
e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree)
@@ -3391,7 +3381,7 @@ e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree)
{
for(E_Expr *tag = expr->first_tag; tag != &e_expr_nil; tag = tag->next)
{
if(e_tag_is_poisoned(tag)) { continue; }
if(e_expr_is_poisoned(tag)) { continue; }
if(str8_match(tag->string, e_lookup_rule__default.name, 0))
{
result.rule = &e_lookup_rule__default;
@@ -3427,10 +3417,10 @@ e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree)
// rjf: next try auto hook map
if(!default_is_forced && result.rule == &e_lookup_rule__default)
{
E_ExprList tags = e_auto_hook_tag_exprs_from_type_key__cached(irtree->type_key);
E_ExprList tags = e_auto_hook_exprs_from_type_key__cached(irtree->type_key);
for(E_ExprNode *n = tags.first; n != 0; n = n->next)
{
if(e_tag_is_poisoned(n->v)) { continue; }
if(e_expr_is_poisoned(n->v)) { continue; }
E_LookupRule *candidate = e_lookup_rule_from_string(n->v->string);
if(candidate != &e_lookup_rule__nil)
{
+21 -20
View File
@@ -35,26 +35,26 @@ struct E_OpList
////////////////////////////////
//~ rjf: Used Tag Map Data Structure
typedef struct E_UsedTagNode E_UsedTagNode;
struct E_UsedTagNode
typedef struct E_UsedExprNode E_UsedExprNode;
struct E_UsedExprNode
{
E_UsedTagNode *next;
E_UsedTagNode *prev;
E_Expr *tag;
E_UsedExprNode *next;
E_UsedExprNode *prev;
E_Expr *expr;
};
typedef struct E_UsedTagSlot E_UsedTagSlot;
struct E_UsedTagSlot
typedef struct E_UsedExprSlot E_UsedExprSlot;
struct E_UsedExprSlot
{
E_UsedTagNode *first;
E_UsedTagNode *last;
E_UsedExprNode *first;
E_UsedExprNode *last;
};
typedef struct E_UsedTagMap E_UsedTagMap;
struct E_UsedTagMap
typedef struct E_UsedExprMap E_UsedExprMap;
struct E_UsedExprMap
{
U64 slots_count;
E_UsedTagSlot *slots;
E_UsedExprSlot *slots;
};
////////////////////////////////
@@ -155,7 +155,7 @@ struct E_IRState
RDI_Procedure *thread_ip_procedure;
// rjf: caches
E_UsedTagMap *used_tag_map;
E_UsedExprMap *used_expr_map;
E_TypeAutoHookCacheMap *type_auto_hook_cache_map;
U64 string_id_gen;
E_StringIDMap *string_id_map;
@@ -225,8 +225,8 @@ internal E_IRGenRule *e_irgen_rule_from_string(String8 string);
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, 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);
internal E_ExprList e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key);
internal E_ExprList e_auto_hook_exprs_from_type_key__cached(E_TypeKey type_key);
////////////////////////////////
//~ rjf: Evaluated String IDs
@@ -266,10 +266,10 @@ internal E_IRNode *e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key)
internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in);
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
//- rjf: rule tag poison checking
internal B32 e_tag_is_poisoned(E_Expr *tag);
internal void e_tag_poison(E_Expr *tag);
internal void e_tag_unpoison(E_Expr *tag);
//- rjf: expression poison checking
internal B32 e_expr_is_poisoned(E_Expr *expr);
internal void e_expr_poison(E_Expr *expr);
internal void e_expr_unpoison(E_Expr *expr);
//- rjf: top-level irtree/type extraction
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
@@ -286,8 +286,9 @@ internal E_Expr *e_expr_irext_deref(Arena *arena, E_Expr *rhs, E_IRTreeAndType *
internal E_Expr *e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_TypeKey type_key);
////////////////////////////////
//~ rjf: Expression & IR-Tree => Lookup Rule
//~ rjf: Expression & IR-Tree => Rules
internal E_LookupRule *e_lookup_rule_from_irtree(E_IRTreeAndType *irtree);
internal E_LookupRuleTagPair e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree);
#endif // EVAL_IR_H
+1 -15
View File
@@ -341,7 +341,7 @@ internal E_Expr *
e_push_expr(Arena *arena, E_ExprKind kind, void *location)
{
E_Expr *e = push_array(arena, E_Expr, 1);
e->first = e->last = e->next = e->prev = e->ref = e->first_tag = e->last_tag = &e_expr_nil;
e->first = e->last = e->next = e->prev = e->ref = &e_expr_nil;
e->location = location;
e->kind = kind;
return e;
@@ -365,12 +365,6 @@ e_expr_remove_child(E_Expr *parent, E_Expr *child)
DLLRemove_NPZ(&e_expr_nil, parent->first, parent->last, child, next, prev);
}
internal void
e_expr_push_tag(E_Expr *parent, E_Expr *child)
{
DLLPushBack_NPZ(&e_expr_nil, parent->first_tag, parent->last_tag, child, next, prev);
}
internal E_Expr *
e_expr_ref(Arena *arena, E_Expr *ref)
{
@@ -460,14 +454,6 @@ e_expr_copy(Arena *arena, E_Expr *src)
task->src = src_child;
SLLQueuePush(first_task, last_task, task);
}
for(E_Expr *src_child = t->src->first_tag; src_child != &e_expr_nil; src_child = src_child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
task->dst_parent = dst;
task->src = src_child;
task->is_tag = 1;
SLLQueuePush(first_task, last_task, task);
}
}
}
scratch_end(scratch);
-1
View File
@@ -69,7 +69,6 @@ internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, void *location);
internal void e_expr_insert_child(E_Expr *parent, E_Expr *prev, E_Expr *child);
internal void e_expr_push_child(E_Expr *parent, E_Expr *child);
internal void e_expr_remove_child(E_Expr *parent, E_Expr *child);
internal void e_expr_push_tag(E_Expr *parent, E_Expr *child);
internal E_Expr *e_expr_ref(Arena *arena, E_Expr *ref);
internal E_Expr *e_expr_ref_deref(Arena *arena, E_Expr *rhs);
internal E_Expr *e_expr_ref_cast(Arena *arena, E_TypeKey type_key, E_Expr *rhs);
@@ -509,7 +509,7 @@ ev_keyed_expr_push_tags(Arena *arena, EV_View *view, EV_Block *block, EV_Key key
// rjf: push tags inferred from the type
{
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
E_ExprList tags = e_auto_hook_tag_exprs_from_type_key__cached(irtree.type_key);
E_ExprList tags = e_auto_hook_exprs_from_type_key__cached(irtree.type_key);
for(E_ExprNode *n = tags.first; n != 0; n = n->next)
{
e_expr_push_tag(expr, e_expr_copy(arena, n->v));
@@ -1596,7 +1596,7 @@ ev_expand_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree)
// rjf: next try auto hook map
if(result.rule == &ev_nil_expand_rule)
{
E_ExprList tags = e_auto_hook_tag_exprs_from_type_key__cached(irtree->type_key);
E_ExprList tags = e_auto_hook_exprs_from_type_key__cached(irtree->type_key);
for(E_ExprNode *n = tags.first; n != 0; n = n->next)
{
EV_ExpandRule *candidate = ev_expand_rule_from_string(n->v->string);
+5
View File
@@ -93,6 +93,11 @@
// [ ] need a formalization which takes unknown identifiers which are called, and tries
// to use that to apply a IR-generation rule, which is keyed by that unknown
// identifier
// [ ] we need to select expressions as "parents" when possible, so that when using an
// auto-view-rule (or similar context), leaf identifiers referring to e.g. members
// of an expression's type resolve correctly (e.g. bitmap(base, width, height) being
// used as a shorthand for bitmap(foo.base, foo.width, foo.height) when evaluating
// foo).
// [ ] *ALL* expressions in watch windows need to be editable.
//
// [ ] config hot-reloading, using cfg wins