diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 66e3d0c3..7c9a2a78 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -4443,7 +4443,6 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C // { E_InterpretCtx *ctx = &scope->interpret_ctx; - ctx->space_read = ctrl_eval_space_read; ctx->primary_space = eval_modules_primary->space; ctx->reg_arch = eval_modules_primary->arch; ctx->reg_space = e_space_make(CTRL_EvalSpaceKind_Entity); diff --git a/src/eval/eval_core.h b/src/eval/eval_core.h index a0a35717..19e35783 100644 --- a/src/eval/eval_core.h +++ b/src/eval/eval_core.h @@ -766,7 +766,6 @@ struct E_BaseCtx E_Module *primary_module; // rjf: space hooks - void *space_rw_user_data; E_SpaceGenFunction *space_gen; E_SpaceRWFunction *space_read; E_SpaceRWFunction *space_write; diff --git a/src/eval/eval_interpret.c b/src/eval/eval_interpret.c index 74fffeda..53710f16 100644 --- a/src/eval/eval_interpret.c +++ b/src/eval/eval_interpret.c @@ -130,9 +130,9 @@ e_space_read(E_Space space, void *out, Rng1U64 range) //- rjf: default -> use hooks default: - if(e_interpret_ctx->space_read != 0) + if(e_base_ctx->space_read != 0) { - result = e_interpret_ctx->space_read(space, out, range); + result = e_base_ctx->space_read(space, out, range); }break; } } @@ -145,13 +145,13 @@ e_space_write(E_Space space, void *in, Rng1U64 range) { ProfBeginFunction(); B32 result = 0; - if(e_interpret_ctx->space_write != 0) + if(e_base_ctx->space_write != 0) { switch(space.kind) { default: { - result = e_interpret_ctx->space_write(space, in, range); + result = e_base_ctx->space_write(space, in, range); }break; } } diff --git a/src/eval/eval_interpret.h b/src/eval/eval_interpret.h index 4151a837..590d4e4e 100644 --- a/src/eval/eval_interpret.h +++ b/src/eval/eval_interpret.h @@ -10,8 +10,6 @@ typedef struct E_InterpretCtx E_InterpretCtx; struct E_InterpretCtx { - E_SpaceRWFunction *space_read; - E_SpaceRWFunction *space_write; E_Space primary_space; Arch reg_arch; E_Space reg_space; diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index 23deef63..ffc9c747 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -2573,47 +2573,246 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(array) //////////////////////////////// //~ rjf: (Built-In Type Hooks) `list` lens -typedef struct E_ListGatherArtifact E_ListGatherArtifact; -struct E_ListGatherArtifact -{ - U64 *node_vaddrs; - U64 node_vaddrs_count; -}; - internal AC_Artifact e_list_gather_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { + Temp scratch = scratch_begin(0, 0); + //- rjf: unpack key + E_Space space = {0}; + U64 base_off = 0; + U64 member_element_off = 0; + U64 member_size = 0; + E_SpaceRWFunction *space_read = 0; + { + U64 key_read_off = 0; + key_read_off += str8_deserial_read_struct(key, key_read_off, &space); + key_read_off += str8_deserial_read_struct(key, key_read_off, &base_off); + key_read_off += str8_deserial_read_struct(key, key_read_off, &member_element_off); + key_read_off += str8_deserial_read_struct(key, key_read_off, &member_size); + key_read_off += str8_deserial_read_struct(key, key_read_off, &space_read); + } + + //- rjf: gather chain + typedef struct HitOffsetNode HitOffsetNode; + struct HitOffsetNode + { + HitOffsetNode *next; + U64 off; + }; + typedef struct OffsetChunk OffsetChunk; + struct OffsetChunk + { + OffsetChunk *next; + U64 *v; + U64 count; + U64 cap; + }; + OffsetChunk *first_chunk = 0; + OffsetChunk *last_chunk = 0; + U64 total_count = 0; + { + U64 hit_slots_count = 4096; + HitOffsetNode **hit_slots = push_array(scratch.arena, HitOffsetNode *, hit_slots_count); + for(U64 off = base_off, next_off = 0;; off = next_off) + { + //- rjf: see if we've cycled + B32 hit_cycle = 0; + { + U64 hash = u64_hash_from_str8(str8_struct(&off)); + U64 slot_idx = hash%hit_slots_count; + for(HitOffsetNode *n = hit_slots[slot_idx]; n != 0; n = n->next) + { + if(n->off == off) + { + hit_cycle = 1; + break; + } + } + } + + //- rjf: terminate loop + B32 terminated = (hit_cycle || off == 0); + if(terminated) + { + break; + } + + //- rjf: another node -> push offset to chunk list + OffsetChunk *chunk = last_chunk; + if(chunk == 0 || chunk->count >= chunk->cap) + { + chunk = push_array(scratch.arena, OffsetChunk, 1); + SLLQueuePush(first_chunk, last_chunk, chunk); + chunk->cap = 1024; + chunk->v = push_array_no_zero(scratch.arena, U64, chunk->cap); + } + chunk->v[chunk->count] = off; + chunk->count += 1; + total_count += 1; + + //- rjf: read next offset, advance + if(!space_read(space, &next_off, r1u64(off + member_element_off, off + member_element_off + member_size))) + { + break; + } + } + } + + //- rjf: flatten + Arena *arena = 0; + U64 node_offs_count = 0; + U64 *node_offs = 0; + if(total_count != 0) + { + arena = arena_alloc(); + node_offs_count = total_count; + node_offs = push_array_no_zero(arena, U64, node_offs_count); + { + U64 idx = 0; + for EachNode(n, OffsetChunk, first_chunk) + { + MemoryCopy(node_offs + idx, n->v, n->count * sizeof(n->v[0])); + idx += n->count; + } + } + } + + //- rjf: package + AC_Artifact artifact = {0}; + { + artifact.u64[0] = (U64)arena; + artifact.u64[1] = (U64)node_offs; + artifact.u64[2] = node_offs_count; + } + + scratch_end(scratch); + return artifact; } internal void e_list_gather_artifact_destroy(AC_Artifact artifact) { - + Arena *arena = (Arena *)artifact.u64[0]; + if(arena != 0) + { + arena_release(arena); + } } -E_TYPE_EXPAND_INFO_FUNCTION_DEF(list) +typedef struct E_ListIRExt E_ListIRExt; +struct E_ListIRExt { - E_Type *type = e_type_from_key(eval.irtree.type_key); + U64 *offs; + U64 offs_count; +}; + +E_TYPE_IREXT_FUNCTION_DEF(list) +{ + E_IRExt result = {0}; + E_Type *type = e_type_from_key(irtree->type_key); String8 next_link_member_name = str8_lit("next"); if(type->args != 0 && type->count > 0) { next_link_member_name = type->args[0]->string; } - E_TypeKey node_type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_All); + E_TypeKey node_type_key = e_type_key_unwrap(irtree->type_key, E_TypeUnwrapFlag_All); E_Member next_link_member = e_type_member_from_key_name__cached(node_type_key, next_link_member_name); + E_TypeExpandInfo info = {0, 0}; if(next_link_member.kind != E_MemberKind_DataField) { // TODO(rjf): error reporting } else { + Temp scratch = scratch_begin(&arena, 1); + Access *access = access_open(); + // rjf: evaluate first offset + E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree->root); + String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); + E_Interpretation base_off_interpret = e_interpret(bytecode); + + // rjf: get artifact +#pragma pack(push, 1) + struct + { + E_Space space; + U64 base_off; + U64 member_element_off; + U64 member_size; + E_SpaceRWFunction *space_read; + } + key_data = + { + base_off_interpret.space, + base_off_interpret.value.u64, + next_link_member.off, + e_type_byte_size_from_key(next_link_member.type_key), + e_base_ctx->space_read, + }; +#pragma pack(pop) + AC_Artifact gather_artifact = ac_artifact_from_key(access, str8_struct(&key_data), e_list_gather_artifact_create, e_list_gather_artifact_destroy, 0); + U64 *offs = (U64 *)gather_artifact.u64[1]; + U64 offs_count = gather_artifact.u64[2]; + + // rjf: fill info from artifact + E_ListIRExt *ext = push_array(arena, E_ListIRExt, 1); + ext->offs = offs; + ext->offs_count = offs_count; + result.user_data = ext; + + access_close(access); + scratch_end(scratch); } - E_TypeExpandInfo info = {0, 0}; + return result; +} + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(list) +{ + E_ListIRExt *ext = (E_ListIRExt *)eval.irtree.user_data; + U64 count = 0; + if(ext != 0) + { + count = ext->offs_count; + } + E_TypeExpandInfo info = {0, count}; return info; } +E_TYPE_ACCESS_FUNCTION_DEF(list) +{ + E_IRTreeAndType result = {&e_irnode_nil}; + E_ListIRExt *ext = (E_ListIRExt *)lhs_irtree->user_data; + if(ext != 0 && expr->kind == E_ExprKind_ArrayIndex) + { + Temp scratch = scratch_begin(&arena, 1); + + // rjf: compute index + E_Expr *rhs_expr = expr->last; + E_IRTreeAndType rhs_irtree = e_push_irtree_and_type_from_expr(scratch.arena, overridden, &e_default_identifier_resolution_rule, 0, 0, rhs_expr); + E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); + String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); + E_Interpretation rhs_interpret = e_interpret(rhs_bytecode); + U64 idx = rhs_interpret.value.u64; + + // rjf: get offset + U64 off = 0; + if(idx < ext->offs_count) + { + off = ext->offs[idx]; + } + + // rjf: generate IR tree to compute this offset w/ the node type + result.root = e_irtree_const_u(arena, off); + result.type_key = e_type_key_unwrap(lhs_irtree->type_key, E_TypeUnwrapFlag_AllDecorative); + result.mode = E_Mode_Offset; + + scratch_end(scratch); + } + return result; +} + E_TYPE_EXPAND_RANGE_FUNCTION_DEF(list) { U64 read_range_count = dim_1u64(idx_range); diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index ead2004e..8a506373 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -1179,6 +1179,7 @@ rdim_bake_params_concat_in_place(RDIM_BakeParams *dst, RDIM_BakeParams *src) { // rjf: join top-level info (deduplicate - throw away conflicts) { + dst->subset_flags |= src->subset_flags; if(dst->top_level_info.arch == RDI_Arch_NULL) { dst->top_level_info.arch = src->top_level_info.arch; diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index 19f70cb2..c363a09e 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -569,6 +569,18 @@ type_coverage_eval_tests(void) Linked_List list = {&list, &list, 0}; + struct SLLNode + { + SLLNode *next; + int x; + }; + SLLNode node6 = {0, 6}; + SLLNode node5 = {&node6, 5}; + SLLNode node4 = {&node5, 4}; + SLLNode node3 = {&node4, 3}; + SLLNode node2 = {&node3, 2}; + SLLNode node1 = {&node2, 1}; + Alias1 a1 = has_enums.kind; Alias2 a2 = has_enums.flags; Alias3 a3 = has_enums; diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index a5ab4c9b..d7d09916 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -12511,6 +12511,7 @@ rd_frame(void) {str8_lit("range1"), 0, 0, 0, 0, 0, {0}}, {str8_lit("array"), 0, 0, 1, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(array), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(array)}}, {str8_lit("slice"), 0, 0, 1, E_TYPE_IREXT_FUNCTION_NAME(slice), E_TYPE_ACCESS_FUNCTION_NAME(slice), {E_TYPE_EXPAND_INFO_FUNCTION_NAME(slice), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(slice)}}, + {str8_lit("list"), 0, 0, 1, E_TYPE_IREXT_FUNCTION_NAME(list), E_TYPE_ACCESS_FUNCTION_NAME(list), {E_TYPE_EXPAND_INFO_FUNCTION_NAME(list), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(list)}}, {str8_lit("text"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(text), EV_EXPAND_RULE_INFO_FUNCTION_NAME(text)}, {str8_lit("disasm"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(disasm), EV_EXPAND_RULE_INFO_FUNCTION_NAME(disasm)}, {str8_lit("memory"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(memory), EV_EXPAND_RULE_INFO_FUNCTION_NAME(memory)}, @@ -12685,8 +12686,6 @@ rd_frame(void) E_InterpretCtx *interpret_ctx = push_array(scratch.arena, E_InterpretCtx, 1); { E_InterpretCtx *ctx = interpret_ctx; - ctx->space_read = rd_eval_space_read; - ctx->space_write = rd_eval_space_write; ctx->primary_space = eval_modules_primary->space; ctx->reg_arch = eval_modules_primary->arch; ctx->reg_space = rd_eval_space_from_ctrl_entity(thread, CTRL_EvalSpaceKind_Entity);