mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-12 23:31:38 -07:00
first pass at list view, w/ asynchronous offset chain gathering
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+211
-12
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user