eliminate all old evaluation bundled helpers, eliminate old fragmented eval caches; move all to unified evaluation cache

This commit is contained in:
Ryan Fleury
2025-04-24 09:07:29 -07:00
parent c341fb6c00
commit 9bb592786a
24 changed files with 1315 additions and 1489 deletions
+17 -12
View File
@@ -217,6 +217,16 @@ ctrl_handle_from_string(String8 string)
return handle;
}
internal E_Eval
ctrl_eval_from_handle(CTRL_Handle handle)
{
Temp scratch = scratch_begin(0, 0);
String8 string = ctrl_string_from_handle(scratch.arena, handle);
E_Eval eval = e_eval_from_string(string);
scratch_end(scratch);
return eval;
}
////////////////////////////////
//~ rjf: Trap Type Functions
@@ -1412,6 +1422,7 @@ ctrl_init(void)
scratch_end(scratch);
}
ctrl_state->ctrl_thread_entity_store = ctrl_entity_store_alloc();
ctrl_state->ctrl_thread_eval_cache = e_cache_alloc();
ctrl_state->dmn_event_arena = arena_alloc();
ctrl_state->user_entry_point_arena = arena_alloc();
ctrl_state->dbg_dir_arena = arena_alloc();
@@ -4754,6 +4765,11 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
}
}
//////////////////////////////
//- rjf: select evaluation cache
//
e_select_cache(ctrl_state->ctrl_thread_eval_cache);
//////////////////////////////
//- rjf: build base evaluation context
//
@@ -4778,12 +4794,6 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
}
e_select_base_ctx(&scope->base_ctx);
//////////////////////////////
//- rjf: begin type evaluation
//
e_parse_eval_begin();
e_type_eval_begin();
//////////////////////////////
//- rjf: build IR evaluation context
//
@@ -4819,11 +4829,6 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
}
e_select_interpret_ctx(&scope->interpret_ctx, eval_modules_primary->rdi, thread_rip_voff);
////////////////////////////
//- rjf: begin cached evaluations
//
e_cache_eval_begin();
return scope;
}
@@ -5886,7 +5891,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
E_Eval eval = zero_struct;
ProfScope("evaluate expression")
{
eval = e_eval_from_string(temp.arena, condition_n->string);
eval = e_eval_from_string(condition_n->string);
}
// rjf: interpret evaluation
+3
View File
@@ -709,6 +709,7 @@ struct CTRL_State
OS_Handle ctrl_thread;
Log *ctrl_thread_log;
CTRL_EntityStore *ctrl_thread_entity_store;
E_Cache *ctrl_thread_eval_cache;
Arena *dmn_event_arena;
DMN_EventNode *first_dmn_event_node;
DMN_EventNode *last_dmn_event_node;
@@ -769,6 +770,8 @@ internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b);
internal void ctrl_handle_list_push(Arena *arena, CTRL_HandleList *list, CTRL_Handle *pair);
internal CTRL_HandleList ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src);
internal String8 ctrl_string_from_handle(Arena *arena, CTRL_Handle handle);
internal CTRL_Handle ctrl_handle_from_string(String8 string);
internal E_Eval ctrl_eval_from_handle(CTRL_Handle handle);
////////////////////////////////
//~ rjf: Trap Type Functions
+4 -58
View File
@@ -4,6 +4,7 @@
////////////////////////////////
//~ rjf: Bundled Evaluation Functions
#if 0
internal E_Eval
e_eval_from_expr(Arena *arena, E_Expr *expr)
{
@@ -144,63 +145,6 @@ e_dynamically_typed_eval_from_eval(E_Eval eval)
return eval;
}
internal E_Eval
e_value_eval_from_eval(E_Eval eval)
{
ProfBeginFunction();
if(eval.irtree.mode == E_Mode_Offset)
{
E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(type_kind == E_TypeKind_Array)
{
eval.irtree.mode = E_Mode_Value;
}
else
{
U64 type_byte_size = e_type_byte_size_from_key(type_key);
Rng1U64 value_vaddr_range = r1u64(eval.value.u64, eval.value.u64 + type_byte_size);
MemoryZeroStruct(&eval.value);
if(!e_type_key_match(type_key, e_type_key_zero()) &&
type_byte_size <= sizeof(E_Value) &&
e_space_read(eval.space, &eval.value, value_vaddr_range))
{
eval.irtree.mode = E_Mode_Value;
// rjf: mask&shift, for bitfields
if(type_kind == E_TypeKind_Bitfield && type_byte_size <= sizeof(U64))
{
Temp scratch = scratch_begin(0, 0);
E_Type *type = e_type_from_key__cached(type_key);
U64 valid_bits_mask = 0;
for(U64 idx = 0; idx < type->count; idx += 1)
{
valid_bits_mask |= (1ull<<idx);
}
eval.value.u64 = eval.value.u64 >> type->off;
eval.value.u64 = eval.value.u64 & valid_bits_mask;
eval.irtree.type_key = type->direct_type_key;
scratch_end(scratch);
}
// rjf: manually sign-extend
switch(type_kind)
{
default: break;
case E_TypeKind_Char8:
case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u64);}break;
case E_TypeKind_Char16:
case E_TypeKind_S16: {eval.value.s64 = (S64)*((S16 *)&eval.value.u64);}break;
case E_TypeKind_Char32:
case E_TypeKind_S32: {eval.value.s64 = (S64)*((S32 *)&eval.value.u64);}break;
}
}
}
}
ProfEnd();
return eval;
}
internal E_Value
e_value_from_string(String8 string)
{
@@ -267,6 +211,8 @@ e_eval_wrapf(Arena *arena, E_Eval eval, char *fmt, ...)
return result;
}
#endif
internal U64
e_base_offset_from_eval(E_Eval eval)
{
@@ -389,7 +335,7 @@ e_debug_log_from_expr_string(Arena *arena, String8 string)
}
//- rjf: type
E_IRTreeAndType irtree = e_push_irtree_and_type_from_expr(scratch.arena, parse.expr);
E_IRTreeAndType irtree = e_push_irtree_and_type_from_expr(scratch.arena, 0, 0, 0, parse.expr);
{
str8_list_pushf(scratch.arena, &strings, " type:\n");
S32 indent = 2;
+2
View File
@@ -7,6 +7,7 @@
////////////////////////////////
//~ rjf: Bundled Evaluation Functions
#if 0
internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr);
internal E_Eval e_eval_from_string(Arena *arena, String8 string);
internal E_Eval e_eval_from_stringf(Arena *arena, char *fmt, ...);
@@ -18,6 +19,7 @@ internal E_Value e_value_from_expr(E_Expr *expr);
internal E_Value e_value_from_eval(E_Eval eval);
internal E_Eval e_eval_wrap(Arena *arena, E_Eval eval, String8 string);
internal E_Eval e_eval_wrapf(Arena *arena, E_Eval eval, char *fmt, ...);;
#endif
internal U64 e_base_offset_from_eval(E_Eval eval);
internal Rng1U64 e_range_from_eval(E_Eval eval);
-256
View File
@@ -1,256 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Basic Key Helpers
internal B32
e_key_match(E_Key a, E_Key b)
{
B32 result = (a.u64 == b.u64);
return result;
}
////////////////////////////////
//~ rjf: Cache Initialization (Required For All Subsequent APIs)
internal void
e_cache_eval_begin(void)
{
if(e_cache == 0)
{
Arena *arena = arena_alloc();
e_cache = push_array(arena, E_Cache, 1);
e_cache->arena = arena;
e_cache->arena_eval_start_pos = arena_pos(arena);
}
arena_pop_to(e_cache->arena, e_cache->arena_eval_start_pos);
e_cache->key_id_gen = 0;
e_cache->key_slots_count = 4096;
e_cache->key_slots = push_array(e_cache->arena, E_CacheSlot, e_cache->key_slots_count);
e_cache->string_slots_count = 4096;
e_cache->string_slots = push_array(e_cache->arena, E_CacheSlot, e_cache->string_slots_count);
e_cache->free_parent_node = 0;
e_cache->top_parent_node = 0;
}
////////////////////////////////
//~ rjf: Cache Accessing Functions
//- rjf: parent key stack
internal E_Key
e_parent_key_push(E_Key key)
{
E_Key top = {0};
if(e_cache->top_parent_node != 0)
{
top = e_cache->top_parent_node->key;
}
E_CacheParentNode *n = e_cache->free_parent_node;
if(n != 0)
{
SLLStackPop(e_cache->free_parent_node);
}
else
{
n = push_array(e_cache->arena, E_CacheParentNode, 1);
}
SLLStackPush(e_cache->top_parent_node, n);
n->key = key;
return top;
}
internal E_Key
e_parent_key_pop(void)
{
E_CacheParentNode *n = e_cache->top_parent_node;
SLLStackPop(e_cache->top_parent_node);
SLLStackPush(e_cache->free_parent_node, n);
E_Key popped = n->key;
return popped;
}
//- rjf: key construction
internal E_Key
e_key_from_string(String8 string)
{
E_Key parent_key = {0};
if(e_cache->top_parent_node)
{
parent_key = e_cache->top_parent_node->key;
}
U64 hash = e_hash_from_string(parent_key.u64, string);
U64 slot_idx = hash%e_cache->string_slots_count;
E_CacheSlot *slot = &e_cache->string_slots[slot_idx];
E_CacheNode *node = 0;
for(E_CacheNode *n = slot->first; n != 0; n = n->string_next)
{
if(e_key_match(parent_key, n->bundle.parent_key) && str8_match(n->bundle.string, string, 0))
{
node = n;
break;
}
}
if(node == 0)
{
e_cache->key_id_gen += 1;
E_Key key = {e_cache->key_id_gen};
U64 key_hash = e_hash_from_string(5381, str8_struct(&key));
U64 key_slot_idx = key_hash%e_cache->key_slots_count;
E_CacheSlot *key_slot = &e_cache->key_slots[key_slot_idx];
node = push_array(e_cache->arena, E_CacheNode, 1);
node->key = key;
SLLQueuePush_N(slot->first, slot->last, node, string_next);
SLLQueuePush_N(key_slot->first, key_slot->last, node, key_next);
node->bundle.parent_key = parent_key;
node->bundle.string = push_str8_copy(e_cache->arena, string);
}
return node->key;
}
internal E_Key
e_key_from_stringf(char *fmt, ...)
{
Temp scratch = scratch_begin(0, 0);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
E_Key result = e_key_from_string(string);
va_end(args);
scratch_end(scratch);
return result;
}
//- rjf: base key -> node helper
internal E_CacheBundle *
e_cache_bundle_from_key(E_Key key)
{
U64 hash = e_hash_from_string(5381, str8_struct(&key));
U64 slot_idx = hash%e_cache->key_slots_count;
E_CacheSlot *slot = &e_cache->key_slots[slot_idx];
E_CacheNode *node = 0;
for(E_CacheNode *n = slot->first; n != 0; n = n->key_next)
{
if(e_key_match(n->key, key))
{
node = n;
break;
}
}
E_CacheBundle *bundle = &e_cache_bundle_nil;
if(node != 0)
{
bundle = &node->bundle;
}
return bundle;
}
//- rjf: bundle -> pipeline stage outputs
internal E_Parse
e_parse_from_bundle(E_CacheBundle *bundle)
{
if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Parse))
{
bundle->flags |= E_CacheBundleFlag_Parse;
bundle->parse = e_push_parse_from_string(e_cache->arena, bundle->string);
}
E_Parse parse = bundle->parse;
return parse;
}
internal E_IRTreeAndType
e_irtree_from_bundle(E_CacheBundle *bundle)
{
if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_IRTree))
{
bundle->flags |= E_CacheBundleFlag_IRTree;
E_IRTreeAndType overridden = e_irtree_from_key(bundle->parent_key);
E_IRTreeAndType *prev_overridden = e_ir_state->overridden_irtree;
e_ir_state->overridden_irtree = &overridden;
E_Parse parse = e_parse_from_bundle(bundle);
bundle->irtree = e_push_irtree_and_type_from_expr(e_cache->arena, parse.expr);
e_ir_state->overridden_irtree = prev_overridden;
}
E_IRTreeAndType result = bundle->irtree;
return result;
}
internal String8
e_bytecode_from_bundle(E_CacheBundle *bundle)
{
if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Bytecode))
{
bundle->flags |= E_CacheBundleFlag_Bytecode;
Temp scratch = scratch_begin(0, 0);
E_IRTreeAndType irtree = e_irtree_from_bundle(bundle);
E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree.root);
bundle->bytecode = e_bytecode_from_oplist(e_cache->arena, &oplist);
scratch_end(scratch);
}
String8 result = bundle->bytecode;
return result;
}
internal E_Interpretation
e_interpretation_from_bundle(E_CacheBundle *bundle)
{
if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Interpret))
{
bundle->flags |= E_CacheBundleFlag_Interpret;
String8 bytecode = e_bytecode_from_bundle(bundle);
E_Interpretation interpret = e_interpret(bytecode);
bundle->interpretation = interpret;
}
E_Interpretation interpret = bundle->interpretation;
return interpret;
}
//- rjf: comprehensive bundle
internal E_Eval
e_eval_from_bundle(E_CacheBundle *bundle)
{
E_Eval eval =
{
.expr = e_parse_from_bundle(bundle).expr,
.irtree = e_irtree_from_bundle(bundle),
.bytecode = e_bytecode_from_bundle(bundle),
};
E_Interpretation interpretation = e_interpretation_from_bundle(bundle);
eval.code = interpretation.code;
eval.value = interpretation.value;
eval.space = interpretation.space;
return eval;
}
//- rjf: string-based helpers
// TODO(rjf): (replace the old bundle APIs here)
////////////////////////////////
//~ rjf: Key Extension Functions
internal E_Key
e_key_wrap(E_Key key, String8 string)
{
e_parent_key_push(key);
E_Key result = e_key_from_string(string);
e_parent_key_pop();
return result;
}
internal E_Key
e_key_wrapf(E_Key key, char *fmt, ...)
{
Temp scratch = scratch_begin(0, 0);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
E_Key result = e_key_wrap(key, string);
va_end(args);
scratch_end(scratch);
return result;
}
-158
View File
@@ -1,158 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_CACHE_H
#define EVAL_CACHE_H
////////////////////////////////
//~ rjf: Cache Key Type
typedef struct E_Key E_Key;
struct E_Key
{
U64 u64;
};
////////////////////////////////
//~ rjf: Cache Types
typedef U32 E_CacheBundleFlags;
enum
{
E_CacheBundleFlag_Parse = (1<<0),
E_CacheBundleFlag_IRTree = (1<<1),
E_CacheBundleFlag_Bytecode = (1<<2),
E_CacheBundleFlag_Interpret = (1<<3),
};
typedef struct E_CacheBundle E_CacheBundle;
struct E_CacheBundle
{
E_CacheBundleFlags flags;
E_Key parent_key;
String8 string;
E_Parse parse;
E_IRTreeAndType irtree;
String8 bytecode;
E_Interpretation interpretation;
};
typedef struct E_CacheNode E_CacheNode;
struct E_CacheNode
{
E_CacheNode *string_next;
E_CacheNode *key_next;
E_Key key;
E_CacheBundle bundle;
};
typedef struct E_CacheLookup E_CacheLookup;
struct E_CacheLookup
{
E_CacheNode *node;
U64 hash;
};
typedef struct E_CacheSlot E_CacheSlot;
struct E_CacheSlot
{
E_CacheNode *first;
E_CacheNode *last;
};
typedef struct E_CacheParentNode E_CacheParentNode;
struct E_CacheParentNode
{
E_CacheParentNode *next;
E_Key key;
};
typedef struct E_Cache E_Cache;
struct E_Cache
{
Arena *arena;
U64 arena_eval_start_pos;
U64 key_id_gen;
U64 key_slots_count;
E_CacheSlot *key_slots;
U64 string_slots_count;
E_CacheSlot *string_slots;
E_CacheParentNode *top_parent_node;
E_CacheParentNode *free_parent_node;
};
////////////////////////////////
//~ rjf: Globals
thread_static E_Cache *e_cache = 0;
read_only global E_CacheBundle e_cache_bundle_nil = {0, {0}, {0}, {{0}, 0, &e_expr_nil, &e_expr_nil}, {&e_irnode_nil}};
////////////////////////////////
//~ rjf: Basic Key Helpers
internal B32 e_key_match(E_Key a, E_Key b);
////////////////////////////////
//~ rjf: Cache Initialization (Required For All Subsequent APIs)
internal void e_cache_eval_begin(void);
////////////////////////////////
//~ rjf: Cache Accessing Functions
//
// The cache uses a unique keying mechanism to refer to some evaluation at
// many layers of analysis.
//
// key
// ________________________________________________
// / / | \
// text -> expression -> ir tree and type -> interpretation result
//
// Each one of these calls refers to one stage in this pipeline. The cache will
// only compute what is needed on-demand. If you ask for the full evaluation,
// which is a bundle of artifacts at all layers of analysis, then all stages
// will be computed.
//
// One wrinkle here is that the IR tree generation stage is implicitly
// parameterized by the "overridden" IR tree - this is to enable "parent
// expressions", e.g. `$.x`, or simply `x` assuming `foo` has such a member,
// in the context of some struct `foo` evaluates to the same thing as `foo.x`.
// So even though the primary API shape is based around singular keys, the
// "parent key stack" also implicitly parameterizes all of these (partly
// because it is not relevant in 99% of cases).
//- rjf: parent key stack
internal E_Key e_parent_key_push(E_Key key);
internal E_Key e_parent_key_pop(void);
//- rjf: key construction
internal E_Key e_key_from_string(String8 string);
internal E_Key e_key_from_stringf(char *fmt, ...);
//- rjf: base key -> bundle helper
internal E_CacheBundle *e_cache_bundle_from_key(E_Key key);
//- rjf: bundle -> pipeline stage outputs
internal E_Parse e_parse_from_bundle(E_CacheBundle *bundle);
internal E_IRTreeAndType e_irtree_from_bundle(E_CacheBundle *bundle);
internal String8 e_bytecode_from_bundle(E_CacheBundle *bundle);
internal E_Interpretation e_interpretation_from_bundle(E_CacheBundle *bundle);
#define e_parse_from_key(key) e_parse_from_bundle(e_cache_bundle_from_key(key))
#define e_irtree_from_key(key) e_irtree_from_bundle(e_cache_bundle_from_key(key))
#define e_bytecode_from_key(key) e_bytecode_from_bundle(e_cache_bundle_from_key(key))
#define e_interpretation_from_key(key) e_interpretation_from_bundle(e_cache_bundle_from_key(key))
//- rjf: comprehensive bundle
internal E_Eval e_eval_from_bundle(E_CacheBundle *bundle);
#define e_eval_from_key(key) e_eval_from_bundle(e_cache_bundle_from_key(key))
//- rjf: string-based helpers
// TODO(rjf): (replace the old bundle APIs here)
////////////////////////////////
//~ rjf: Key Extension Functions
internal E_Key e_key_wrap(E_Key key, String8 string);
internal E_Key e_key_wrapf(E_Key key, char *fmt, ...);
#endif // EVAL_CACHE_H
+624 -6
View File
@@ -7,7 +7,7 @@
#include "eval/generated/eval.meta.c"
////////////////////////////////
//~ rjf: Basic Helper Functions
//~ rjf: Basic Helpers
#if !defined(XXH_IMPLEMENTATION)
# define XXH_IMPLEMENTATION
@@ -22,7 +22,72 @@ e_hash_from_string(U64 seed, String8 string)
return result;
}
//- rjf: type key data structures
////////////////////////////////
//~ rjf: Expr Kind Enum Functions
internal RDI_EvalOp
e_opcode_from_expr_kind(E_ExprKind kind)
{
RDI_EvalOp result = RDI_EvalOp_Stop;
switch(kind)
{
case E_ExprKind_Neg: result = RDI_EvalOp_Neg; break;
case E_ExprKind_LogNot: result = RDI_EvalOp_LogNot; break;
case E_ExprKind_BitNot: result = RDI_EvalOp_BitNot; break;
case E_ExprKind_Mul: result = RDI_EvalOp_Mul; break;
case E_ExprKind_Div: result = RDI_EvalOp_Div; break;
case E_ExprKind_Mod: result = RDI_EvalOp_Mod; break;
case E_ExprKind_Add: result = RDI_EvalOp_Add; break;
case E_ExprKind_Sub: result = RDI_EvalOp_Sub; break;
case E_ExprKind_LShift: result = RDI_EvalOp_LShift; break;
case E_ExprKind_RShift: result = RDI_EvalOp_RShift; break;
case E_ExprKind_Less: result = RDI_EvalOp_Less; break;
case E_ExprKind_LsEq: result = RDI_EvalOp_LsEq; break;
case E_ExprKind_Grtr: result = RDI_EvalOp_Grtr; break;
case E_ExprKind_GrEq: result = RDI_EvalOp_GrEq; break;
case E_ExprKind_EqEq: result = RDI_EvalOp_EqEq; break;
case E_ExprKind_NtEq: result = RDI_EvalOp_NtEq; break;
case E_ExprKind_BitAnd: result = RDI_EvalOp_BitAnd; break;
case E_ExprKind_BitXor: result = RDI_EvalOp_BitXor; break;
case E_ExprKind_BitOr: result = RDI_EvalOp_BitOr; break;
case E_ExprKind_LogAnd: result = RDI_EvalOp_LogAnd; break;
case E_ExprKind_LogOr: result = RDI_EvalOp_LogOr; break;
}
return result;
}
internal B32
e_expr_kind_is_comparison(E_ExprKind kind)
{
B32 result = 0;
switch(kind)
{
default:{}break;
case E_ExprKind_EqEq:
case E_ExprKind_NtEq:
case E_ExprKind_Less:
case E_ExprKind_Grtr:
case E_ExprKind_LsEq:
case E_ExprKind_GrEq:
{
result = 1;
}break;
}
return result;
}
////////////////////////////////
//~ rjf: Key Type Functions
internal B32
e_key_match(E_Key a, E_Key b)
{
B32 result = (a.u64 == b.u64);
return result;
}
////////////////////////////////
//~ rjf: Type Key Type Functions
internal void
e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key)
@@ -107,7 +172,7 @@ e_space_make(E_SpaceKind kind)
}
////////////////////////////////
//~ rjf: Basic Map Functions
//~ rjf: Map Functions
//- rjf: string -> num
@@ -277,7 +342,7 @@ e_string2expr_map_dec_poison(E_String2ExprMap *map, String8 string)
}
internal E_Expr *
e_string2expr_lookup(E_String2ExprMap *map, String8 string)
e_string2expr_map_lookup(E_String2ExprMap *map, String8 string)
{
E_Expr *expr = &e_expr_nil;
if(map->slots_count != 0)
@@ -340,6 +405,43 @@ e_string2typekey_map_lookup(E_String2TypeKeyMap *map, String8 string)
return key;
}
//- rjf: auto hooks
internal E_AutoHookMap
e_auto_hook_map_make(Arena *arena, U64 slots_count)
{
E_AutoHookMap map = {0};
map.slots_count = slots_count;
map.slots = push_array(arena, E_AutoHookSlot, map.slots_count);
return map;
}
internal void
e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params)
{
E_TypeKey type_key = params->type_key;
if(params->type_pattern.size != 0)
{
E_Parse parse = e_push_parse_from_string(arena, params->type_pattern);
type_key = e_type_key_from_expr(parse.expr);
}
E_AutoHookNode *node = push_array(arena, E_AutoHookNode, 1);
node->type_string = str8_skip_chop_whitespace(e_type_string_from_key(arena, type_key));
U8 pattern_split = '?';
node->type_pattern_parts = str8_split(arena, params->type_pattern, &pattern_split, 1, StringSplitFlag_KeepEmpties);
node->expr = e_parse_from_string(params->tag_expr_string).expr;
if(!e_type_key_match(e_type_key_zero(), type_key))
{
U64 hash = e_hash_from_string(5381, node->type_string);
U64 slot_idx = hash%map->slots_count;
SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next);
}
else
{
SLLQueuePush_N(map->first_pattern, map->last_pattern, node, pattern_order_next);
}
}
////////////////////////////////
//~ rjf: Debug-Info-Driven Map Building Functions
@@ -464,13 +566,529 @@ e_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff)
}
////////////////////////////////
//~ rjf: Base Evaluation Context Selection
//~ rjf: Cache Creation & Selection
internal E_Cache *
e_cache_alloc(void)
{
Arena *arena = arena_alloc();
E_Cache *cache = push_array(arena, E_Cache, 1);
cache->arena = arena;
cache->arena_eval_start_pos = arena_pos(arena);
return cache;
}
internal void
e_cache_release(E_Cache *cache)
{
arena_release(cache->arena);
}
internal void
e_select_cache(E_Cache *cache)
{
e_cache = cache;
}
////////////////////////////////
//~ rjf: Evaluation Phase Markers
internal void
e_select_base_ctx(E_BaseCtx *ctx)
{
//- rjf: select base context
if(ctx->modules == 0) { ctx->modules = &e_module_nil; }
if(ctx->primary_module == 0) { ctx->primary_module = &e_module_nil; }
e_base_ctx = ctx;
e_base_ctx_gen += 1;
//- rjf: reset the evaluation cache
arena_pop_to(e_cache->arena, e_cache->arena_eval_start_pos);
e_cache->key_id_gen = 0;
e_cache->key_slots_count = 4096;
e_cache->key_slots = push_array(e_cache->arena, E_CacheSlot, e_cache->key_slots_count);
e_cache->string_slots_count = 4096;
e_cache->string_slots = push_array(e_cache->arena, E_CacheSlot, e_cache->string_slots_count);
e_cache->free_parent_node = 0;
e_cache->top_parent_node = 0;
e_cache->cons_id_gen = 0;
e_cache->cons_content_slots_count = 256;
e_cache->cons_key_slots_count = 256;
e_cache->cons_content_slots = push_array(e_cache->arena, E_ConsTypeSlot, e_cache->cons_content_slots_count);
e_cache->cons_key_slots = push_array(e_cache->arena, E_ConsTypeSlot, e_cache->cons_key_slots_count);
e_cache->member_cache_slots_count = 256;
e_cache->member_cache_slots = push_array(e_cache->arena, E_MemberCacheSlot, e_cache->member_cache_slots_count);
e_cache->type_cache_slots_count = 1024;
e_cache->type_cache_slots = push_array(e_cache->arena, E_TypeCacheSlot, e_cache->type_cache_slots_count);
e_cache->file_type_key = e_type_key_cons(.kind = E_TypeKind_Set,
.name = str8_lit("file"),
.irext = E_TYPE_IREXT_FUNCTION_NAME(file),
.access = E_TYPE_ACCESS_FUNCTION_NAME(file),
.expand =
{
.info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(file),
.range= E_TYPE_EXPAND_RANGE_FUNCTION_NAME(file),
});
e_cache->folder_type_key = e_type_key_cons(.kind = E_TypeKind_Set,
.name = str8_lit("folder"),
.expand =
{
.info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(folder),
.range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(folder),
.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(folder),
.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(folder),
});
e_cache->thread_ip_procedure = rdi_procedure_from_voff(e_base_ctx->primary_module->rdi, e_base_ctx->thread_ip_voff);
e_cache->used_expr_map = push_array(e_cache->arena, E_UsedExprMap, 1);
e_cache->used_expr_map->slots_count = 64;
e_cache->used_expr_map->slots = push_array(e_cache->arena, E_UsedExprSlot, e_cache->used_expr_map->slots_count);
e_cache->type_auto_hook_cache_map = push_array(e_cache->arena, E_TypeAutoHookCacheMap, 1);
e_cache->type_auto_hook_cache_map->slots_count = 256;
e_cache->type_auto_hook_cache_map->slots = push_array(e_cache->arena, E_TypeAutoHookCacheSlot, e_cache->type_auto_hook_cache_map->slots_count);
e_cache->string_id_gen = 0;
e_cache->string_id_map = push_array(e_cache->arena, E_StringIDMap, 1);
e_cache->string_id_map->id_slots_count = 1024;
e_cache->string_id_map->id_slots = push_array(e_cache->arena, E_StringIDSlot, e_cache->string_id_map->id_slots_count);
e_cache->string_id_map->hash_slots_count = 1024;
e_cache->string_id_map->hash_slots = push_array(e_cache->arena, E_StringIDSlot, e_cache->string_id_map->hash_slots_count);
}
internal void
e_select_ir_ctx(E_IRCtx *ctx)
{
if(ctx->regs_map == 0) { ctx->regs_map = &e_string2num_map_nil; }
if(ctx->reg_alias_map == 0) { ctx->reg_alias_map = &e_string2num_map_nil; }
if(ctx->locals_map == 0) { ctx->locals_map = &e_string2num_map_nil; }
if(ctx->member_map == 0) { ctx->member_map = &e_string2num_map_nil; }
if(ctx->macro_map == 0) { ctx->macro_map = push_array(e_cache->arena, E_String2ExprMap, 1); ctx->macro_map[0] = e_string2expr_map_make(e_cache->arena, 512); }
e_ir_ctx = ctx;
}
////////////////////////////////
//~ rjf: Cache Accessing Functions
//- rjf: parent key stack
internal E_Key
e_parent_key_push(E_Key key)
{
E_Key top = {0};
if(e_cache->top_parent_node != 0)
{
top = e_cache->top_parent_node->key;
}
E_CacheParentNode *n = e_cache->free_parent_node;
if(n != 0)
{
SLLStackPop(e_cache->free_parent_node);
}
else
{
n = push_array(e_cache->arena, E_CacheParentNode, 1);
}
SLLStackPush(e_cache->top_parent_node, n);
n->key = key;
return top;
}
internal E_Key
e_parent_key_pop(void)
{
E_CacheParentNode *n = e_cache->top_parent_node;
SLLStackPop(e_cache->top_parent_node);
SLLStackPush(e_cache->free_parent_node, n);
E_Key popped = n->key;
return popped;
}
//- rjf: key construction
internal E_Key
e_key_from_string(String8 string)
{
E_Key parent_key = {0};
if(e_cache->top_parent_node)
{
parent_key = e_cache->top_parent_node->key;
}
U64 hash = e_hash_from_string(parent_key.u64, string);
U64 slot_idx = hash%e_cache->string_slots_count;
E_CacheSlot *slot = &e_cache->string_slots[slot_idx];
E_CacheNode *node = 0;
for(E_CacheNode *n = slot->first; n != 0; n = n->string_next)
{
if(e_key_match(parent_key, n->bundle.parent_key) && str8_match(n->bundle.string, string, 0))
{
node = n;
break;
}
}
if(node == 0)
{
e_cache->key_id_gen += 1;
E_Key key = {e_cache->key_id_gen};
U64 key_hash = e_hash_from_string(5381, str8_struct(&key));
U64 key_slot_idx = key_hash%e_cache->key_slots_count;
E_CacheSlot *key_slot = &e_cache->key_slots[key_slot_idx];
node = push_array(e_cache->arena, E_CacheNode, 1);
SLLQueuePush_N(slot->first, slot->last, node, string_next);
SLLQueuePush_N(key_slot->first, key_slot->last, node, key_next);
node->bundle.key = key;
node->bundle.parent_key = parent_key;
node->bundle.string = push_str8_copy(e_cache->arena, string);
}
return node->bundle.key;
}
internal E_Key
e_key_from_stringf(char *fmt, ...)
{
Temp scratch = scratch_begin(0, 0);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
E_Key result = e_key_from_string(string);
va_end(args);
scratch_end(scratch);
return result;
}
internal E_Key
e_key_from_expr(E_Expr *expr)
{
Temp scratch = scratch_begin(0, 0);
String8 string = e_string_from_expr(scratch.arena, expr, str8_zero());
E_Key key = e_key_from_string(string);
scratch_end(scratch);
return key;
}
//- rjf: base key -> node helper
internal E_CacheBundle *
e_cache_bundle_from_key(E_Key key)
{
U64 hash = e_hash_from_string(5381, str8_struct(&key));
U64 slot_idx = hash%e_cache->key_slots_count;
E_CacheSlot *slot = &e_cache->key_slots[slot_idx];
E_CacheNode *node = 0;
for(E_CacheNode *n = slot->first; n != 0; n = n->key_next)
{
if(e_key_match(n->bundle.key, key))
{
node = n;
break;
}
}
E_CacheBundle *bundle = &e_cache_bundle_nil;
if(node != 0)
{
bundle = &node->bundle;
}
return bundle;
}
//- rjf: bundle -> pipeline stage outputs
internal E_Parse
e_parse_from_bundle(E_CacheBundle *bundle)
{
if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Parse))
{
bundle->flags |= E_CacheBundleFlag_Parse;
bundle->parse = e_push_parse_from_string(e_cache->arena, bundle->string);
}
E_Parse parse = bundle->parse;
return parse;
}
internal E_IRTreeAndType
e_irtree_from_bundle(E_CacheBundle *bundle)
{
if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_IRTree))
{
bundle->flags |= E_CacheBundleFlag_IRTree;
E_IRTreeAndType overridden = e_irtree_from_key(bundle->parent_key);
E_Parse parse = e_parse_from_bundle(bundle);
bundle->irtree = e_push_irtree_and_type_from_expr(e_cache->arena, &overridden, 0, 0, parse.expr);
}
E_IRTreeAndType result = bundle->irtree;
return result;
}
internal String8
e_bytecode_from_bundle(E_CacheBundle *bundle)
{
if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Bytecode))
{
bundle->flags |= E_CacheBundleFlag_Bytecode;
Temp scratch = scratch_begin(0, 0);
E_IRTreeAndType irtree = e_irtree_from_bundle(bundle);
E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree.root);
bundle->bytecode = e_bytecode_from_oplist(e_cache->arena, &oplist);
scratch_end(scratch);
}
String8 result = bundle->bytecode;
return result;
}
internal E_Interpretation
e_interpretation_from_bundle(E_CacheBundle *bundle)
{
if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Interpret))
{
bundle->flags |= E_CacheBundleFlag_Interpret;
String8 bytecode = e_bytecode_from_bundle(bundle);
E_Interpretation interpret = e_interpret(bytecode);
bundle->interpretation = interpret;
}
E_Interpretation interpret = bundle->interpretation;
return interpret;
}
//- rjf: comprehensive bundle
internal E_Eval
e_eval_from_bundle(E_CacheBundle *bundle)
{
E_Eval eval =
{
.key = bundle->key,
.expr = e_parse_from_bundle(bundle).expr,
.irtree = e_irtree_from_bundle(bundle),
.bytecode = e_bytecode_from_bundle(bundle),
};
E_Interpretation interpretation = e_interpretation_from_bundle(bundle);
eval.code = interpretation.code;
eval.value = interpretation.value;
eval.space = interpretation.space;
return eval;
}
internal E_Eval
e_value_eval_from_eval(E_Eval eval)
{
ProfBeginFunction();
if(eval.irtree.mode == E_Mode_Offset)
{
E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(type_kind == E_TypeKind_Array)
{
eval.irtree.mode = E_Mode_Value;
}
else
{
U64 type_byte_size = e_type_byte_size_from_key(type_key);
Rng1U64 value_vaddr_range = r1u64(eval.value.u64, eval.value.u64 + type_byte_size);
MemoryZeroStruct(&eval.value);
if(!e_type_key_match(type_key, e_type_key_zero()) &&
type_byte_size <= sizeof(E_Value) &&
e_space_read(eval.space, &eval.value, value_vaddr_range))
{
eval.irtree.mode = E_Mode_Value;
// rjf: mask&shift, for bitfields
if(type_kind == E_TypeKind_Bitfield && type_byte_size <= sizeof(U64))
{
Temp scratch = scratch_begin(0, 0);
E_Type *type = e_type_from_key__cached(type_key);
U64 valid_bits_mask = 0;
for(U64 idx = 0; idx < type->count; idx += 1)
{
valid_bits_mask |= (1ull<<idx);
}
eval.value.u64 = eval.value.u64 >> type->off;
eval.value.u64 = eval.value.u64 & valid_bits_mask;
eval.irtree.type_key = type->direct_type_key;
scratch_end(scratch);
}
// rjf: manually sign-extend
switch(type_kind)
{
default: break;
case E_TypeKind_Char8:
case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u64);}break;
case E_TypeKind_Char16:
case E_TypeKind_S16: {eval.value.s64 = (S64)*((S16 *)&eval.value.u64);}break;
case E_TypeKind_Char32:
case E_TypeKind_S32: {eval.value.s64 = (S64)*((S32 *)&eval.value.u64);}break;
}
}
}
}
ProfEnd();
return eval;
}
//- rjf: string-based helpers
// TODO(rjf): (replace the old bundle APIs here)
//- rjf: type key -> auto hooks
internal E_ExprList
e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key)
{
ProfBeginFunction();
E_ExprList exprs = {0};
if(e_ir_ctx != 0)
{
Temp scratch = scratch_begin(&arena, 1);
E_AutoHookMap *map = e_ir_ctx->auto_hook_map;
String8 type_string = str8_skip_chop_whitespace(e_type_string_from_key(scratch.arena, type_key));
//- rjf: gather exact-type-key-matches from the map
if(map != 0 && map->slots_count != 0)
{
U64 hash = e_hash_from_string(5381, type_string);
U64 slot_idx = hash%map->slots_count;
for(E_AutoHookNode *n = map->slots[slot_idx].first; n != 0; n = n->hash_next)
{
if(str8_match(n->type_string, type_string, 0))
{
e_expr_list_push(arena, &exprs, n->expr);
}
}
}
//- rjf: gather fuzzy matches from all patterns in the map
if(map != 0 && map->first_pattern != 0)
{
for(E_AutoHookNode *auto_hook_node = map->first_pattern;
auto_hook_node != 0;
auto_hook_node = auto_hook_node->pattern_order_next)
{
B32 fits_this_type_string = 1;
U64 scan_pos = 0;
for(String8Node *n = auto_hook_node->type_pattern_parts.first; n != 0; n = n->next)
{
if(n->string.size == 0)
{
continue;
}
U64 pattern_part_pos = str8_find_needle(type_string, scan_pos, n->string, 0);
if(pattern_part_pos >= type_string.size)
{
fits_this_type_string = 0;
break;
}
scan_pos = pattern_part_pos + n->string.size;
}
if(fits_this_type_string)
{
e_expr_list_push(arena, &exprs, auto_hook_node->expr);
}
}
}
scratch_end(scratch);
}
ProfEnd();
return exprs;
}
internal E_ExprList
e_auto_hook_exprs_from_type_key__cached(E_TypeKey type_key)
{
E_ExprList exprs = {0};
{
U64 hash = e_hash_from_string(5381, str8_struct(&type_key));
U64 slot_idx = hash%e_cache->type_auto_hook_cache_map->slots_count;
E_TypeAutoHookCacheNode *node = 0;
for(E_TypeAutoHookCacheNode *n = e_cache->type_auto_hook_cache_map->slots[slot_idx].first;
n != 0;
n = n->next)
{
if(e_type_key_match(n->key, type_key))
{
node = n;
}
}
if(node == 0)
{
node = push_array(e_cache->arena, E_TypeAutoHookCacheNode, 1);
SLLQueuePush(e_cache->type_auto_hook_cache_map->slots[slot_idx].first, e_cache->type_auto_hook_cache_map->slots[slot_idx].last, node);
node->key = type_key;
node->exprs = e_auto_hook_exprs_from_type_key(e_cache->arena, type_key);
}
exprs = node->exprs;
}
return exprs;
}
//- rjf: string IDs
internal U64
e_id_from_string(String8 string)
{
U64 hash = e_hash_from_string(5381, string);
U64 hash_slot_idx = hash%e_cache->string_id_map->hash_slots_count;
E_StringIDNode *node = 0;
for(E_StringIDNode *n = e_cache->string_id_map->hash_slots[hash_slot_idx].first; n != 0; n = n->hash_next)
{
if(str8_match(n->string, string, 0))
{
node = n;
break;
}
}
if(node == 0)
{
e_cache->string_id_gen += 1;
U64 id = e_cache->string_id_gen;
U64 id_slot_idx = id%e_cache->string_id_map->id_slots_count;
node = push_array(e_cache->arena, E_StringIDNode, 1);
SLLQueuePush_N(e_cache->string_id_map->hash_slots[hash_slot_idx].first, e_cache->string_id_map->hash_slots[hash_slot_idx].last, node, hash_next);
SLLQueuePush_N(e_cache->string_id_map->id_slots[id_slot_idx].first, e_cache->string_id_map->hash_slots[id_slot_idx].last, node, id_next);
node->id = id;
node->string = push_str8_copy(e_cache->arena, string);
}
U64 result = node->id;
return result;
}
internal String8
e_string_from_id(U64 id)
{
U64 id_slot_idx = id%e_cache->string_id_map->id_slots_count;
E_StringIDNode *node = 0;
for(E_StringIDNode *n = e_cache->string_id_map->id_slots[id_slot_idx].first; n != 0; n = n->id_next)
{
if(n->id == id)
{
node = n;
break;
}
}
String8 result = {0};
if(node != 0)
{
result = node->string;
}
return result;
}
////////////////////////////////
//~ rjf: Key Extension Functions
internal E_Key
e_key_wrap(E_Key key, String8 string)
{
e_parent_key_push(key);
E_Key result = e_key_from_string(string);
e_parent_key_pop();
return result;
}
internal E_Key
e_key_wrapf(E_Key key, char *fmt, ...)
{
Temp scratch = scratch_begin(0, 0);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
E_Key result = e_key_wrap(key, string);
va_end(args);
scratch_end(scratch);
return result;
}
+466 -8
View File
@@ -4,6 +4,15 @@
#ifndef EVAL_CORE_H
#define EVAL_CORE_H
////////////////////////////////
//~ rjf: Evaluation Key Type
typedef struct E_Key E_Key;
struct E_Key
{
U64 u64;
};
////////////////////////////////
//~ rjf: Messages
@@ -309,6 +318,7 @@ struct E_IRTreeAndType
typedef struct E_Eval E_Eval;
struct E_Eval
{
E_Key key;
E_Expr *expr;
E_IRTreeAndType irtree;
String8 bytecode;
@@ -417,7 +427,7 @@ struct E_TypeExpandInfo
#define E_TYPE_IREXT_FUNCTION_DEF(name) internal E_TYPE_IREXT_FUNCTION_SIG(E_TYPE_IREXT_FUNCTION_NAME(name))
typedef E_TYPE_IREXT_FUNCTION_SIG(E_TypeIRExtFunctionType);
#define E_TYPE_ACCESS_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_Expr *expr, E_IRTreeAndType *lhs_irtree)
#define E_TYPE_ACCESS_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_IRTreeAndType *overridden, E_Expr *expr, E_IRTreeAndType *lhs_irtree)
#define E_TYPE_ACCESS_FUNCTION_NAME(name) e_type_access__##name
#define E_TYPE_ACCESS_FUNCTION_DEF(name) internal E_TYPE_ACCESS_FUNCTION_SIG(E_TYPE_ACCESS_FUNCTION_NAME(name))
typedef E_TYPE_ACCESS_FUNCTION_SIG(E_TypeAccessFunctionType);
@@ -473,6 +483,44 @@ struct E_Type
E_TypeExpandRule expand;
};
////////////////////////////////
//~ rjf: Constructed Type Types
typedef struct E_ConsTypeParams E_ConsTypeParams;
struct E_ConsTypeParams
{
Arch arch;
E_TypeKind kind;
E_TypeFlags flags;
String8 name;
E_TypeKey direct_key;
U64 count;
U64 depth;
E_Member *members;
E_EnumVal *enum_vals;
E_Expr **args;
E_TypeIRExtFunctionType *irext;
E_TypeAccessFunctionType *access;
E_TypeExpandRule expand;
};
typedef struct E_ConsTypeNode E_ConsTypeNode;
struct E_ConsTypeNode
{
E_ConsTypeNode *key_next;
E_ConsTypeNode *content_next;
E_TypeKey key;
E_ConsTypeParams params;
U64 byte_size;
};
typedef struct E_ConsTypeSlot E_ConsTypeSlot;
struct E_ConsTypeSlot
{
E_ConsTypeNode *first;
E_ConsTypeNode *last;
};
////////////////////////////////
//~ rjf: Modules
@@ -614,6 +662,8 @@ struct E_AutoHookParams
typedef B32 E_SpaceRWFunction(void *user_data, E_Space space, void *out, Rng1U64 offset_range);
//- rjf: base context
typedef struct E_BaseCtx E_BaseCtx;
struct E_BaseCtx
{
@@ -635,6 +685,300 @@ struct E_BaseCtx
E_SpaceRWFunction *space_write;
};
//- rjf: ir generation context
typedef struct E_IRCtx E_IRCtx;
struct E_IRCtx
{
E_String2NumMap *regs_map;
E_String2NumMap *reg_alias_map;
E_String2NumMap *locals_map; // (within `primary_module`)
E_String2NumMap *member_map; // (within `primary_module`)
E_String2ExprMap *macro_map;
E_AutoHookMap *auto_hook_map;
};
////////////////////////////////
//~ rjf: Parse Results
typedef struct E_Parse E_Parse;
struct E_Parse
{
E_TokenArray tokens;
E_Token *last_token;
E_Expr *expr;
E_Expr *last_expr;
E_MsgList msgs;
};
////////////////////////////////
//~ rjf: Bytecode Interpretation Types
typedef struct E_Interpretation E_Interpretation;
struct E_Interpretation
{
E_Value value;
E_Space space;
E_InterpretationCode code;
};
////////////////////////////////
//~ rjf: Core Evaluation Cache Types
//- rjf: unpacked type cache
typedef struct E_TypeCacheNode E_TypeCacheNode;
struct E_TypeCacheNode
{
E_TypeCacheNode *next;
E_TypeKey key;
E_Type *type;
};
typedef struct E_TypeCacheSlot E_TypeCacheSlot;
struct E_TypeCacheSlot
{
E_TypeCacheNode *first;
E_TypeCacheNode *last;
};
//- rjf: member lookup cache types
typedef struct E_MemberHashNode E_MemberHashNode;
struct E_MemberHashNode
{
E_MemberHashNode *next;
U64 member_idx;
};
typedef struct E_MemberHashSlot E_MemberHashSlot;
struct E_MemberHashSlot
{
E_MemberHashNode *first;
E_MemberHashNode *last;
};
typedef struct E_MemberFilterNode E_MemberFilterNode;
struct E_MemberFilterNode
{
E_MemberFilterNode *next;
String8 filter;
E_MemberArray members_filtered;
};
typedef struct E_MemberFilterSlot E_MemberFilterSlot;
struct E_MemberFilterSlot
{
E_MemberFilterNode *first;
E_MemberFilterNode *last;
};
typedef struct E_MemberCacheNode E_MemberCacheNode;
struct E_MemberCacheNode
{
E_MemberCacheNode *next;
E_TypeKey key;
E_MemberArray members;
U64 member_hash_slots_count;
E_MemberHashSlot *member_hash_slots;
U64 member_filter_slots_count;
E_MemberFilterSlot *member_filter_slots;
};
typedef struct E_MemberCacheSlot E_MemberCacheSlot;
struct E_MemberCacheSlot
{
E_MemberCacheNode *first;
E_MemberCacheNode *last;
};
//- rjf: used expression map
typedef struct E_UsedExprNode E_UsedExprNode;
struct E_UsedExprNode
{
E_UsedExprNode *next;
E_UsedExprNode *prev;
E_Expr *expr;
};
typedef struct E_UsedExprSlot E_UsedExprSlot;
struct E_UsedExprSlot
{
E_UsedExprNode *first;
E_UsedExprNode *last;
};
typedef struct E_UsedExprMap E_UsedExprMap;
struct E_UsedExprMap
{
U64 slots_count;
E_UsedExprSlot *slots;
};
//- rjf: type key -> auto hook expression list cache
typedef struct E_TypeAutoHookCacheNode E_TypeAutoHookCacheNode;
struct E_TypeAutoHookCacheNode
{
E_TypeAutoHookCacheNode *next;
E_TypeKey key;
E_ExprList exprs;
};
typedef struct E_TypeAutoHookCacheSlot E_TypeAutoHookCacheSlot;
struct E_TypeAutoHookCacheSlot
{
E_TypeAutoHookCacheNode *first;
E_TypeAutoHookCacheNode *last;
};
typedef struct E_TypeAutoHookCacheMap E_TypeAutoHookCacheMap;
struct E_TypeAutoHookCacheMap
{
U64 slots_count;
E_TypeAutoHookCacheSlot *slots;
};
//- rjf: string ID cache
typedef struct E_StringIDNode E_StringIDNode;
struct E_StringIDNode
{
E_StringIDNode *hash_next;
E_StringIDNode *id_next;
U64 id;
String8 string;
};
typedef struct E_StringIDSlot E_StringIDSlot;
struct E_StringIDSlot
{
E_StringIDNode *first;
E_StringIDNode *last;
};
typedef struct E_StringIDMap E_StringIDMap;
struct E_StringIDMap
{
U64 id_slots_count;
E_StringIDSlot *id_slots;
U64 hash_slots_count;
E_StringIDSlot *hash_slots;
};
//- rjf: cache evaluation bundles
typedef U32 E_CacheBundleFlags;
enum
{
E_CacheBundleFlag_Parse = (1<<0),
E_CacheBundleFlag_IRTree = (1<<1),
E_CacheBundleFlag_Bytecode = (1<<2),
E_CacheBundleFlag_Interpret = (1<<3),
};
typedef struct E_CacheBundle E_CacheBundle;
struct E_CacheBundle
{
E_CacheBundleFlags flags;
E_Key key;
E_Key parent_key;
String8 string;
E_Parse parse;
E_IRTreeAndType irtree;
String8 bytecode;
E_Interpretation interpretation;
};
typedef struct E_CacheNode E_CacheNode;
struct E_CacheNode
{
E_CacheNode *string_next;
E_CacheNode *key_next;
E_CacheBundle bundle;
};
typedef struct E_CacheLookup E_CacheLookup;
struct E_CacheLookup
{
E_CacheNode *node;
U64 hash;
};
typedef struct E_CacheSlot E_CacheSlot;
struct E_CacheSlot
{
E_CacheNode *first;
E_CacheNode *last;
};
//- rjf: parent stack
typedef struct E_CacheParentNode E_CacheParentNode;
struct E_CacheParentNode
{
E_CacheParentNode *next;
E_Key key;
};
//- rjf: main cache state type
typedef struct E_Cache E_Cache;
struct E_Cache
{
//- rjf: root arena
Arena *arena;
U64 arena_eval_start_pos;
//- rjf: key ID generation counter
U64 key_id_gen;
//- rjf: key -> bundle, string -> bundle tables
U64 key_slots_count;
E_CacheSlot *key_slots;
U64 string_slots_count;
E_CacheSlot *string_slots;
//- rjf: parent stack
E_CacheParentNode *top_parent_node;
E_CacheParentNode *free_parent_node;
//- rjf: unpacked context
RDI_Procedure *thread_ip_procedure;
//- rjf: [types] JIT-constructed types tables
U64 cons_id_gen;
U64 cons_content_slots_count;
U64 cons_key_slots_count;
E_ConsTypeSlot *cons_content_slots;
E_ConsTypeSlot *cons_key_slots;
//- rjf: [types] build-in constructed type keys
E_TypeKey file_type_key;
E_TypeKey folder_type_key;
//- rjf: [types] member cache table
U64 member_cache_slots_count;
E_MemberCacheSlot *member_cache_slots;
//- rjf: [types] unpacked type cache
U64 type_cache_slots_count;
E_TypeCacheSlot *type_cache_slots;
//- rjf: [ir] ir gen options
B32 disallow_autohooks;
B32 disallow_chained_fastpaths;
//- rjf: [ir] ir caches
E_UsedExprMap *used_expr_map;
E_TypeAutoHookCacheMap *type_auto_hook_cache_map;
//- rjf: [ir] string ID cache
U64 string_id_gen;
E_StringIDMap *string_id_map;
};
////////////////////////////////
//~ rjf: Generated Code
@@ -647,18 +991,33 @@ read_only global E_String2NumMap e_string2num_map_nil = {0};
read_only global E_String2ExprMap e_string2expr_map_nil = {0};
read_only global E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil};
read_only global E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
read_only global E_Eval e_eval_nil = {&e_expr_nil, {&e_irnode_nil}};
read_only global E_Eval e_eval_nil = {{0}, &e_expr_nil, {&e_irnode_nil}};
read_only global E_Module e_module_nil = {&rdi_parsed_nil};
read_only global E_CacheBundle e_cache_bundle_nil = {0, {0}, {0}, {0}, {{0}, 0, &e_expr_nil, &e_expr_nil}, {&e_irnode_nil}};
thread_static E_BaseCtx *e_base_ctx = 0;
thread_static U64 e_base_ctx_gen = 0;
thread_static E_IRCtx *e_ir_ctx = 0;
thread_static E_Cache *e_cache = 0;
////////////////////////////////
//~ rjf: Basic Helper Functions
//~ rjf: Basic Helpers
internal U64 e_hash_from_string(U64 seed, String8 string);
#define e_value_u64(v) (E_Value){.u64 = (v)}
//- rjf: type key data structures
////////////////////////////////
//~ rjf: Expr Kind Enum Functions
internal RDI_EvalOp e_opcode_from_expr_kind(E_ExprKind kind);
internal B32 e_expr_kind_is_comparison(E_ExprKind kind);
////////////////////////////////
//~ rjf: Key Type Functions
internal B32 e_key_match(E_Key a, E_Key b);
////////////////////////////////
//~ rjf: Type Key Type Functions
internal void e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key);
internal void e_type_key_list_push_front(Arena *arena, E_TypeKeyList *list, E_TypeKey key);
internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src);
@@ -676,7 +1035,7 @@ internal void e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push);
internal E_Space e_space_make(E_SpaceKind kind);
////////////////////////////////
//~ rjf: Basic Map Functions
//~ rjf: Map Functions
//- rjf: string -> num
internal E_String2NumMap e_string2num_map_make(Arena *arena, U64 slot_count);
@@ -691,13 +1050,18 @@ internal E_String2ExprMap e_string2expr_map_make(Arena *arena, U64 slot_count);
internal void e_string2expr_map_insert(Arena *arena, E_String2ExprMap *map, String8 string, E_Expr *expr);
internal void e_string2expr_map_inc_poison(E_String2ExprMap *map, String8 string);
internal void e_string2expr_map_dec_poison(E_String2ExprMap *map, String8 string);
internal E_Expr *e_string2expr_lookup(E_String2ExprMap *map, String8 string);
internal E_Expr *e_string2expr_map_lookup(E_String2ExprMap *map, String8 string);
//- rjf: string -> type-key
internal E_String2TypeKeyMap e_string2typekey_map_make(Arena *arena, U64 slots_count);
internal void e_string2typekey_map_insert(Arena *arena, E_String2TypeKeyMap *map, String8 string, E_TypeKey key);
internal E_TypeKey e_string2typekey_map_lookup(E_String2TypeKeyMap *map, String8 string);
//- rjf: auto hooks
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__})
////////////////////////////////
//~ rjf: Debug-Info-Driven Map Building Functions
@@ -705,8 +1069,102 @@ internal E_String2NumMap *e_push_locals_map_from_rdi_voff(Arena *arena, RDI_Pars
internal E_String2NumMap *e_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff);
////////////////////////////////
//~ rjf: Base Evaluation Context Selection
//~ rjf: Cache Creation & Selection
internal E_Cache *e_cache_alloc(void);
internal void e_cache_release(E_Cache *cache);
internal void e_select_cache(E_Cache *cache);
////////////////////////////////
//~ rjf: Evaluation Phase Markers
internal void e_select_base_ctx(E_BaseCtx *ctx);
internal void e_select_ir_ctx(E_IRCtx *ctx);
////////////////////////////////
//~ rjf: Base Cache Accessing Functions
//
// The cache uses a unique keying mechanism to refer to some evaluation at
// many layers of analysis.
//
// key
// ________________________________________________
// / / | \
// text -> expression -> ir tree and type -> interpretation result
//
// Each one of these calls refers to one stage in this pipeline. The cache will
// only compute what is needed on-demand. If you ask for the full evaluation,
// which is a bundle of artifacts at all layers of analysis, then all stages
// will be computed.
//
// One wrinkle here is that the IR tree generation stage is implicitly
// parameterized by the "overridden" IR tree - this is to enable "parent
// expressions", e.g. `$.x`, or simply `x` assuming `foo` has such a member,
// in the context of some struct `foo` evaluates to the same thing as `foo.x`.
// So even though the primary API shape is based around singular keys, the
// "parent key stack" also implicitly parameterizes all of these (partly
// because it is not relevant in 99% of cases).
//- rjf: parent key stack
internal E_Key e_parent_key_push(E_Key key);
internal E_Key e_parent_key_pop(void);
#define E_ParentKey(key) DeferLoop(e_parent_key_push(key), e_parent_key_pop())
//- rjf: key construction
internal E_Key e_key_from_string(String8 string);
internal E_Key e_key_from_stringf(char *fmt, ...);
internal E_Key e_key_from_expr(E_Expr *expr);
//- rjf: base key -> bundle helper
internal E_CacheBundle *e_cache_bundle_from_key(E_Key key);
//- rjf: bundle -> pipeline stage outputs
internal E_Parse e_parse_from_bundle(E_CacheBundle *bundle);
internal E_IRTreeAndType e_irtree_from_bundle(E_CacheBundle *bundle);
internal String8 e_bytecode_from_bundle(E_CacheBundle *bundle);
internal E_Interpretation e_interpretation_from_bundle(E_CacheBundle *bundle);
#define e_parse_from_key(key) e_parse_from_bundle(e_cache_bundle_from_key(key))
#define e_irtree_from_key(key) e_irtree_from_bundle(e_cache_bundle_from_key(key))
#define e_bytecode_from_key(key) e_bytecode_from_bundle(e_cache_bundle_from_key(key))
#define e_interpretation_from_key(key) e_interpretation_from_bundle(e_cache_bundle_from_key(key))
//- rjf: comprehensive bundle
internal E_Eval e_eval_from_bundle(E_CacheBundle *bundle);
internal E_Eval e_value_eval_from_eval(E_Eval eval);
#define e_eval_from_key(key) e_eval_from_bundle(e_cache_bundle_from_key(key))
#define e_value_from_key(key) (e_value_eval_from_eval(e_eval_from_key(key)).value)
//- rjf: string-based helpers
#define e_parse_from_string(string) e_parse_from_bundle(e_cache_bundle_from_key(e_key_from_string(string)))
#define e_irtree_from_string(string) e_irtree_from_bundle(e_cache_bundle_from_key(e_key_from_string(string)))
#define e_bytecode_from_string(string) e_bytecode_from_bundle(e_cache_bundle_from_key(e_key_from_string(string)))
#define e_interpretation_from_string(string) e_interpretation_from_bundle(e_cache_bundle_from_key(e_key_from_string(string)))
#define e_eval_from_string(string) e_eval_from_key(e_key_from_string(string))
#define e_eval_from_stringf(...) e_eval_from_key(e_key_from_stringf(__VA_ARGS__))
#define e_value_from_string(string) e_value_eval_from_eval(e_eval_from_string(string)).value
#define e_value_from_stringf(...) e_value_eval_from_eval(e_eval_from_stringf(__VA_ARGS__)).value
// TODO(rjf): (replace the old bundle APIs here)
//- rjf: expr-based helpers
#define e_eval_from_expr(expr) e_eval_from_key(e_key_from_expr(expr))
#define e_value_from_expr(expr) e_value_eval_from_eval(e_eval_from_expr(expr)).value
//- rjf: type key -> auto hooks
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: string IDs
internal U64 e_id_from_string(String8 string);
internal String8 e_string_from_id(U64 id);
////////////////////////////////
//~ rjf: Key Extension Functions
internal E_Key e_key_wrap(E_Key key, String8 string);
internal E_Key e_key_wrapf(E_Key key, char *fmt, ...);
//- rjf: eval-based helpers
#define e_eval_wrap(eval, string) e_eval_from_key(e_key_wrap((eval).key, (string)))
#define e_eval_wrapf(eval, ...) e_eval_from_key(e_key_wrapf((eval).key, __VA_ARGS__))
#endif // EVAL_CORE_H
-1
View File
@@ -7,4 +7,3 @@
#include "eval/eval_ir.c"
#include "eval/eval_interpret.c"
#include "eval/eval_bundles.c"
#include "eval/eval_cache.c"
-1
View File
@@ -10,6 +10,5 @@
#include "eval/eval_ir.h"
#include "eval/eval_interpret.h"
#include "eval/eval_bundles.h"
#include "eval/eval_cache.h"
#endif // EVAL_INC_H
-11
View File
@@ -4,17 +4,6 @@
#ifndef EVAL_INTERPRET_H
#define EVAL_INTERPRET_H
////////////////////////////////
//~ rjf: Bytecode Interpretation Types
typedef struct E_Interpretation E_Interpretation;
struct E_Interpretation
{
E_Value value;
E_Space space;
E_InterpretationCode code;
};
////////////////////////////////
//~ rjf: Interpretation Context
+66 -398
View File
@@ -1,289 +1,6 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Expr Kind Enum Functions
internal RDI_EvalOp
e_opcode_from_expr_kind(E_ExprKind kind)
{
RDI_EvalOp result = RDI_EvalOp_Stop;
switch(kind)
{
case E_ExprKind_Neg: result = RDI_EvalOp_Neg; break;
case E_ExprKind_LogNot: result = RDI_EvalOp_LogNot; break;
case E_ExprKind_BitNot: result = RDI_EvalOp_BitNot; break;
case E_ExprKind_Mul: result = RDI_EvalOp_Mul; break;
case E_ExprKind_Div: result = RDI_EvalOp_Div; break;
case E_ExprKind_Mod: result = RDI_EvalOp_Mod; break;
case E_ExprKind_Add: result = RDI_EvalOp_Add; break;
case E_ExprKind_Sub: result = RDI_EvalOp_Sub; break;
case E_ExprKind_LShift: result = RDI_EvalOp_LShift; break;
case E_ExprKind_RShift: result = RDI_EvalOp_RShift; break;
case E_ExprKind_Less: result = RDI_EvalOp_Less; break;
case E_ExprKind_LsEq: result = RDI_EvalOp_LsEq; break;
case E_ExprKind_Grtr: result = RDI_EvalOp_Grtr; break;
case E_ExprKind_GrEq: result = RDI_EvalOp_GrEq; break;
case E_ExprKind_EqEq: result = RDI_EvalOp_EqEq; break;
case E_ExprKind_NtEq: result = RDI_EvalOp_NtEq; break;
case E_ExprKind_BitAnd: result = RDI_EvalOp_BitAnd; break;
case E_ExprKind_BitXor: result = RDI_EvalOp_BitXor; break;
case E_ExprKind_BitOr: result = RDI_EvalOp_BitOr; break;
case E_ExprKind_LogAnd: result = RDI_EvalOp_LogAnd; break;
case E_ExprKind_LogOr: result = RDI_EvalOp_LogOr; break;
}
return result;
}
internal B32
e_expr_kind_is_comparison(E_ExprKind kind)
{
B32 result = 0;
switch(kind)
{
default:{}break;
case E_ExprKind_EqEq:
case E_ExprKind_NtEq:
case E_ExprKind_Less:
case E_ExprKind_Grtr:
case E_ExprKind_LsEq:
case E_ExprKind_GrEq:
{
result = 1;
}break;
}
return result;
}
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal void
e_select_ir_ctx(E_IRCtx *ctx)
{
if(e_ir_state == 0)
{
Arena *arena = arena_alloc();
e_ir_state = push_array(arena, E_IRState, 1);
e_ir_state->arena = arena;
e_ir_state->arena_eval_start_pos = arena_pos(arena);
}
arena_pop_to(e_ir_state->arena, e_ir_state->arena_eval_start_pos);
if(ctx->regs_map == 0) { ctx->regs_map = &e_string2num_map_nil; }
if(ctx->reg_alias_map == 0) { ctx->reg_alias_map = &e_string2num_map_nil; }
if(ctx->locals_map == 0) { ctx->locals_map = &e_string2num_map_nil; }
if(ctx->member_map == 0) { ctx->member_map = &e_string2num_map_nil; }
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(e_base_ctx->primary_module->rdi, e_base_ctx->thread_ip_voff);
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);
e_ir_state->string_id_gen = 0;
e_ir_state->string_id_map = push_array(e_ir_state->arena, E_StringIDMap, 1);
e_ir_state->string_id_map->id_slots_count = 1024;
e_ir_state->string_id_map->id_slots = push_array(e_ir_state->arena, E_StringIDSlot, e_ir_state->string_id_map->id_slots_count);
e_ir_state->string_id_map->hash_slots_count = 1024;
e_ir_state->string_id_map->hash_slots = push_array(e_ir_state->arena, E_StringIDSlot, e_ir_state->string_id_map->hash_slots_count);
e_ir_state->ir_cache_slots_count = 4096;
e_ir_state->ir_cache_slots = push_array(e_ir_state->arena, E_IRCacheSlot, e_ir_state->ir_cache_slots_count);
String8 builtin_view_rule_names[] =
{
str8_lit_comp("bswap"),
};
for EachElement(idx, builtin_view_rule_names)
{
E_Expr *expr = e_push_expr(e_ir_state->arena, E_ExprKind_LeafOffset, 0);
expr->type_key = e_type_key_cons(.kind = E_TypeKind_LensSpec, .name = builtin_view_rule_names[idx]);
e_string2expr_map_insert(e_ir_state->arena, ctx->macro_map, builtin_view_rule_names[idx], expr);
}
}
////////////////////////////////
//~ rjf: Auto Hooks
internal E_AutoHookMap
e_auto_hook_map_make(Arena *arena, U64 slots_count)
{
E_AutoHookMap map = {0};
map.slots_count = slots_count;
map.slots = push_array(arena, E_AutoHookSlot, map.slots_count);
return map;
}
internal void
e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params)
{
E_TypeKey type_key = params->type_key;
if(params->type_pattern.size != 0)
{
E_Parse parse = e_parse_from_string(params->type_pattern);
type_key = e_type_key_from_expr(parse.expr);
}
E_AutoHookNode *node = push_array(arena, E_AutoHookNode, 1);
node->type_string = str8_skip_chop_whitespace(e_type_string_from_key(arena, type_key));
U8 pattern_split = '?';
node->type_pattern_parts = str8_split(arena, params->type_pattern, &pattern_split, 1, StringSplitFlag_KeepEmpties);
node->expr = e_parse_from_string(params->tag_expr_string).expr;
if(!e_type_key_match(e_type_key_zero(), type_key))
{
U64 hash = e_hash_from_string(5381, node->type_string);
U64 slot_idx = hash%map->slots_count;
SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next);
}
else
{
SLLQueuePush_N(map->first_pattern, map->last_pattern, node, pattern_order_next);
}
}
internal E_ExprList
e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key)
{
ProfBeginFunction();
E_ExprList exprs = {0};
if(e_ir_state != 0 && e_ir_state->ctx != 0)
{
Temp scratch = scratch_begin(&arena, 1);
E_AutoHookMap *map = e_ir_state->ctx->auto_hook_map;
String8 type_string = str8_skip_chop_whitespace(e_type_string_from_key(scratch.arena, type_key));
//- rjf: gather exact-type-key-matches from the map
if(map != 0 && map->slots_count != 0)
{
U64 hash = e_hash_from_string(5381, type_string);
U64 slot_idx = hash%map->slots_count;
for(E_AutoHookNode *n = map->slots[slot_idx].first; n != 0; n = n->hash_next)
{
if(str8_match(n->type_string, type_string, 0))
{
e_expr_list_push(arena, &exprs, n->expr);
}
}
}
//- rjf: gather fuzzy matches from all patterns in the map
if(map != 0 && map->first_pattern != 0)
{
for(E_AutoHookNode *auto_hook_node = map->first_pattern;
auto_hook_node != 0;
auto_hook_node = auto_hook_node->pattern_order_next)
{
B32 fits_this_type_string = 1;
U64 scan_pos = 0;
for(String8Node *n = auto_hook_node->type_pattern_parts.first; n != 0; n = n->next)
{
if(n->string.size == 0)
{
continue;
}
U64 pattern_part_pos = str8_find_needle(type_string, scan_pos, n->string, 0);
if(pattern_part_pos >= type_string.size)
{
fits_this_type_string = 0;
break;
}
scan_pos = pattern_part_pos + n->string.size;
}
if(fits_this_type_string)
{
e_expr_list_push(arena, &exprs, auto_hook_node->expr);
}
}
}
scratch_end(scratch);
}
ProfEnd();
return exprs;
}
internal E_ExprList
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)
{
U64 hash = e_hash_from_string(5381, str8_struct(&type_key));
U64 slot_idx = hash%e_ir_state->type_auto_hook_cache_map->slots_count;
E_TypeAutoHookCacheNode *node = 0;
for(E_TypeAutoHookCacheNode *n = e_ir_state->type_auto_hook_cache_map->slots[slot_idx].first;
n != 0;
n = n->next)
{
if(e_type_key_match(n->key, type_key))
{
node = n;
}
}
if(node == 0)
{
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_exprs_from_type_key(e_type_state->arena, type_key);
}
exprs = node->exprs;
}
return exprs;
}
////////////////////////////////
//~ rjf: Evaluated String IDs
internal U64
e_id_from_string(String8 string)
{
U64 hash = e_hash_from_string(5381, string);
U64 hash_slot_idx = hash%e_ir_state->string_id_map->hash_slots_count;
E_StringIDNode *node = 0;
for(E_StringIDNode *n = e_ir_state->string_id_map->hash_slots[hash_slot_idx].first; n != 0; n = n->hash_next)
{
if(str8_match(n->string, string, 0))
{
node = n;
break;
}
}
if(node == 0)
{
e_ir_state->string_id_gen += 1;
U64 id = e_ir_state->string_id_gen;
U64 id_slot_idx = id%e_ir_state->string_id_map->id_slots_count;
node = push_array(e_ir_state->arena, E_StringIDNode, 1);
SLLQueuePush_N(e_ir_state->string_id_map->hash_slots[hash_slot_idx].first, e_ir_state->string_id_map->hash_slots[hash_slot_idx].last, node, hash_next);
SLLQueuePush_N(e_ir_state->string_id_map->id_slots[id_slot_idx].first, e_ir_state->string_id_map->hash_slots[id_slot_idx].last, node, id_next);
node->id = id;
node->string = push_str8_copy(e_ir_state->arena, string);
}
U64 result = node->id;
return result;
}
internal String8
e_string_from_id(U64 id)
{
U64 id_slot_idx = id%e_ir_state->string_id_map->id_slots_count;
E_StringIDNode *node = 0;
for(E_StringIDNode *n = e_ir_state->string_id_map->id_slots[id_slot_idx].first; n != 0; n = n->id_next)
{
if(n->id == id)
{
node = n;
break;
}
}
String8 result = {0};
if(node != 0)
{
result = node->string;
}
return result;
}
////////////////////////////////
//~ rjf: IR-ization Functions
@@ -594,8 +311,8 @@ e_expr_is_poisoned(E_Expr *expr)
{
B32 tag_is_poisoned = 0;
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)
U64 slot_idx = hash%e_cache->used_expr_map->slots_count;
for(E_UsedExprNode *n = e_cache->used_expr_map->slots[slot_idx].first; n != 0; n = n->next)
{
if(n->expr == expr)
{
@@ -610,22 +327,22 @@ internal void
e_expr_poison(E_Expr *expr)
{
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);
U64 slot_idx = hash%e_cache->used_expr_map->slots_count;
E_UsedExprNode *n = push_array(e_cache->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);
DLLPushBack(e_cache->used_expr_map->slots[slot_idx].first, e_cache->used_expr_map->slots[slot_idx].last, n);
}
internal void
e_expr_unpoison(E_Expr *expr)
{
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)
U64 slot_idx = hash%e_cache->used_expr_map->slots_count;
for(E_UsedExprNode *n = e_cache->used_expr_map->slots[slot_idx].first; n != 0; n = n->next)
{
if(n->expr == expr)
{
DLLRemove(e_ir_state->used_expr_map->slots[slot_idx].first, e_ir_state->used_expr_map->slots[slot_idx].last, n);
DLLRemove(e_cache->used_expr_map->slots[slot_idx].first, e_cache->used_expr_map->slots[slot_idx].last, n);
break;
}
}
@@ -775,7 +492,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default)
E_Expr *exprl = expr->first;
E_Expr *exprr = exprl->next;
E_IRTreeAndType l = *lhs_irtree;
E_IRTreeAndType r = e_push_irtree_and_type_from_expr(arena, exprr);
E_IRTreeAndType r = e_push_irtree_and_type_from_expr(arena, overridden, 0, 0, exprr);
E_TypeKey l_restype = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKey r_restype = e_type_key_unwrap(r.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind l_restype_kind = e_type_kind_from_key(l_restype);
@@ -869,7 +586,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default)
//- rjf: top-level irtree/type extraction
internal E_IRTreeAndType
e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
@@ -886,9 +603,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
E_Expr *expr;
E_IRTreeAndType *prev;
};
E_IRTreeAndType *start_prev = e_ir_state->overridden_irtree;
B32 start_disallow_autohooks = e_ir_state->disallow_autohooks;
Task start_task = {0, root_expr, e_ir_state->overridden_irtree};
Task start_task = {0, root_expr, overridden};
Task *first_task = &start_task;
Task *last_task = first_task;
for(Task *t = first_task; t != 0; t = t->next)
@@ -901,7 +616,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_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;
overridden = t->prev;
}
//- rjf: do expr -> irtree generation for this expression
@@ -920,7 +635,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
// rjf: unpack left-hand-side
E_Expr *lhs = expr->first;
E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, lhs);
E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, lhs);
// 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)
@@ -961,7 +676,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
}
// rjf: call into hook to do access
result = lhs_access(arena, expr, lhs_irtree_try);
result = lhs_access(arena, overridden, expr, lhs_irtree_try);
// rjf: end chain if we found a result
if(result.root != &e_irnode_nil)
@@ -976,7 +691,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind r_type_kind = e_type_kind_from_key(r_type);
E_TypeKey r_type_direct = e_type_key_unwrap(r_type, E_TypeUnwrapFlag_All);
@@ -1035,7 +750,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
E_TypeKey r_type = r_tree.type_key;
E_TypeKey r_type_unwrapped = e_type_key_unwrap(r_type, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind r_type_unwrapped_kind = e_type_kind_from_key(r_type_unwrapped);
@@ -1063,11 +778,11 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
// rjf: unpack operands
E_Expr *cast_type_expr = expr->first;
E_Expr *casted_expr = cast_type_expr->next;
E_IRTreeAndType cast_irtree = e_push_irtree_and_type_from_expr(arena, cast_type_expr);
E_IRTreeAndType cast_irtree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, cast_type_expr);
E_TypeKey cast_type = cast_irtree.type_key;
E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type);
U64 cast_type_byte_size = e_type_byte_size_from_key(cast_type);
E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, casted_expr);
E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, casted_expr);
e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs);
E_TypeKey casted_type = e_type_key_unwrap(casted_tree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind casted_type_kind = e_type_kind_from_key(casted_type);
@@ -1122,7 +837,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
E_Expr *r_expr = expr->first;
E_TypeKey r_type = zero_struct;
E_Space space = r_expr->space;
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
r_type = r_tree.type_key;
@@ -1150,7 +865,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
// rjf: evaluate operand tree
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
// rjf: fill output
@@ -1164,7 +879,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind r_type_kind = e_type_kind_from_key(r_type);
@@ -1192,14 +907,14 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
//- rjf: unary operations
case E_ExprKind_Pos:
{
result = e_push_irtree_and_type_from_expr(arena, expr->first);
result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, expr->first);
}break;
case E_ExprKind_Neg:
case E_ExprKind_BitNot:
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind r_type_kind = e_type_kind_from_key(r_type);
RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind);
@@ -1232,7 +947,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind r_type_kind = e_type_kind_from_key(r_type);
RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind);
@@ -1287,8 +1002,8 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
B32 is_comparison = e_expr_kind_is_comparison(kind);
E_Expr *l_expr = expr->first;
E_Expr *r_expr = l_expr->next;
E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, l_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, l_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
E_TypeKey l_type = e_type_key_unwrap(l_tree.type_key, E_TypeUnwrapFlag_AllDecorative);
@@ -1511,9 +1226,9 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
E_Expr *c_expr = expr->first;
E_Expr *l_expr = c_expr->next;
E_Expr *r_expr = l_expr->next;
E_IRTreeAndType c_tree = e_push_irtree_and_type_from_expr(arena, c_expr);
E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, l_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, r_expr);
E_IRTreeAndType c_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, c_expr);
E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, l_expr);
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr);
e_msg_list_concat_in_place(&result.msgs, &c_tree.msgs);
e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
@@ -1556,10 +1271,8 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
//- rjf: call
case E_ExprKind_Call:
{
B32 start_disallow_chained_fastpaths = e_ir_state->disallow_chained_fastpaths;
e_ir_state->disallow_chained_fastpaths = 1;
E_Expr *lhs = expr->first;
E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, lhs);
E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, 1, lhs);
E_TypeKey lhs_type_key = lhs_irtree.type_key;
E_Type *lhs_type = e_type_from_key__cached(lhs_type_key);
@@ -1580,17 +1293,17 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
e_expr_push_child(call, e_expr_ref(arena, arg));
}
result = e_push_irtree_and_type_from_expr(arena, call);
result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, call);
// rjf: is "raw"? -> try to return overridden tree, otherwise strip all
// lens types from result; disallow auto-hooks
if(str8_match(callee->string, str8_lit("raw"), 0))
{
e_ir_state->disallow_autohooks = 1;
if(e_ir_state->overridden_irtree != 0)
disallow_autohooks = 1;
if(overridden != 0)
{
result = *e_ir_state->overridden_irtree;
for(E_IRTreeAndType *prev = e_ir_state->overridden_irtree->prev; prev != 0; prev = prev->prev)
result = *overridden;
for(E_IRTreeAndType *prev = overridden->prev; prev != 0; prev = prev->prev)
{
result = *prev;
}
@@ -1609,7 +1322,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
Temp scratch = scratch_begin(&arena, 1);
// rjf: generate result via first argument to lens
result = e_push_irtree_and_type_from_expr(arena, lhs->next);
result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, lhs->next);
// rjf: count extra arguments
U64 arg_count = 0;
@@ -1632,18 +1345,18 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
// lens types from result; disallow auto-hooks
if(str8_match(lhs_type->name, str8_lit("raw"), 0))
{
e_ir_state->disallow_autohooks = 1;
if(e_ir_state->overridden_irtree != 0)
disallow_autohooks = 1;
if(overridden != 0)
{
result = *e_ir_state->overridden_irtree;
for(E_IRTreeAndType *prev = e_ir_state->overridden_irtree->prev; prev != 0; prev = prev->prev)
result = *overridden;
for(E_IRTreeAndType *prev = overridden->prev; prev != 0; prev = prev->prev)
{
result = *prev;
}
}
else
{
result = e_push_irtree_and_type_from_expr(arena, lhs->next);
result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, lhs->next);
result.type_key = e_type_key_unwrap(result.type_key, E_TypeUnwrapFlag_Lenses);
}
}
@@ -1670,8 +1383,6 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
e_msgf(arena, &result.msgs, E_MsgKind_InterpretationError, expr->location, "Calling this type is not supported.");
}
e_ir_state->disallow_chained_fastpaths = start_disallow_chained_fastpaths;
}break;
//- rjf: leaf bytecode
@@ -1751,7 +1462,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
E_Module *module = e_base_ctx->primary_module;
RDI_Parsed *rdi = module->rdi;
RDI_Procedure *procedure = e_ir_state->thread_ip_procedure;
RDI_Procedure *procedure = e_cache->thread_ip_procedure;
U64 name_size = 0;
U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
String8 containing_procedure_name = str8(name_ptr, name_size);
@@ -1773,21 +1484,21 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
}
//- rjf: try to map name as overridden expression signifier ('$')
if(!string_mapped && str8_match(string, str8_lit("$"), 0) && e_ir_state->overridden_irtree != 0)
if(!string_mapped && str8_match(string, str8_lit("$"), 0) && overridden != 0)
{
E_OpList oplist = e_oplist_from_irtree(arena, e_ir_state->overridden_irtree->root);
E_OpList oplist = e_oplist_from_irtree(arena, overridden->root);
string_mapped = 1;
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = e_ir_state->overridden_irtree->mode;
mapped_type_key = e_ir_state->overridden_irtree->type_key;
e_ir_state->disallow_autohooks = 1;
mapped_bytecode_mode = overridden->mode;
mapped_type_key = overridden->type_key;
disallow_autohooks = 1;
}
//- rjf: try to map name as implicit access of overridden expression ('$.member_name', where the $. prefix is omitted)
if(!string_mapped && e_ir_state->overridden_irtree != 0)
if(!string_mapped && overridden != 0)
{
E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, e_ir_state->overridden_irtree, string);
E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, access);
E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, overridden, string);
E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, overridden, disallow_autohooks, disallow_chained_fastpaths, access);
if(access_irtree.root != &e_irnode_nil)
{
string_mapped = 1;
@@ -1806,7 +1517,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
E_Module *module = e_base_ctx->primary_module;
U32 module_idx = (U32)(module - e_base_ctx->modules);
RDI_Parsed *rdi = module->rdi;
RDI_Procedure *procedure = e_ir_state->thread_ip_procedure;
RDI_Procedure *procedure = e_cache->thread_ip_procedure;
RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure);
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module_idx);
@@ -1824,7 +1535,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
E_Module *module = e_base_ctx->primary_module;
U32 module_idx = (U32)(module - e_base_ctx->modules);
RDI_Parsed *rdi = module->rdi;
U64 local_num = e_num_from_string(e_ir_state->ctx->locals_map, string__redirected);
U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string__redirected);
if(local_num != 0)
{
RDI_Local *local = rdi_element_from_name_idx(rdi, Locals, local_num-1);
@@ -2073,7 +1784,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
//- rjf: try registers
if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0)))
{
U64 reg_num = e_num_from_string(e_ir_state->ctx->regs_map, string);
U64 reg_num = e_num_from_string(e_ir_ctx->regs_map, string);
if(reg_num != 0)
{
string_mapped = 1;
@@ -2090,7 +1801,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
//- rjf: try register aliases
if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0)))
{
U64 alias_num = e_num_from_string(e_ir_state->ctx->reg_alias_map, string);
U64 alias_num = e_num_from_string(e_ir_ctx->reg_alias_map, string);
if(alias_num != 0)
{
string_mapped = 1;
@@ -2149,13 +1860,13 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
//- rjf: generate IR trees for macros
if(!generated)
{
E_Expr *macro_expr = e_string2expr_lookup(e_ir_state->ctx->macro_map, string);
E_Expr *macro_expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, string);
if(macro_expr != &e_expr_nil)
{
generated = 1;
e_string2expr_map_inc_poison(e_ir_state->ctx->macro_map, string);
result = e_push_irtree_and_type_from_expr(arena, macro_expr);
e_string2expr_map_dec_poison(e_ir_state->ctx->macro_map, string);
e_string2expr_map_inc_poison(e_ir_ctx->macro_map, string);
result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, macro_expr);
e_string2expr_map_dec_poison(e_ir_ctx->macro_map, string);
}
}
@@ -2213,7 +1924,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
E_Space space = e_space_make(E_SpaceKind_FileSystem);
result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(file_path)));
result.type_key = e_type_state->file_type_key;
result.type_key = e_cache->file_type_key;
result.mode = E_Mode_Value;
}
else
@@ -2224,7 +1935,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
E_Space space = e_space_make(E_SpaceKind_FileSystem);
result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(folder_path)));
result.type_key = e_type_state->folder_type_key;
result.type_key = e_cache->folder_type_key;
result.mode = E_Mode_Value;
}
}
@@ -2241,13 +1952,13 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
}break;
case E_ExprKind_Ptr:
{
E_IRTreeAndType ptee_irtree = e_push_irtree_and_type_from_expr(arena, expr->first);
E_IRTreeAndType ptee_irtree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, expr->first);
result = ptee_irtree;
result.type_key = e_type_key_cons_ptr(e_base_ctx->primary_module->arch, result.type_key, 1, 0);
}break;
case E_ExprKind_Array:
{
E_IRTreeAndType element_irtree = e_push_irtree_and_type_from_expr(arena, expr->first);
E_IRTreeAndType element_irtree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, expr->first);
result = element_irtree;
result.type_key = e_type_key_cons_array(result.type_key, expr->value.u64, 0);
}break;
@@ -2261,7 +1972,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
E_Expr *lhs = expr->first;
E_Expr *rhs = lhs->next;
result = e_push_irtree_and_type_from_expr(arena, rhs);
result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, rhs);
if(lhs->kind != E_ExprKind_LeafIdentifier)
{
e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Left side of assignment must be an unused identifier.");
@@ -2270,7 +1981,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
}
//- rjf: check chained expressions for simple wrappers
if(!e_ir_state->disallow_chained_fastpaths)
if(!disallow_chained_fastpaths)
{
struct
{
@@ -2310,7 +2021,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
if(e_type_kind_is_pointer_or_ref(type_kind) ||
type_kind == E_TypeKind_Array)
{
E_Expr *lens_spec_expr = e_string2expr_lookup(e_ir_state->ctx->macro_map, str8_lit("array"));
E_Expr *lens_spec_expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, str8_lit("array"));
E_TypeKey lens_spec_type_key = lens_spec_expr->type_key;
E_Type *lens_spec_type = e_type_from_key__cached(lens_spec_type_key);
result.type_key = e_type_key_cons(.kind = E_TypeKind_Lens,
@@ -2360,7 +2071,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
}
//- rjf: find any auto hooks according to this generation's type
if(!e_ir_state->disallow_autohooks && result.mode != E_Mode_Null)
if(!disallow_autohooks && result.mode != E_Mode_Null)
{
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)
@@ -2382,12 +2093,6 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
}
}
//////////////////////////////
//- rjf: reset the overridden settings to whatever they were before this task list
//
e_ir_state->overridden_irtree = start_prev;
e_ir_state->disallow_autohooks = start_disallow_autohooks;
//////////////////////////////
//- rjf: unpoison the tags we used
//
@@ -2688,40 +2393,3 @@ e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_Type
e_expr_push_child(root, rhs_bytecode);
return root;
}
////////////////////////////////
//~ rjf: IR Cache Functions
internal E_IRTreeAndType
e_irtree_and_type_from_expr(E_Expr *expr)
{
U64 hash_parts[] =
{
(U64)expr,
(U64)(e_ir_state->overridden_irtree ? e_ir_state->overridden_irtree->root : 0),
};
U64 hash = e_hash_from_string(5381, str8((U8 *)hash_parts, sizeof(hash_parts)));
U64 slot_idx = hash%e_ir_state->ir_cache_slots_count;
E_IRCacheSlot *slot = &e_ir_state->ir_cache_slots[slot_idx];
E_IRCacheNode *node = 0;
for(E_IRCacheNode *n = slot->first; n != 0; n = n->next)
{
if(expr == n->expr &&
((e_ir_state->overridden_irtree == 0 && n->overridden_node == 0) ||
(e_ir_state->overridden_irtree != 0 && n->overridden_node == e_ir_state->overridden_irtree->root)))
{
node = n;
break;
}
}
if(node == 0)
{
node = push_array(e_ir_state->arena, E_IRCacheNode, 1);
SLLQueuePush(slot->first, slot->last, node);
node->expr = expr;
node->overridden_node = (e_ir_state->overridden_irtree ? e_ir_state->overridden_irtree->root : 0);
node->irtree = e_push_irtree_and_type_from_expr(e_ir_state->arena, expr);
}
E_IRTreeAndType result = node->irtree;
return result;
}
+1 -129
View File
@@ -4,98 +4,6 @@
#ifndef EVAL_IR_H
#define EVAL_IR_H
////////////////////////////////
//~ rjf: Used Tag Map Data Structure
typedef struct E_UsedExprNode E_UsedExprNode;
struct E_UsedExprNode
{
E_UsedExprNode *next;
E_UsedExprNode *prev;
E_Expr *expr;
};
typedef struct E_UsedExprSlot E_UsedExprSlot;
struct E_UsedExprSlot
{
E_UsedExprNode *first;
E_UsedExprNode *last;
};
typedef struct E_UsedExprMap E_UsedExprMap;
struct E_UsedExprMap
{
U64 slots_count;
E_UsedExprSlot *slots;
};
////////////////////////////////
//~ rjf: Type Key -> Auto Hook Expr List Cache
typedef struct E_TypeAutoHookCacheNode E_TypeAutoHookCacheNode;
struct E_TypeAutoHookCacheNode
{
E_TypeAutoHookCacheNode *next;
E_TypeKey key;
E_ExprList exprs;
};
typedef struct E_TypeAutoHookCacheSlot E_TypeAutoHookCacheSlot;
struct E_TypeAutoHookCacheSlot
{
E_TypeAutoHookCacheNode *first;
E_TypeAutoHookCacheNode *last;
};
typedef struct E_TypeAutoHookCacheMap E_TypeAutoHookCacheMap;
struct E_TypeAutoHookCacheMap
{
U64 slots_count;
E_TypeAutoHookCacheSlot *slots;
};
////////////////////////////////
//~ rjf: Evaluated String ID Map
typedef struct E_StringIDNode E_StringIDNode;
struct E_StringIDNode
{
E_StringIDNode *hash_next;
E_StringIDNode *id_next;
U64 id;
String8 string;
};
typedef struct E_StringIDSlot E_StringIDSlot;
struct E_StringIDSlot
{
E_StringIDNode *first;
E_StringIDNode *last;
};
typedef struct E_StringIDMap E_StringIDMap;
struct E_StringIDMap
{
U64 id_slots_count;
E_StringIDSlot *id_slots;
U64 hash_slots_count;
E_StringIDSlot *hash_slots;
};
////////////////////////////////
//~ rjf: IR Context
typedef struct E_IRCtx E_IRCtx;
struct E_IRCtx
{
E_String2NumMap *regs_map;
E_String2NumMap *reg_alias_map;
E_String2NumMap *locals_map; // (within `primary_module`)
E_String2NumMap *member_map; // (within `primary_module`)
E_String2ExprMap *macro_map;
E_AutoHookMap *auto_hook_map;
};
////////////////////////////////
//~ rjf: IR State
@@ -141,37 +49,6 @@ struct E_IRState
E_IRCacheSlot *ir_cache_slots;
};
////////////////////////////////
//~ rjf: Globals
thread_static E_IRState *e_ir_state = 0;
////////////////////////////////
//~ rjf: Expr Kind Enum Functions
internal RDI_EvalOp e_opcode_from_expr_kind(E_ExprKind kind);
internal B32 e_expr_kind_is_comparison(E_ExprKind kind);
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal void e_select_ir_ctx(E_IRCtx *ctx);
////////////////////////////////
//~ rjf: Auto Hooks
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_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
internal U64 e_id_from_string(String8 string);
internal String8 e_string_from_id(U64 id);
////////////////////////////////
//~ rjf: IR-ization Functions
@@ -211,7 +88,7 @@ internal void e_expr_unpoison(E_Expr *expr);
//- rjf: top-level irtree/type extraction
E_TYPE_ACCESS_FUNCTION_DEF(default);
internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr);
//- rjf: irtree -> linear ops/bytecode
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out);
@@ -224,9 +101,4 @@ internal E_Expr *e_expr_irext_array_index(Arena *arena, E_Expr *lhs, E_IRTreeAnd
internal E_Expr *e_expr_irext_deref(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree);
internal E_Expr *e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_TypeKey type_key);
////////////////////////////////
//~ rjf: IR Cache Functions
internal E_IRTreeAndType e_irtree_and_type_from_expr(E_Expr *expr);
#endif // EVAL_IR_H
-44
View File
@@ -1454,47 +1454,3 @@ e_push_parse_from_string(Arena *arena, String8 text)
scratch_end(scratch);
return parse;
}
////////////////////////////////
//~ rjf: Parse Cache Functions
internal void
e_parse_eval_begin(void)
{
if(e_parse_state == 0)
{
Arena *arena = arena_alloc();
e_parse_state = push_array(arena, E_ParseState, 1);
e_parse_state->arena = arena;
e_parse_state->arena_eval_start_pos = arena_pos(e_parse_state->arena);
}
arena_pop_to(e_parse_state->arena, e_parse_state->arena_eval_start_pos);
e_parse_state->cache_slots_count = 4096;
e_parse_state->cache_slots = push_array(e_parse_state->arena, E_ParseCacheSlot, e_parse_state->cache_slots_count);
}
internal E_Parse
e_parse_from_string(String8 string)
{
U64 hash = e_hash_from_string(5381, string);
U64 slot_idx = hash%e_parse_state->cache_slots_count;
E_ParseCacheSlot *slot = &e_parse_state->cache_slots[slot_idx];
E_ParseCacheNode *node = 0;
for(E_ParseCacheNode *n = slot->first; n != 0; n = n->next)
{
if(str8_match(n->string, string, 0))
{
node = n;
break;
}
}
if(node == 0)
{
node = push_array(e_parse_state->arena, E_ParseCacheNode, 1);
SLLQueuePush(slot->first, slot->last, node);
node->string = push_str8_copy(e_parse_state->arena, string);
node->parse = e_push_parse_from_string(e_parse_state->arena, node->string);
}
E_Parse result = node->parse;
return result;
}
-51
View File
@@ -4,51 +4,6 @@
#ifndef EVAL_PARSE_H
#define EVAL_PARSE_H
////////////////////////////////
//~ rjf: Parse Results
typedef struct E_Parse E_Parse;
struct E_Parse
{
E_TokenArray tokens;
E_Token *last_token;
E_Expr *expr;
E_Expr *last_expr;
E_MsgList msgs;
};
////////////////////////////////
//~ rjf: Parse Evaluation State
typedef struct E_ParseCacheNode E_ParseCacheNode;
struct E_ParseCacheNode
{
E_ParseCacheNode *next;
String8 string;
E_Parse parse;
};
typedef struct E_ParseCacheSlot E_ParseCacheSlot;
struct E_ParseCacheSlot
{
E_ParseCacheNode *first;
E_ParseCacheNode *last;
};
typedef struct E_ParseState E_ParseState;
struct E_ParseState
{
Arena *arena;
U64 arena_eval_start_pos;
U64 cache_slots_count;
E_ParseCacheSlot *cache_slots;
};
////////////////////////////////
//~ rjf: Globals
thread_static E_ParseState *e_parse_state = 0;
////////////////////////////////
//~ rjf: Tokenization Functions
@@ -86,10 +41,4 @@ internal E_Parse e_push_type_parse_from_text_tokens(Arena *arena, String8 text,
internal E_Parse e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray tokens, S64 max_precedence, U64 max_chain_count);
internal E_Parse e_push_parse_from_string(Arena *arena, String8 text);
////////////////////////////////
//~ rjf: Parse Cache Functions
internal void e_parse_eval_begin(void);
internal E_Parse e_parse_from_string(String8 string);
#endif // EVAL_PARSE_H
+41 -88
View File
@@ -222,49 +222,6 @@ e_member_array_from_list(Arena *arena, E_MemberList *list)
return array;
}
////////////////////////////////
//~ rjf: Type Evaluation Phase Beginning Marker (Required For All Subsequent APIs)
internal void
e_type_eval_begin(void)
{
if(e_type_state == 0)
{
Arena *arena = arena_alloc();
e_type_state = push_array(arena, E_TypeState, 1);
e_type_state->arena = arena;
e_type_state->arena_eval_start_pos = arena_pos(e_type_state->arena);
}
arena_pop_to(e_type_state->arena, e_type_state->arena_eval_start_pos);
e_type_state->cons_id_gen = 0;
e_type_state->cons_content_slots_count = 256;
e_type_state->cons_key_slots_count = 256;
e_type_state->cons_content_slots = push_array(e_type_state->arena, E_ConsTypeSlot, e_type_state->cons_content_slots_count);
e_type_state->cons_key_slots = push_array(e_type_state->arena, E_ConsTypeSlot, e_type_state->cons_key_slots_count);
e_type_state->member_cache_slots_count = 256;
e_type_state->member_cache_slots = push_array(e_type_state->arena, E_MemberCacheSlot, e_type_state->member_cache_slots_count);
e_type_state->type_cache_slots_count = 1024;
e_type_state->type_cache_slots = push_array(e_type_state->arena, E_TypeCacheSlot, e_type_state->type_cache_slots_count);
e_type_state->file_type_key = e_type_key_cons(.kind = E_TypeKind_Set,
.name = str8_lit("file"),
.irext = E_TYPE_IREXT_FUNCTION_NAME(file),
.access = E_TYPE_ACCESS_FUNCTION_NAME(file),
.expand =
{
.info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(file),
.range= E_TYPE_EXPAND_RANGE_FUNCTION_NAME(file),
});
e_type_state->folder_type_key = e_type_key_cons(.kind = E_TypeKind_Set,
.name = str8_lit("folder"),
.expand =
{
.info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(folder),
.range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(folder),
.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(folder),
.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(folder),
});
}
////////////////////////////////
//~ rjf: Type Operation Functions
@@ -385,8 +342,8 @@ internal E_TypeKey
e_type_key_cons_(E_ConsTypeParams *params)
{
U64 content_hash = e_hash_from_cons_type_params(params);
U64 content_slot_idx = content_hash%e_type_state->cons_content_slots_count;
E_ConsTypeSlot *content_slot = &e_type_state->cons_content_slots[content_slot_idx];
U64 content_slot_idx = content_hash%e_cache->cons_content_slots_count;
E_ConsTypeSlot *content_slot = &e_cache->cons_content_slots[content_slot_idx];
E_ConsTypeNode *node = 0;
for(E_ConsTypeNode *n = content_slot->first; n != 0; n = n->content_next)
{
@@ -401,17 +358,17 @@ e_type_key_cons_(E_ConsTypeParams *params)
{
E_TypeKey key = {E_TypeKeyKind_Cons};
key.u32[0] = (U32)params->kind;
key.u32[1] = (U32)e_type_state->cons_id_gen;
e_type_state->cons_id_gen += 1;
key.u32[1] = (U32)e_cache->cons_id_gen;
e_cache->cons_id_gen += 1;
U64 key_hash = e_hash_from_string(5381, str8_struct(&key));
U64 key_slot_idx = key_hash%e_type_state->cons_key_slots_count;
E_ConsTypeSlot *key_slot = &e_type_state->cons_key_slots[key_slot_idx];
E_ConsTypeNode *node = push_array(e_type_state->arena, E_ConsTypeNode, 1);
U64 key_slot_idx = key_hash%e_cache->cons_key_slots_count;
E_ConsTypeSlot *key_slot = &e_cache->cons_key_slots[key_slot_idx];
E_ConsTypeNode *node = push_array(e_cache->arena, E_ConsTypeNode, 1);
SLLQueuePush_N(content_slot->first, content_slot->last, node, content_next);
SLLQueuePush_N(key_slot->first, key_slot->last, node, key_next);
node->key = key;
MemoryCopyStruct(&node->params, params);
node->params.name = push_str8_copy(e_type_state->arena, params->name);
node->params.name = push_str8_copy(e_cache->arena, params->name);
if(node->params.expand.info != 0)
{
if(node->params.expand.range == 0) {node->params.expand.range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(default);}
@@ -420,32 +377,32 @@ e_type_key_cons_(E_ConsTypeParams *params)
}
if(params->members != 0)
{
node->params.members = push_array(e_type_state->arena, E_Member, params->count);
node->params.members = push_array(e_cache->arena, E_Member, params->count);
MemoryCopy(node->params.members, params->members, sizeof(E_Member)*params->count);
for(U64 idx = 0; idx < node->params.count; idx += 1)
{
node->params.members[idx].name = push_str8_copy(e_type_state->arena, node->params.members[idx].name);
node->params.members[idx].inheritance_key_chain = e_type_key_list_copy(e_type_state->arena, &node->params.members[idx].inheritance_key_chain);
node->params.members[idx].name = push_str8_copy(e_cache->arena, node->params.members[idx].name);
node->params.members[idx].inheritance_key_chain = e_type_key_list_copy(e_cache->arena, &node->params.members[idx].inheritance_key_chain);
U64 opl_off = (node->params.members[idx].off + e_type_byte_size_from_key(node->params.members[idx].type_key));
node->byte_size = Max(node->byte_size, opl_off);
}
}
else if(params->enum_vals != 0)
{
node->params.enum_vals = push_array(e_type_state->arena, E_EnumVal, params->count);
node->params.enum_vals = push_array(e_cache->arena, E_EnumVal, params->count);
MemoryCopy(node->params.enum_vals, params->enum_vals, sizeof(E_EnumVal)*params->count);
for(U64 idx = 0; idx < node->params.count; idx += 1)
{
node->params.enum_vals[idx].name = push_str8_copy(e_type_state->arena, node->params.enum_vals[idx].name);
node->params.enum_vals[idx].name = push_str8_copy(e_cache->arena, node->params.enum_vals[idx].name);
}
node->byte_size = e_type_byte_size_from_key(node->params.direct_key);
}
else if(params->args != 0)
{
node->params.args = push_array(e_type_state->arena, E_Expr *, params->count);
node->params.args = push_array(e_cache->arena, E_Expr *, params->count);
for EachIndex(idx, params->count)
{
node->params.args[idx] = e_expr_copy(e_type_state->arena, params->args[idx]);
node->params.args[idx] = e_expr_copy(e_cache->arena, params->args[idx]);
}
}
else switch(params->kind)
@@ -560,14 +517,14 @@ e_type_key_cons_base(Type *type)
internal E_TypeKey
e_type_key_file(void)
{
E_TypeKey key = e_type_state->file_type_key;
E_TypeKey key = e_cache->file_type_key;
return key;
}
internal E_TypeKey
e_type_key_folder(void)
{
E_TypeKey key = e_type_state->folder_type_key;
E_TypeKey key = e_cache->folder_type_key;
return key;
}
@@ -669,8 +626,8 @@ e_type_byte_size_from_key(E_TypeKey key)
case E_TypeKeyKind_Cons:
{
U64 key_hash = e_hash_from_string(5381, str8_struct(&key));
U64 key_slot_idx = key_hash%e_type_state->cons_key_slots_count;
E_ConsTypeSlot *key_slot = &e_type_state->cons_key_slots[key_slot_idx];
U64 key_slot_idx = key_hash%e_cache->cons_key_slots_count;
E_ConsTypeSlot *key_slot = &e_cache->cons_key_slots[key_slot_idx];
for(E_ConsTypeNode *node = key_slot->first;
node != 0;
node = node->key_next)
@@ -715,8 +672,8 @@ e_type_from_key(Arena *arena, E_TypeKey key)
case E_TypeKeyKind_Cons:
{
U64 key_hash = e_hash_from_string(5381, str8_struct(&key));
U64 key_slot_idx = key_hash%e_type_state->cons_key_slots_count;
E_ConsTypeSlot *key_slot = &e_type_state->cons_key_slots[key_slot_idx];
U64 key_slot_idx = key_hash%e_cache->cons_key_slots_count;
E_ConsTypeSlot *key_slot = &e_cache->cons_key_slots[key_slot_idx];
for(E_ConsTypeNode *node = key_slot->first;
node != 0;
node = node->key_next)
@@ -1996,9 +1953,9 @@ e_type_from_key__cached(E_TypeKey key)
E_Type *type = &e_type_nil;
{
U64 hash = e_hash_from_string(5381, str8_struct(&key));
U64 slot_idx = hash%e_type_state->type_cache_slots_count;
U64 slot_idx = hash%e_cache->type_cache_slots_count;
E_TypeCacheNode *node = 0;
for(E_TypeCacheNode *n = e_type_state->type_cache_slots[slot_idx].first; n != 0; n = n->next)
for(E_TypeCacheNode *n = e_cache->type_cache_slots[slot_idx].first; n != 0; n = n->next)
{
if(e_type_key_match(key, n->key))
{
@@ -2008,10 +1965,10 @@ e_type_from_key__cached(E_TypeKey key)
}
if(node == 0)
{
node = push_array(e_type_state->arena, E_TypeCacheNode, 1);
node = push_array(e_cache->arena, E_TypeCacheNode, 1);
node->key = key;
node->type = e_type_from_key(e_type_state->arena, key);
SLLQueuePush(e_type_state->type_cache_slots[slot_idx].first, e_type_state->type_cache_slots[slot_idx].last, node);
node->type = e_type_from_key(e_cache->arena, key);
SLLQueuePush(e_cache->type_cache_slots[slot_idx].first, e_cache->type_cache_slots[slot_idx].last, node);
}
type = node->type;
}
@@ -2022,8 +1979,8 @@ internal E_MemberCacheNode *
e_member_cache_node_from_type_key(E_TypeKey key)
{
U64 hash = e_hash_from_string(5381, str8_struct(&key));
U64 slot_idx = hash%e_type_state->member_cache_slots_count;
E_MemberCacheSlot *slot = &e_type_state->member_cache_slots[slot_idx];
U64 slot_idx = hash%e_cache->member_cache_slots_count;
E_MemberCacheSlot *slot = &e_cache->member_cache_slots[slot_idx];
E_MemberCacheNode *node = 0;
for(E_MemberCacheNode *n = slot->first; n != 0; n = n->next)
{
@@ -2035,19 +1992,19 @@ e_member_cache_node_from_type_key(E_TypeKey key)
}
if(node == 0)
{
node = push_array(e_type_state->arena, E_MemberCacheNode, 1);
node = push_array(e_cache->arena, E_MemberCacheNode, 1);
SLLQueuePush(slot->first, slot->last, node);
node->key = key;
node->members = e_type_data_members_from_key(e_type_state->arena, key);
node->members = e_type_data_members_from_key(e_cache->arena, key);
node->member_hash_slots_count = node->members.count;
node->member_hash_slots = push_array(e_type_state->arena, E_MemberHashSlot, node->member_hash_slots_count);
node->member_hash_slots = push_array(e_cache->arena, E_MemberHashSlot, node->member_hash_slots_count);
node->member_filter_slots_count = 16;
node->member_filter_slots = push_array(e_type_state->arena, E_MemberFilterSlot, node->member_filter_slots_count);
node->member_filter_slots = push_array(e_cache->arena, E_MemberFilterSlot, node->member_filter_slots_count);
for EachIndex(idx, node->members.count)
{
U64 hash = e_hash_from_string(5381, node->members.v[idx].name);
U64 slot_idx = hash%node->member_hash_slots_count;
E_MemberHashNode *n = push_array(e_type_state->arena, E_MemberHashNode, 1);
E_MemberHashNode *n = push_array(e_cache->arena, E_MemberHashNode, 1);
SLLQueuePush(node->member_hash_slots[slot_idx].first, node->member_hash_slots[slot_idx].last, n);
n->member_idx = idx;
}
@@ -2083,8 +2040,8 @@ e_type_data_members_from_key_filter__cached(E_TypeKey key, String8 filter)
if(filter_node == 0)
{
Temp scratch = scratch_begin(0, 0);
filter_node = push_array(e_type_state->arena, E_MemberFilterNode, 1);
filter_node->filter = push_str8_copy(e_type_state->arena, filter);
filter_node = push_array(e_cache->arena, E_MemberFilterNode, 1);
filter_node->filter = push_str8_copy(e_cache->arena, filter);
E_MemberList member_list__filtered = {0};
for EachIndex(idx, node->members.count)
{
@@ -2095,7 +2052,7 @@ e_type_data_members_from_key_filter__cached(E_TypeKey key, String8 filter)
e_member_list_push(scratch.arena, &member_list__filtered, member);
}
}
filter_node->members_filtered = e_member_array_from_list(e_type_state->arena, &member_list__filtered);
filter_node->members_filtered = e_member_array_from_list(e_cache->arena, &member_list__filtered);
scratch_end(scratch);
}
members = filter_node->members_filtered;
@@ -2300,6 +2257,7 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(omit)
irtree_stripped.type_key = type->direct_type_key;
irtree_stripped.user_data = stripped_type->irext ? stripped_type->irext(scratch.arena, expr, &irtree_stripped).user_data : 0;
E_TypeExpandRule *expand_rule = e_expand_rule_from_type_key(irtree_stripped.type_key);
// TODO(rjf): @eval before expanding a type, ALWAYS select the parent key
E_TypeExpandInfo expand_info = expand_rule->info(scratch.arena, expr, &irtree_stripped, filter);
if(expand_info.expr_count < 4096)
{
@@ -2395,14 +2353,9 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(array)
U64 count = 1;
if(type->args != 0 && type->count > 0)
{
E_Expr *count_expr = type->args[0];
E_IRTreeAndType *prev_overridden_irtree = e_ir_state->overridden_irtree;
e_ir_state->overridden_irtree = irtree;
{
E_Value count_value = e_value_from_expr(count_expr);
count = count_value.u64;
}
e_ir_state->overridden_irtree = prev_overridden_irtree;
E_Key count_key = e_key_from_expr(type->args[0]);
E_Value count_value = e_value_from_key(count_key);
count = count_value.u64;
}
E_TypeExpandInfo info = {0, count};
return info;
@@ -2550,7 +2503,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(slice)
default:
case E_ExprKind_MemberAccess:
{
result = E_TYPE_ACCESS_FUNCTION_NAME(default)(arena, expr, lhs_irtree);
result = E_TYPE_ACCESS_FUNCTION_NAME(default)(arena, overridden, expr, lhs_irtree);
}break;
case E_ExprKind_ArrayIndex:
{
-141
View File
@@ -20,141 +20,6 @@ enum
E_TypeUnwrapFlag_AllDecorative = (E_TypeUnwrapFlag_All & ~E_TypeUnwrapFlag_Pointers)
};
////////////////////////////////
//~ rjf: Type Evaluation State
//- rjf: constructed type cache types
typedef struct E_ConsTypeParams E_ConsTypeParams;
struct E_ConsTypeParams
{
Arch arch;
E_TypeKind kind;
E_TypeFlags flags;
String8 name;
E_TypeKey direct_key;
U64 count;
U64 depth;
E_Member *members;
E_EnumVal *enum_vals;
E_Expr **args;
E_TypeIRExtFunctionType *irext;
E_TypeAccessFunctionType *access;
E_TypeExpandRule expand;
};
typedef struct E_ConsTypeNode E_ConsTypeNode;
struct E_ConsTypeNode
{
E_ConsTypeNode *key_next;
E_ConsTypeNode *content_next;
E_TypeKey key;
E_ConsTypeParams params;
U64 byte_size;
};
typedef struct E_ConsTypeSlot E_ConsTypeSlot;
struct E_ConsTypeSlot
{
E_ConsTypeNode *first;
E_ConsTypeNode *last;
};
//- rjf: unpacked type cache
typedef struct E_TypeCacheNode E_TypeCacheNode;
struct E_TypeCacheNode
{
E_TypeCacheNode *next;
E_TypeKey key;
E_Type *type;
};
typedef struct E_TypeCacheSlot E_TypeCacheSlot;
struct E_TypeCacheSlot
{
E_TypeCacheNode *first;
E_TypeCacheNode *last;
};
//- rjf: member lookup cache types
typedef struct E_MemberHashNode E_MemberHashNode;
struct E_MemberHashNode
{
E_MemberHashNode *next;
U64 member_idx;
};
typedef struct E_MemberHashSlot E_MemberHashSlot;
struct E_MemberHashSlot
{
E_MemberHashNode *first;
E_MemberHashNode *last;
};
typedef struct E_MemberFilterNode E_MemberFilterNode;
struct E_MemberFilterNode
{
E_MemberFilterNode *next;
String8 filter;
E_MemberArray members_filtered;
};
typedef struct E_MemberFilterSlot E_MemberFilterSlot;
struct E_MemberFilterSlot
{
E_MemberFilterNode *first;
E_MemberFilterNode *last;
};
typedef struct E_MemberCacheNode E_MemberCacheNode;
struct E_MemberCacheNode
{
E_MemberCacheNode *next;
E_TypeKey key;
E_MemberArray members;
U64 member_hash_slots_count;
E_MemberHashSlot *member_hash_slots;
U64 member_filter_slots_count;
E_MemberFilterSlot *member_filter_slots;
};
typedef struct E_MemberCacheSlot E_MemberCacheSlot;
struct E_MemberCacheSlot
{
E_MemberCacheNode *first;
E_MemberCacheNode *last;
};
//- rjf: bundle
typedef struct E_TypeState E_TypeState;
struct E_TypeState
{
Arena *arena;
U64 arena_eval_start_pos;
// rjf: JIT-constructed types tables
U64 cons_id_gen;
U64 cons_content_slots_count;
U64 cons_key_slots_count;
E_ConsTypeSlot *cons_content_slots;
E_ConsTypeSlot *cons_key_slots;
// rjf: build-in constructed type keys
E_TypeKey file_type_key;
E_TypeKey folder_type_key;
// rjf: member cache table
U64 member_cache_slots_count;
E_MemberCacheSlot *member_cache_slots;
// rjf: unpacked type cache
U64 type_cache_slots_count;
E_TypeCacheSlot *type_cache_slots;
};
////////////////////////////////
//~ rjf: Globals
@@ -171,7 +36,6 @@ global read_only E_TypeExpandRule e_type_expand_rule__default =
E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity),
E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity),
};
thread_static E_TypeState *e_type_state = 0;
////////////////////////////////
//~ rjf: Type Kind Enum Functions
@@ -192,11 +56,6 @@ internal void e_member_list_push(Arena *arena, E_MemberList *list, E_Member *mem
#define e_member_list_push_new(arena, list, ...) e_member_list_push((arena), (list), &(E_Member){.kind = E_MemberKind_DataField, __VA_ARGS__})
internal E_MemberArray e_member_array_from_list(Arena *arena, E_MemberList *list);
////////////////////////////////
//~ rjf: Type Evaluation Phase Beginning Marker (Required For All Subsequent APIs)
internal void e_type_eval_begin(void);
////////////////////////////////
//~ rjf: Type Operation Functions
@@ -586,6 +586,7 @@ ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval eval
}
// rjf: get top-level lookup/expansion info
// TODO(rjf): @eval before expanding a type, ALWAYS select the parent key
E_TypeExpandInfo type_expand_info = type_expand_rule->info(arena, t->eval.expr, &t->eval.irtree, filter);
EV_ExpandInfo viz_expand_info = viz_expand_rule->info(arena, view, filter, t->eval.expr);
@@ -705,7 +706,7 @@ ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval eval
type_expand_rule->range(arena, type_expand_info.user_data, t->eval.expr, &t->eval.irtree, filter, r1u64(split_relative_idx, split_relative_idx+1), &child_expr, &child_string);
if(child_expr != &e_expr_nil)
{
E_Eval child_eval = e_eval_from_expr(arena, child_expr);
E_Eval child_eval = e_eval_from_expr(child_expr);
EV_Key child_key = child_keys[idx];
Task *task = push_array(scratch.arena, Task, 1);
SLLQueuePush(first_task, last_task, task);
@@ -725,7 +726,7 @@ ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval eval
task->next = t->next;
t->next = task;
task->parent_block = t->parent_block;
task->eval = e_eval_from_expr(arena, t->eval.expr->next);
task->eval = e_eval_from_expr(t->eval.expr->next);
task->child_id = t->child_id + 1;
task->split_relative_idx = 0;
task->default_expanded = t->default_expanded;
@@ -1046,7 +1047,7 @@ ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8
U64 child_id = ev_block_id_from_num(n->v.block, child_num);
EV_Key row_key = ev_key_make(ev_hash_from_key(n->v.block->key), child_id);
E_Expr *row_expr = range_exprs[idx];
E_Eval row_eval = e_eval_from_expr(arena, row_expr);
E_Eval row_eval = e_eval_from_expr(row_expr);
EV_WindowedRowNode *row_node = push_array(arena, EV_WindowedRowNode, 1);
SLLQueuePush(rows.first, rows.last, row_node);
rows.count += 1;
@@ -2055,7 +2056,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
if(ptr_data->type->count == 1)
{
E_Expr *deref_expr = e_expr_irext_deref(arena, eval.expr, &eval.irtree);
E_Eval deref_eval = e_eval_from_expr(arena, deref_expr);
E_Eval deref_eval = e_eval_from_expr(deref_expr);
need_new_task = 1;
need_pop = 0;
new_task.params = *params;
@@ -2105,6 +2106,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
expand_data = it->top_task->user_data = push_array(arena, EV_ExpandedTypeData, 1);
expand_data->type = e_type_from_key__cached(type_key);
expand_data->expand_rule = e_expand_rule_from_type_key(type_key);
// TODO(rjf): @eval before expanding a type, ALWAYS select the parent key
expand_data->expand_info = expand_data->expand_rule->info(arena, eval.expr, &eval.irtree, params->filter);
}
switch(task_idx)
@@ -2134,7 +2136,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
need_new_task = 1;
need_pop = 0;
new_task.params = *params;
new_task.eval = e_eval_from_expr(arena, next_expr);
new_task.eval = e_eval_from_expr(next_expr);
if(task_idx > 1)
{
*out_string = str8_lit(", ");
@@ -294,7 +294,7 @@ global read_only EV_Block ev_nil_block =
{0},
0,
{0},
{&e_expr_nil, &e_irnode_nil},
{{0}, &e_expr_nil, &e_irnode_nil},
{0},
&e_type_expand_rule__default,
{0},
+44 -74
View File
@@ -1245,7 +1245,7 @@ rd_setting_b32_from_name(String8 name)
Temp scratch = scratch_begin(0, 0);
String8 value = rd_setting_from_name(name);
String8 expr = push_str8f(scratch.arena, "(bool)(%S)", value);
E_Eval eval = e_eval_from_string(scratch.arena, expr);
E_Eval eval = e_eval_from_string(expr);
B32 result = !!e_value_eval_from_eval(eval).value.u64;
scratch_end(scratch);
return result;
@@ -1257,7 +1257,7 @@ rd_setting_u64_from_name(String8 name)
Temp scratch = scratch_begin(0, 0);
String8 value = rd_setting_from_name(name);
String8 expr = push_str8f(scratch.arena, "(uint64)(%S)", value);
E_Eval eval = e_eval_from_string(scratch.arena, expr);
E_Eval eval = e_eval_from_string(expr);
U64 result = e_value_eval_from_eval(eval).value.u64;
scratch_end(scratch);
return result;
@@ -1269,7 +1269,7 @@ rd_setting_f32_from_name(String8 name)
Temp scratch = scratch_begin(0, 0);
String8 value = rd_setting_from_name(name);
String8 expr = push_str8f(scratch.arena, "(float32)(%S)", value);
E_Eval eval = e_eval_from_string(scratch.arena, expr);
E_Eval eval = e_eval_from_string(expr);
F32 result = e_value_eval_from_eval(eval).value.f32;
scratch_end(scratch);
return result;
@@ -2029,7 +2029,7 @@ rd_commit_eval_value_string(E_Eval dst_eval, String8 string)
got_commit_data = 1;
E_Expr *src_expr = e_parse_from_string(string).expr;
E_Expr *src_expr__casted = e_expr_ref_cast(scratch.arena, type_key, src_expr);
E_Eval src_eval = e_eval_from_expr(scratch.arena, src_expr__casted);
E_Eval src_eval = e_eval_from_expr(src_expr__casted);
commit_data = push_str8_copy(scratch.arena, str8_struct(&src_eval.value));
commit_data.size = Min(commit_data.size, e_type_byte_size_from_key(type_key));
}
@@ -2095,7 +2095,7 @@ rd_commit_eval_value_string(E_Eval dst_eval, String8 string)
//- rjf: pointer? -> try to treat new value as numeric value
if(!got_commit_data && type_kind == E_TypeKind_Ptr)
{
E_Eval src_eval = e_eval_from_string(scratch.arena, string);
E_Eval src_eval = e_eval_from_string(string);
E_Eval src_eval_value = e_value_eval_from_eval(src_eval);
E_TypeKind src_eval_value_type_kind = e_type_kind_from_key(src_eval_value.irtree.type_key);
if((e_type_kind_is_pointer_or_ref(src_eval_value_type_kind) ||
@@ -2156,7 +2156,7 @@ rd_file_path_from_eval_string(Arena *arena, String8 string)
String8 result = {0};
{
Temp scratch = scratch_begin(&arena, 1);
E_Eval eval = e_eval_from_string(scratch.arena, string);
E_Eval eval = e_eval_from_string(string);
result = rd_file_path_from_eval(arena, eval);
scratch_end(scratch);
}
@@ -2617,7 +2617,7 @@ rd_view_ui(Rng2F32 rect)
}
// rjf: unpack view's target expression & hash
E_Eval eval = e_eval_from_string(scratch.arena, expr_string);
E_Eval eval = e_eval_from_string(expr_string);
Rng1U64 range = r1u64(0, 1024);
U128 key = rd_key_from_eval_space_range(eval.space, range, 0);
U128 hash = hs_hash_from_key(key, 0);
@@ -2709,7 +2709,7 @@ rd_view_ui(Rng2F32 rect)
Temp scratch = scratch_begin(0, 0);
RD_Font(RD_FontSlot_Code)
{
E_Eval eval = e_eval_from_string(scratch.arena, expr_string);
E_Eval eval = e_eval_from_string(expr_string);
RD_WatchViewState *ewv = rd_view_state(RD_WatchViewState);
UI_ScrollPt2 scroll_pos = rd_view_scroll_pos();
F32 entity_hover_t_rate = rd_setting_b32_from_name(str8_lit("hover_animations")) ? (1 - pow_f32(2, (-60.f * rd_state->frame_dt))) : 1.f;
@@ -4260,8 +4260,7 @@ rd_view_ui(Rng2F32 rect)
{
E_Expr *min_expr = cell_type->args[0];
E_Expr *max_expr = cell_type->args[1];
E_IRTreeAndType *prev_overridden_irtree = e_ir_state->overridden_irtree;
e_ir_state->overridden_irtree = &cell->eval.irtree;
E_ParentKey(cell->eval.key)
{
E_TypeKey slider_value_type = e_type_key_unwrap(cell_type->direct_type_key, E_TypeUnwrapFlag_AllDecorative);
slider_value_type_kind = e_type_kind_from_key(slider_value_type);
@@ -4270,7 +4269,6 @@ rd_view_ui(Rng2F32 rect)
cell_slider_min = e_value_from_expr(min_casted);
cell_slider_max = e_value_from_expr(max_casted);
}
e_ir_state->overridden_irtree = prev_overridden_irtree;
}
switch(slider_value_type_kind)
{
@@ -4399,10 +4397,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->eval.irtree.prev;
cell_info.view_ui_rule->ui(cell->eval, cell_rect);
e_ir_state->overridden_irtree = prev_overridden_irtree;
E_ParentKey(cell->eval.key)
{
cell_info.view_ui_rule->ui(cell->eval, cell_rect);
}
// rjf: loading fill
UI_Parent(loading_overlay_container)
@@ -4850,15 +4848,11 @@ 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;
for(E_IRTreeAndType *prev = expr_eval.irtree.prev; prev != 0; prev = prev->prev)
E_Eval expr_eval = e_eval_from_string(expr_string);
E_ParentKey(expr_eval.key)
{
e_ir_state->overridden_irtree = prev;
view_ui_rule->ui(expr_eval, rect);
}
view_ui_rule->ui(expr_eval, rect);
e_ir_state->overridden_irtree = prev_overridden_irtree;
scratch_end(scratch);
}
}
@@ -4950,48 +4944,34 @@ rd_view_cfg_from_string(String8 string)
internal E_Value
rd_view_cfg_value_from_string(String8 string)
{
Temp scratch = scratch_begin(0, 0);
RD_Cfg *root = rd_view_cfg_from_string(string);
String8 expr = root->first->string;
E_Eval eval = e_eval_from_string(scratch.arena, expr);
E_Eval eval = e_eval_from_string(expr);
E_Value result = e_value_eval_from_eval(eval).value;
scratch_end(scratch);
return result;
}
internal B32
rd_view_cfg_b32_from_string(String8 string)
{
Temp scratch = scratch_begin(0, 0);
RD_Cfg *root = rd_view_cfg_from_string(string);
String8 expr = push_str8f(scratch.arena, "(bool)(%S)", root->first->string);
E_Eval eval = e_eval_from_string(scratch.arena, expr);
B32 result = !!e_value_eval_from_eval(eval).value.u64;
scratch_end(scratch);
B32 result = !!e_value_from_stringf("(bool)(%S)", root->first->string).u64;
return result;
}
internal U64
rd_view_cfg_u64_from_string(String8 string)
{
Temp scratch = scratch_begin(0, 0);
RD_Cfg *root = rd_view_cfg_from_string(string);
String8 expr = push_str8f(scratch.arena, "(uint64)(%S)", root->first->string);
E_Eval eval = e_eval_from_string(scratch.arena, expr);
U64 result = e_value_eval_from_eval(eval).value.u64;
scratch_end(scratch);
U64 result = e_value_from_stringf("(uint64)(%S)", root->first->string).u64;
return result;
}
internal F32
rd_view_cfg_f32_from_string(String8 string)
{
Temp scratch = scratch_begin(0, 0);
RD_Cfg *root = rd_view_cfg_from_string(string);
String8 expr = push_str8f(scratch.arena, "(float32)(%S)", root->first->string);
E_Eval eval = e_eval_from_string(scratch.arena, expr);
F32 result = e_value_eval_from_eval(eval).value.f32;
scratch_end(scratch);
F32 result = e_value_from_stringf("(float32)(%S)", root->first->string).f32;
return result;
}
@@ -5912,7 +5892,7 @@ rd_window_frame(void)
{
rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), rd_state->drag_drop_regs->expr);
ui_spacer(ui_em(2.f, 1.f));
E_Eval eval = e_eval_from_string(scratch.arena, rd_state->drag_drop_regs->expr);
E_Eval eval = e_eval_from_string(rd_state->drag_drop_regs->expr);
if(eval.irtree.mode != E_Mode_Null)
{
EV_StringParams string_params = {.flags = EV_StringFlag_ReadOnlyDisplayRules, .radix = 10};
@@ -6294,7 +6274,7 @@ rd_window_frame(void)
// rjf: evaluate hover evaluation expression, & determine if it evaluates
// such that we want to build a hover eval.
E_Eval hover_eval = e_eval_from_string(scratch.arena, hover_eval_expr);
E_Eval hover_eval = e_eval_from_string(hover_eval_expr);
{
if(hover_eval.msgs.max_kind > E_MsgKind_Null)
{
@@ -6405,7 +6385,7 @@ rd_window_frame(void)
if(query_is_open)
{
String8 expr = ws->query_regs->expr;
E_Eval eval = e_eval_from_string(scratch.arena, expr);
E_Eval eval = e_eval_from_string(expr);
if(eval.msgs.max_kind > E_MsgKind_Null)
{
query_is_open = 0;
@@ -6473,7 +6453,7 @@ rd_window_frame(void)
}
// rjf: evaluate query expression
E_Eval query_eval = e_eval_from_string(scratch.arena, query_expr);
E_Eval query_eval = e_eval_from_string(query_expr);
// rjf: determine & store row-height setting
if(ws->query_regs->do_big_rows)
@@ -10228,7 +10208,7 @@ rd_theme_color_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8 str
// rjf: try to map as local
if(!mapped && kind == TXT_TokenKind_Identifier)
{
U64 local_num = e_num_from_string(e_ir_state->ctx->locals_map, string);
U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string);
if(local_num != 0)
{
mapped = 1;
@@ -10239,7 +10219,7 @@ rd_theme_color_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8 str
// rjf: try to map as member
if(!mapped && kind == TXT_TokenKind_Identifier)
{
U64 member_num = e_num_from_string(e_ir_state->ctx->member_map, string);
U64 member_num = e_num_from_string(e_ir_ctx->member_map, string);
if(member_num != 0)
{
mapped = 1;
@@ -10250,7 +10230,7 @@ rd_theme_color_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8 str
// rjf: try to map as register
if(!mapped)
{
U64 reg_num = e_num_from_string(e_ir_state->ctx->regs_map, string);
U64 reg_num = e_num_from_string(e_ir_ctx->regs_map, string);
if(reg_num != 0)
{
mapped = 1;
@@ -10261,7 +10241,7 @@ rd_theme_color_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8 str
// rjf: try to map as register alias
if(!mapped)
{
U64 alias_num = e_num_from_string(e_ir_state->ctx->reg_alias_map, string);
U64 alias_num = e_num_from_string(e_ir_ctx->reg_alias_map, string);
if(alias_num != 0)
{
mapped = 1;
@@ -10650,8 +10630,7 @@ rd_regs_fill_slot_from_string(RD_RegSlot slot, String8 string)
case RD_RegSlot_PID: goto use_numeric_eval;
use_numeric_eval:
{
Temp scratch = scratch_begin(0, 0);
E_Eval eval = e_eval_from_string(scratch.arena, string);
E_Eval eval = e_eval_from_string(string);
if(eval.msgs.max_kind == E_MsgKind_Null)
{
E_TypeKind eval_type_kind = e_type_kind_from_key(e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative));
@@ -10691,7 +10670,6 @@ rd_regs_fill_slot_from_string(RD_RegSlot slot, String8 string)
{
log_user_errorf("Couldn't evaluate \"%S\" as an address.", string);
}
scratch_end(scratch);
}break;
}
}
@@ -10816,6 +10794,7 @@ rd_init(CmdLine *cmdln)
rd_state->num_frames_requested = 2;
rd_state->seconds_until_autosave = 0.5f;
rd_state->match_store = di_match_store_alloc();
rd_state->eval_cache = e_cache_alloc();
for(U64 idx = 0; idx < ArrayCount(rd_state->cmds_arenas); idx += 1)
{
rd_state->cmds_arenas[idx] = arena_alloc();
@@ -11815,6 +11794,11 @@ rd_frame(void)
}
ProfEnd();
////////////////////////////
//- rjf: begin evaluation
//
e_select_cache(rd_state->eval_cache);
////////////////////////////
//- rjf: build base evaluation context
//
@@ -11840,12 +11824,6 @@ rd_frame(void)
}
e_select_base_ctx(eval_base_ctx);
////////////////////////////
//- rjf: begin type evaluation
//
e_parse_eval_begin();
e_type_eval_begin();
////////////////////////////
//- rjf: build extra types & maps
//
@@ -12460,11 +12438,6 @@ rd_frame(void)
}
e_select_interpret_ctx(interpret_ctx, eval_modules_primary->rdi, rip_voff);
////////////////////////////
//- rjf: begin cached evaluations
//
e_cache_eval_begin();
////////////////////////////
//- rjf: autosave if needed
//
@@ -15842,19 +15815,16 @@ Z(getting_started)
{
if(t->expr->kind == E_ExprKind_LeafIdentifier)
{
E_Expr *macro_expr = e_string2expr_lookup(e_ir_state->ctx->macro_map, t->expr->string);
if(macro_expr != &e_expr_nil)
E_Expr *macro_expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, t->expr->string);
E_Eval eval = e_eval_from_string(t->expr->string);
switch(eval.space.kind)
{
E_Eval eval = e_eval_from_expr(scratch.arena, macro_expr);
switch(eval.space.kind)
default:{is_static_for_ctrl_thread = 0;}break;
case E_SpaceKind_Null:
case RD_EvalSpaceKind_MetaCfg:
{
default:{is_static_for_ctrl_thread = 0;}break;
case E_SpaceKind_Null:
case RD_EvalSpaceKind_MetaCfg:
{
is_static_for_ctrl_thread = 1;
}break;
}
is_static_for_ctrl_thread = 1;
}break;
}
}
for(E_Expr *child = t->expr->first; child != &e_expr_nil; child = child->next)
@@ -15874,7 +15844,7 @@ Z(getting_started)
String8 non_ctrl_thread_static_condition = src_bp_cnd;
if(is_static_for_ctrl_thread)
{
E_Eval eval = e_eval_from_string(scratch.arena, src_bp_cnd);
E_Eval eval = e_eval_from_string(src_bp_cnd);
E_Eval value_eval = e_value_eval_from_eval(eval);
if(value_eval.value.u64 == 0)
{
+3
View File
@@ -635,6 +635,9 @@ struct RD_State
// rjf: dbgi match store
DI_MatchStore *match_store;
// rjf: evaluation cache
E_Cache *eval_cache;
// rjf: ambiguous path table (constructed from-scratch each frame)
U64 ambiguous_path_slots_count;
RD_AmbiguousPathNode **ambiguous_path_slots;
+7 -13
View File
@@ -75,14 +75,8 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(commands)
for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1)
{
String8 cmd_name = accel->v[idx];
RD_CmdKindInfo *cmd_info = rd_cmd_kind_info_from_string(cmd_name);
E_TypeKey cmd_type = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("command"));
cmd_type = e_type_key_cons_meta_description(cmd_type, cmd_info->description);
E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafValue, 0);
expr->type_key = cmd_type;
expr->space = e_space_make(RD_EvalSpaceKind_MetaCmd);
expr->value.u64 = e_id_from_string(cmd_name);
exprs_out[out_idx] = expr;
E_Eval cmd_eval = e_eval_from_stringf("query:commands.%S", cmd_name);
exprs_out[out_idx] = cmd_eval.expr;
}
}
@@ -105,7 +99,7 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(watches)
B32 passes_filter = 1;
if(filter.size != 0)
{
E_Eval eval = e_eval_from_string(scratch.arena, expr);
E_Eval eval = e_eval_from_string(expr);
E_Type *type = e_type_from_key__cached(eval.irtree.type_key);
if(type->kind != E_TypeKind_Set)
{
@@ -196,7 +190,7 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(locals)
E_TypeExpandInfo result = {0};
Temp scratch = scratch_begin(&arena, 1);
{
E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_ir_state->ctx->locals_map);
E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_ir_ctx->locals_map);
e_string2num_map_node_array_sort__in_place(&nodes);
String8List exprs_filtered = {0};
for EachIndex(idx, nodes.count)
@@ -768,12 +762,12 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(cfgs)
{
Rng1U64 read_range = intersect_1u64(cmds_idx_range, idx_range);
U64 read_count = dim_1u64(read_range);
E_Expr *commands = e_parse_from_string(str8_lit("query:commands")).expr;
E_IRTreeAndType commands_irtree = e_irtree_and_type_from_expr(commands);
E_Eval cmds_eval = e_eval_from_stringf("query:commands");
for(U64 idx = 0; idx < read_count; idx += 1, dst_idx += 1)
{
String8 cmd_name = accel->cmds.v[idx + read_range.min - cmds_idx_range.min];
exprs_out[dst_idx] = e_expr_irext_member_access(arena, commands, &commands_irtree, cmd_name);
E_Eval cmd_eval = e_eval_wrapf(cmds_eval, "$.%S", cmd_name);
exprs_out[dst_idx] = cmd_eval.expr;
}
}
+27 -32
View File
@@ -1108,14 +1108,14 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
RD_Cfg *w_cfg = style->first;
F32 next_pct = 0;
#define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct)
E_IRTreeAndType *prev_overridden_irtree = e_ir_state->overridden_irtree;
e_ir_state->overridden_irtree = &row->eval.irtree;
for(U64 idx = 0; idx < maybe_table_type->count; idx += 1)
E_ParentKey(row->eval.key)
{
E_Eval cell_eval = e_eval_from_expr(arena, maybe_table_type->args[idx]);
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, cell_eval, .default_pct = 1.f/maybe_table_type->count, .pct = take_pct());
for(U64 idx = 0; idx < maybe_table_type->count; idx += 1)
{
E_Eval cell_eval = e_eval_from_expr(maybe_table_type->args[idx]);
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, cell_eval, .default_pct = 1.f/maybe_table_type->count, .pct = take_pct());
}
}
e_ir_state->overridden_irtree = prev_overridden_irtree;
info.can_expand = 0;
#undef take_pct
}
@@ -1229,7 +1229,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
}
if(cmd_kind == RD_CmdKind_EnableCfg || cmd_kind == RD_CmdKind_DisableCfg)
{
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(arena, row->eval, "enabled"),
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "enabled"),
.flags = RD_WatchCellFlag_Background,
.px = floor_f32(ui_top_font_size()*5.f));
}
@@ -1237,7 +1237,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
{
String8 cmd_name = rd_cmd_kind_info_table[cmd_kind].string;
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval,
e_eval_from_stringf(arena, "query:commands.%S", cmd_name),
e_eval_from_stringf("query:commands.%S", cmd_name),
.flags = RD_WatchCellFlag_ActivateWithSingleClick|RD_WatchCellFlag_Button,
.px = floor_f32(ui_top_font_size()*3.f));
}
@@ -1259,7 +1259,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
entity->kind == CTRL_EntityKind_Process ||
entity->kind == CTRL_EntityKind_Thread)
{
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(arena, row->eval, "active"),
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "active"),
.edit_string = row->edit_string,
.px = floor_f32(ui_top_font_size()*5.f));
}
@@ -1271,7 +1271,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
cmd_kind = RD_CmdKind_DeselectEntity;
}
String8 cmd_name = rd_cmd_kind_info_table[cmd_kind].string;
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_from_stringf(arena, "query:commands.%S", cmd_name),
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_from_stringf("query:commands.%S", cmd_name),
.edit_string = row->edit_string,
.flags = RD_WatchCellFlag_ActivateWithSingleClick|RD_WatchCellFlag_Button,
.px = floor_f32(ui_top_font_size()*3.f));
@@ -1383,7 +1383,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
.flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented,
.default_pct = 0.75f,
.pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(arena, row->eval, "lens:hex((uint64)$)"), .default_pct = 0.25f, .pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "lens:hex((uint64)$)"), .default_pct = 0.25f, .pct = take_pct());
#undef take_pct
}
@@ -1395,12 +1395,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
info.cell_style_key = str8_lit("call_stack_frame");
CTRL_Entity *process = ctrl_process_from_entity(info.callstack_thread);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, info.callstack_vaddr);
E_Space space = rd_eval_space_from_ctrl_entity(module, RD_EvalSpaceKind_MetaCtrlEntity);
E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafOffset, 0);
expr->space = space;
expr->mode = E_Mode_Offset;
expr->type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, str8_lit("module"));
E_Eval module_eval = e_eval_from_expr(arena, expr);
E_Eval module_eval = ctrl_eval_from_handle(module->handle);
RD_Cfg *view = rd_cfg_from_id(rd_regs()->view);
RD_Cfg *style = rd_cfg_child_from_string(view, info.cell_style_key);
RD_Cfg *w_cfg = style->first;
@@ -1408,7 +1403,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
#define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct)
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_CallStackFrame, row->eval, .default_pct = 0.05f, .pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .default_pct = 0.55f, .pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(arena, row->eval, "lens:hex((uint64)$)"), .default_pct = 0.20f, .pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "lens:hex((uint64)$)"), .default_pct = 0.20f, .pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, (module == &ctrl_entity_nil ? (E_Eval)zero_struct : module_eval),
.default_pct = 0.20f, .pct = take_pct());
#undef take_pct
@@ -1430,8 +1425,8 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row)
.flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented,
.default_pct = 0.35f,
.pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .default_pct = 0.40f, .pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(arena, row->eval, "typeof(raw($))"), .default_pct = 0.25f, .pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .default_pct = 0.40f, .pct = take_pct());
rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "typeof(raw($))"), .default_pct = 0.25f, .pct = take_pct());
#undef take_pct
}
@@ -2088,13 +2083,13 @@ RD_VIEW_UI_FUNCTION_DEF(disasm)
{
auto_selected = 1;
auto_space = rd_eval_space_from_ctrl_entity(ctrl_entity_from_handle(d_state->ctrl_entity_store, dv->temp_look_process), RD_EvalSpaceKind_CtrlEntity);
eval = e_eval_from_stringf(scratch.arena, "(0x%I64x & (~(0x4000 - 1)))", dv->temp_look_vaddr);
eval = e_eval_from_stringf("(0x%I64x & (~(0x4000 - 1)))", dv->temp_look_vaddr);
}
else
{
auto_selected = 1;
auto_space = rd_eval_space_from_ctrl_entity(ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->process), RD_EvalSpaceKind_CtrlEntity);
eval = e_eval_from_stringf(scratch.arena, "(rip.u64 & (~(0x4000 - 1)))");
eval = e_eval_from_stringf("(rip.u64 & (~(0x4000 - 1)))");
}
}
@@ -2655,10 +2650,10 @@ RD_VIEW_UI_FUNCTION_DEF(memory)
ui_color_from_name(str8_lit("code_local")),
};
U64 thread_rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, rd_regs()->unwind_count);
for(E_String2NumMapNode *n = e_ir_state->ctx->locals_map->first; n != 0; n = n->order_next)
for(E_String2NumMapNode *n = e_ir_ctx->locals_map->first; n != 0; n = n->order_next)
{
String8 local_name = n->string;
E_Eval local_eval = e_eval_from_string(scratch.arena, local_name);
E_Eval local_eval = e_eval_from_string(local_name);
if(local_eval.irtree.mode == E_Mode_Offset)
{
E_TypeKind local_eval_type_kind = e_type_kind_from_key(local_eval.irtree.type_key);
@@ -3463,20 +3458,20 @@ rd_eval_color_from_eval(E_Eval eval)
// rjf: leaf u32 -> take all 4 components
case E_TypeKind_U32:
{
component_evals[0] = e_value_eval_from_eval(e_eval_wrapf(scratch.arena, t->eval, "(float32)(($ & 0xff000000) >> 24) / 255.f"));
component_evals[1] = e_value_eval_from_eval(e_eval_wrapf(scratch.arena, t->eval, "(float32)(($ & 0x00ff0000) >> 16) / 255.f"));
component_evals[2] = e_value_eval_from_eval(e_eval_wrapf(scratch.arena, t->eval, "(float32)(($ & 0x0000ff00) >> 8) / 255.f"));
component_evals[3] = e_value_eval_from_eval(e_eval_wrapf(scratch.arena, t->eval, "(float32)(($ & 0x000000ff) >> 0) / 255.f"));
component_evals[0] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)(($ & 0xff000000) >> 24) / 255.f"));
component_evals[1] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)(($ & 0x00ff0000) >> 16) / 255.f"));
component_evals[2] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)(($ & 0x0000ff00) >> 8) / 255.f"));
component_evals[3] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)(($ & 0x000000ff) >> 0) / 255.f"));
num_components_left -= 4;
}break;
//- rjf: array -> generate tasks for first four elements
case E_TypeKind_Array:
{
component_evals[0] = e_value_eval_from_eval(e_eval_wrapf(scratch.arena, t->eval, "(float32)($[0])"));
component_evals[1] = e_value_eval_from_eval(e_eval_wrapf(scratch.arena, t->eval, "(float32)($[1])"));
component_evals[2] = e_value_eval_from_eval(e_eval_wrapf(scratch.arena, t->eval, "(float32)($[2])"));
component_evals[3] = e_value_eval_from_eval(e_eval_wrapf(scratch.arena, t->eval, "(float32)($[3])"));
component_evals[0] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)($[0])"));
component_evals[1] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)($[1])"));
component_evals[2] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)($[2])"));
component_evals[3] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)($[3])"));
num_components_left -= 4;
}break;
}
+2 -2
View File
@@ -1983,7 +1983,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe
{
RD_Cfg *pin = n->v;
String8 pin_expr = rd_expr_from_cfg(pin);
E_Eval eval = e_eval_from_string(scratch.arena, pin_expr);
E_Eval eval = e_eval_from_string(pin_expr);
String8 eval_string = {0};
if(!e_type_key_match(e_type_key_zero(), eval.irtree.type_key))
{
@@ -2327,7 +2327,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe
//
if(!ui_dragging(text_container_sig) && text_container_sig.event_flags == 0 && mouse_expr.size != 0)
{
E_Eval eval = e_eval_from_string(scratch.arena, mouse_expr);
E_Eval eval = e_eval_from_string(mouse_expr);
if(eval.msgs.max_kind == E_MsgKind_Null && (eval.irtree.mode != E_Mode_Null || mouse_expr_is_explicit))
{
U64 line_vaddr = 0;