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
+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