mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-09 19:11:38 -07:00
split eval systems, to decouple types/exprs/parsing (debug info dependent), from irization (macro map dependent), from interpretation (completely independent of the former two stages & all their dependencies)
This commit is contained in:
+81
-50
@@ -842,6 +842,7 @@ ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list)
|
||||
{
|
||||
CTRL_Entity *process = ctrl_entity_from_machine_id_handle(store, event->machine_id, event->parent);
|
||||
CTRL_Entity *thread = ctrl_entity_alloc(store, process, CTRL_EntityKind_Thread, event->arch, event->machine_id, event->entity, (U64)event->entity_id);
|
||||
ctrl_query_cached_rip_from_thread(store, event->machine_id, event->entity);
|
||||
}break;
|
||||
case CTRL_EventKind_EndThread:
|
||||
{
|
||||
@@ -4641,60 +4642,86 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: form evaluation context
|
||||
E_Ctx ectx = zero_struct;
|
||||
ProfScope("form evaluation context")
|
||||
// rjf: gather debug infos
|
||||
U64 rdis_count = all_modules_count;
|
||||
RDI_Parsed **rdis = push_array(temp.arena, RDI_Parsed *, rdis_count);
|
||||
Rng1U64 *rdis_vaddr_ranges = push_array(temp.arena, Rng1U64, rdis_count);
|
||||
RDI_Parsed *rdi_primary = &di_rdi_parsed_nil;
|
||||
ProfScope("gather debug infos")
|
||||
{
|
||||
E_Ctx *ctx = &ectx;
|
||||
U64 primary_idx = 0;
|
||||
U64 idx = 0;
|
||||
for(CTRL_Entity *m = process->first;
|
||||
m != &ctrl_entity_nil && idx < all_modules_count;
|
||||
m = m->next)
|
||||
{
|
||||
if(m->kind != CTRL_EntityKind_Module)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// rjf: unpack
|
||||
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(m, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
|
||||
|
||||
// rjf: fill
|
||||
rdis[idx] = di_rdi_from_key(di_scope, &dbgi_key, max_U64);
|
||||
rdis_vaddr_ranges[idx] = m->vaddr_range;
|
||||
|
||||
// rjf: pick primary module
|
||||
if(m == module)
|
||||
{
|
||||
rdi_primary = rdis[idx];
|
||||
}
|
||||
|
||||
// rjf: inc
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: build eval type context
|
||||
E_TypeCtx type_ctx = zero_struct;
|
||||
{
|
||||
E_TypeCtx *ctx = &type_ctx;
|
||||
ctx->arch = arch;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->rdis_count = all_modules_count;
|
||||
ctx->rdis = push_array(temp.arena, RDI_Parsed *, ctx->rdis_count);
|
||||
ctx->rdis_vaddr_ranges = push_array(temp.arena, Rng1U64, ctx->rdis_count);
|
||||
RDI_Parsed *primary_rdi = &di_rdi_parsed_nil;
|
||||
{
|
||||
U64 primary_idx = 0;
|
||||
U64 idx = 0;
|
||||
for(CTRL_Entity *m = process->first;
|
||||
m != &ctrl_entity_nil && idx < all_modules_count;
|
||||
m = m->next)
|
||||
{
|
||||
if(m->kind != CTRL_EntityKind_Module)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// rjf: unpack
|
||||
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(m, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
|
||||
|
||||
// rjf: fill
|
||||
ctx->rdis[idx] = di_rdi_from_key(di_scope, &dbgi_key, max_U64);
|
||||
ctx->rdis_vaddr_ranges[idx] = m->vaddr_range;
|
||||
|
||||
// rjf: pick primary module
|
||||
if(m == module)
|
||||
{
|
||||
primary_idx = idx;
|
||||
}
|
||||
|
||||
// rjf: inc
|
||||
idx += 1;
|
||||
}
|
||||
if(primary_idx != 0)
|
||||
{
|
||||
Swap(RDI_Parsed *, ctx->rdis[0], ctx->rdis[primary_idx]);
|
||||
Swap(Rng1U64, ctx->rdis_vaddr_ranges[0], ctx->rdis_vaddr_ranges[primary_idx]);
|
||||
}
|
||||
primary_rdi = ctx->rdis[0];
|
||||
}
|
||||
ctx->rdi_primary = rdi_primary;
|
||||
ctx->rdis_count = rdis_count;
|
||||
ctx->rdis = rdis;
|
||||
ctx->rdis_vaddr_ranges = rdis_vaddr_ranges;
|
||||
}
|
||||
|
||||
// rjf: build eval parse context
|
||||
E_ParseCtx parse_ctx = zero_struct;
|
||||
ProfScope("build eval parse context")
|
||||
{
|
||||
E_ParseCtx *ctx = &parse_ctx;
|
||||
ctx->arch = arch;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->rdi_primary = rdi_primary;
|
||||
ctx->rdis_count = rdis_count;
|
||||
ctx->rdis = rdis;
|
||||
ctx->rdis_vaddr_ranges = rdis_vaddr_ranges;
|
||||
ctx->regs_map = ctrl_string2reg_from_arch(ctx->arch);
|
||||
ctx->reg_alias_map = ctrl_string2alias_from_arch(ctx->arch);
|
||||
ctx->locals_map = e_push_locals_map_from_rdi_voff(temp.arena, primary_rdi, thread_rip_voff);
|
||||
ctx->member_map = e_push_member_map_from_rdi_voff(temp.arena, primary_rdi, thread_rip_voff);
|
||||
ctx->macro_map = &e_string2expr_map_nil;
|
||||
// TODO(rjf): ctx->macro_map = ...;
|
||||
ctx->locals_map = e_push_locals_map_from_rdi_voff(temp.arena, ctx->rdi_primary, thread_rip_voff);
|
||||
ctx->member_map = e_push_member_map_from_rdi_voff(temp.arena, ctx->rdi_primary, thread_rip_voff);
|
||||
}
|
||||
|
||||
// rjf: build eval IR context
|
||||
E_IRCtx ir_ctx = zero_struct;
|
||||
{
|
||||
// TODO(rjf): pipe this here from frontend
|
||||
ir_ctx.macro_map = &e_string2expr_map_nil;
|
||||
}
|
||||
|
||||
// rjf: build eval interpretation context
|
||||
E_InterpretCtx interpret_ctx = zero_struct;
|
||||
{
|
||||
E_InterpretCtx *ctx = &interpret_ctx;
|
||||
ctx->arch = arch;
|
||||
ctx->memory_read_user_data = &event->process;
|
||||
ctx->memory_read = ctrl_eval_memory_read;
|
||||
ctx->reg_size = regs_block_size_from_architecture(ctx->arch);
|
||||
@@ -4703,10 +4730,14 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
ctx->module_base = push_array(temp.arena, U64, 1);
|
||||
ctx->module_base[0]= module->vaddr_range.min;
|
||||
ctx->tls_base = push_array(temp.arena, U64, 1);
|
||||
// TODO(rjf): ctx->tls_base[0]= ...;
|
||||
e_select_ctx(ctx);
|
||||
}
|
||||
|
||||
// rjf: equip contexts
|
||||
e_select_type_ctx(&type_ctx);
|
||||
e_select_parse_ctx(&parse_ctx);
|
||||
e_select_ir_ctx(&ir_ctx);
|
||||
e_select_interpret_ctx(&interpret_ctx);
|
||||
|
||||
// rjf: evaluate
|
||||
E_Eval eval = zero_struct;
|
||||
ProfScope("evaluate expression")
|
||||
|
||||
+79
-57
@@ -8603,59 +8603,95 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
//- rjf: choose evaluation context
|
||||
//- rjf: unpack eval-dependent info
|
||||
DF_Entity *process = df_entity_from_handle(df_interact_regs()->process);
|
||||
DF_Entity *thread = df_entity_from_handle(df_interact_regs()->thread);
|
||||
Architecture arch = df_architecture_from_entity(thread);
|
||||
U64 unwind_count = df_interact_regs()->unwind_count;
|
||||
U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count);
|
||||
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
|
||||
DF_EntityList all_modules = df_query_cached_entity_list_with_kind(DF_EntityKind_Module);
|
||||
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
|
||||
U64 tls_root_vaddr = ctrl_query_cached_tls_root_vaddr_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
|
||||
U64 rdis_count = all_modules.count;
|
||||
RDI_Parsed **rdis = push_array(arena, RDI_Parsed *, rdis_count);
|
||||
Rng1U64 *rdis_vaddr_ranges = push_array(arena, Rng1U64, rdis_count);
|
||||
RDI_Parsed *rdi_primary = &di_rdi_parsed_nil;
|
||||
DI_Key primary_dbgi_key = {0};
|
||||
{
|
||||
DF_Entity *process = df_entity_from_handle(df_interact_regs()->process);
|
||||
DF_Entity *thread = df_entity_from_handle(df_interact_regs()->thread);
|
||||
U64 unwind_count = df_interact_regs()->unwind_count;
|
||||
U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count);
|
||||
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
|
||||
DF_EntityList all_modules = df_query_cached_entity_list_with_kind(DF_EntityKind_Module);
|
||||
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
|
||||
U64 tls_root_vaddr = ctrl_query_cached_tls_root_vaddr_from_thread(df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
|
||||
E_Ctx *ctx = push_array(arena, E_Ctx, 1);
|
||||
ctx->arch = df_architecture_from_entity(thread);
|
||||
ctx->ip_vaddr = rip_vaddr;
|
||||
ctx->ip_voff = rip_voff;
|
||||
DI_Key primary_dbgi_key = {0};
|
||||
if(all_modules.count == 0)
|
||||
U64 idx = 0;
|
||||
for(DF_EntityNode *n = all_modules.first; n != 0; n = n->next, idx += 1)
|
||||
{
|
||||
ctx->rdis_count = 1;
|
||||
ctx->rdis = push_array(arena, RDI_Parsed *, 1);
|
||||
ctx->rdis[0] = &di_rdi_parsed_nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->rdis_count = all_modules.count;
|
||||
ctx->rdis = push_array(arena, RDI_Parsed *, ctx->rdis_count);
|
||||
ctx->rdis_vaddr_ranges = push_array(arena, Rng1U64, ctx->rdis_count);
|
||||
DI_Key dbgi_key = df_dbgi_key_from_module(n->entity);
|
||||
rdis[idx] = di_rdi_from_key(df_state->frame_di_scope, &dbgi_key, 0);
|
||||
rdis_vaddr_ranges[idx] = n->entity->vaddr_rng;
|
||||
if(n->entity == module)
|
||||
{
|
||||
U64 primary_idx = 0;
|
||||
U64 idx = 0;
|
||||
for(DF_EntityNode *n = all_modules.first; n != 0; n = n->next, idx += 1)
|
||||
{
|
||||
DI_Key dbgi_key = df_dbgi_key_from_module(n->entity);
|
||||
ctx->rdis[idx] = di_rdi_from_key(df_state->frame_di_scope, &dbgi_key, 0);
|
||||
ctx->rdis_vaddr_ranges[idx] = n->entity->vaddr_rng;
|
||||
if(n->entity == module)
|
||||
{
|
||||
primary_dbgi_key = dbgi_key;
|
||||
primary_idx = idx;
|
||||
}
|
||||
}
|
||||
if(primary_idx != 0)
|
||||
{
|
||||
Swap(RDI_Parsed *, ctx->rdis[0], ctx->rdis[primary_idx]);
|
||||
Swap(Rng1U64, ctx->rdis_vaddr_ranges[0], ctx->rdis_vaddr_ranges[primary_idx]);
|
||||
}
|
||||
primary_dbgi_key = dbgi_key;
|
||||
rdi_primary = rdis[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: build eval type context
|
||||
E_TypeCtx *type_ctx = push_array(arena, E_TypeCtx, 1);
|
||||
{
|
||||
E_TypeCtx *ctx = type_ctx;
|
||||
ctx->arch = arch;
|
||||
ctx->ip_vaddr = rip_vaddr;
|
||||
ctx->ip_voff = rip_voff;
|
||||
ctx->rdi_primary = rdi_primary;
|
||||
ctx->rdis_count = rdis_count;
|
||||
ctx->rdis = rdis;
|
||||
ctx->rdis_vaddr_ranges = rdis_vaddr_ranges;
|
||||
}
|
||||
e_select_type_ctx(type_ctx);
|
||||
|
||||
//- rjf: build eval parse context
|
||||
E_ParseCtx *parse_ctx = push_array(arena, E_ParseCtx, 1);
|
||||
ProfScope("build eval parse context")
|
||||
{
|
||||
E_ParseCtx *ctx = parse_ctx;
|
||||
ctx->arch = arch;
|
||||
ctx->ip_vaddr = rip_vaddr;
|
||||
ctx->ip_voff = rip_voff;
|
||||
ctx->rdi_primary = rdi_primary;
|
||||
ctx->rdis_count = rdis_count;
|
||||
ctx->rdis = rdis;
|
||||
ctx->rdis_vaddr_ranges = rdis_vaddr_ranges;
|
||||
ctx->regs_map = ctrl_string2reg_from_arch(ctx->arch);
|
||||
ctx->reg_alias_map = ctrl_string2alias_from_arch(ctx->arch);
|
||||
ctx->locals_map = df_query_cached_locals_map_from_dbgi_key_voff(&primary_dbgi_key, rip_voff);
|
||||
ctx->member_map = df_query_cached_member_map_from_dbgi_key_voff(&primary_dbgi_key, rip_voff);
|
||||
}
|
||||
e_select_parse_ctx(parse_ctx);
|
||||
|
||||
//- rjf: build eval IR context
|
||||
E_IRCtx *ir_ctx = push_array(arena, E_IRCtx, 1);
|
||||
{
|
||||
E_IRCtx *ctx = ir_ctx;
|
||||
ctx->macro_map = push_array(arena, E_String2ExprMap, 1);
|
||||
ctx->macro_map[0] = e_string2expr_map_make(arena, 512);
|
||||
DF_EntityList watches = df_query_cached_entity_list_with_kind(DF_EntityKind_Watch);
|
||||
for(DF_EntityNode *n = watches.first; n != 0; n = n->next)
|
||||
{
|
||||
DF_Entity *watch = n->entity;
|
||||
String8 expr = watch->name;
|
||||
E_TokenArray tokens = e_token_array_from_text(arena, expr);
|
||||
E_Parse parse = e_parse_expr_from_text_tokens(arena, expr, &tokens);
|
||||
if(parse.msgs.max_kind == E_MsgKind_Null)
|
||||
{
|
||||
e_push_leaf_ident_exprs_from_expr__in_place(arena, ctx->macro_map, parse.expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
e_select_ir_ctx(ir_ctx);
|
||||
|
||||
//- rjf: build eval interpretation context
|
||||
E_InterpretCtx *interpret_ctx = push_array(arena, E_InterpretCtx, 1);
|
||||
{
|
||||
E_InterpretCtx *ctx = interpret_ctx;
|
||||
ctx->arch = arch;
|
||||
ctx->memory_read_user_data = process;
|
||||
ctx->memory_read = df_eval_memory_read;
|
||||
ctx->reg_data = ctrl_query_cached_reg_block_from_thread(arena, df_state->ctrl_entity_store, thread->ctrl_machine_id, thread->ctrl_handle);
|
||||
@@ -8664,22 +8700,8 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
||||
ctx->module_base[0]= module->vaddr_rng.min;
|
||||
ctx->tls_base = push_array(arena, U64, 1);
|
||||
ctx->tls_base[0] = df_query_cached_tls_base_vaddr_from_process_root_rip(process, tls_root_vaddr, rip_vaddr);
|
||||
e_select_ctx(ctx);
|
||||
{
|
||||
DF_EntityList watches = df_query_cached_entity_list_with_kind(DF_EntityKind_Watch);
|
||||
for(DF_EntityNode *n = watches.first; n != 0; n = n->next)
|
||||
{
|
||||
DF_Entity *watch = n->entity;
|
||||
String8 expr = watch->name;
|
||||
E_TokenArray tokens = e_token_array_from_text(arena, expr);
|
||||
E_Parse parse = e_parse_expr_from_text_tokens(arena, expr, &tokens);
|
||||
if(parse.msgs.max_kind == E_MsgKind_Null)
|
||||
{
|
||||
e_push_leaf_ident_exprs_from_expr__in_place(arena, ctx->macro_map, parse.expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
e_select_interpret_ctx(interpret_ctx);
|
||||
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
+124
-101
@@ -507,8 +507,8 @@ df_cmd_params_from_window(DF_Window *window)
|
||||
p.window = df_handle_from_window(window);
|
||||
p.panel = df_handle_from_panel(window->focused_panel);
|
||||
p.view = df_handle_from_view(df_selected_tab_from_panel(window->focused_panel));
|
||||
p.prefer_dasm = df_prefer_dasm_from_window(window);
|
||||
p.entity = df_interact_regs()->thread;
|
||||
p.prefer_dasm = df_prefer_dasm_from_window(window);
|
||||
p.entity = df_interact_regs()->thread;
|
||||
p.unwind_index = df_interact_regs()->unwind_count;
|
||||
p.inline_depth = df_interact_regs()->inline_depth;
|
||||
return p;
|
||||
@@ -529,7 +529,7 @@ df_cmd_params_from_panel(DF_Window *window, DF_Panel *panel)
|
||||
p.panel = df_handle_from_panel(panel);
|
||||
p.view = df_handle_from_view(df_selected_tab_from_panel(panel));
|
||||
p.prefer_dasm = df_prefer_dasm_from_window(window);
|
||||
p.entity = df_interact_regs()->thread;
|
||||
p.entity = df_interact_regs()->thread;
|
||||
p.unwind_index = df_interact_regs()->unwind_count;
|
||||
p.inline_depth = df_interact_regs()->inline_depth;
|
||||
return p;
|
||||
@@ -550,7 +550,7 @@ df_cmd_params_from_view(DF_Window *window, DF_Panel *panel, DF_View *view)
|
||||
p.panel = df_handle_from_panel(panel);
|
||||
p.view = df_handle_from_view(view);
|
||||
p.prefer_dasm = df_prefer_dasm_from_window(window);
|
||||
p.entity = df_interact_regs()->thread;
|
||||
p.entity = df_interact_regs()->thread;
|
||||
p.unwind_index = df_interact_regs()->unwind_count;
|
||||
p.inline_depth = df_interact_regs()->inline_depth;
|
||||
return p;
|
||||
@@ -2596,8 +2596,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualOff);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth);
|
||||
df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
|
||||
}
|
||||
|
||||
@@ -2613,7 +2613,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualOff);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_UnwindIndex);
|
||||
df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineDepth);
|
||||
df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
|
||||
}
|
||||
@@ -2627,7 +2627,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
|
||||
di_scope_close(scope);
|
||||
}break;
|
||||
case DF_CoreCmdKind_FindSelectedThread:
|
||||
{
|
||||
{
|
||||
DF_Entity *selected_thread = df_entity_from_handle(df_base_interact_regs()->thread);
|
||||
DF_CmdParams params = df_cmd_params_from_window(ws);
|
||||
params.entity = df_handle_from_entity(selected_thread);
|
||||
@@ -4295,37 +4295,37 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
|
||||
DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process);
|
||||
CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(entity);
|
||||
DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind);
|
||||
String8List lines = {0};
|
||||
for(U64 frame_idx = 0; frame_idx < rich_unwind.frames.concrete_frame_count; frame_idx += 1)
|
||||
{
|
||||
DF_UnwindFrame *concrete_frame = &rich_unwind.frames.v[frame_idx];
|
||||
String8List lines = {0};
|
||||
for(U64 frame_idx = 0; frame_idx < rich_unwind.frames.concrete_frame_count; frame_idx += 1)
|
||||
{
|
||||
DF_UnwindFrame *concrete_frame = &rich_unwind.frames.v[frame_idx];
|
||||
U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, concrete_frame->regs);
|
||||
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
|
||||
RDI_Parsed *rdi = concrete_frame->rdi;
|
||||
RDI_Procedure *procedure = concrete_frame->procedure;
|
||||
for(DF_UnwindInlineFrame *inline_frame = concrete_frame->last_inline_frame;
|
||||
inline_frame != 0;
|
||||
inline_frame = inline_frame->prev)
|
||||
{
|
||||
RDI_InlineSite *inline_site = inline_frame->inline_site;
|
||||
RDI_Parsed *rdi = concrete_frame->rdi;
|
||||
RDI_Procedure *procedure = concrete_frame->procedure;
|
||||
for(DF_UnwindInlineFrame *inline_frame = concrete_frame->last_inline_frame;
|
||||
inline_frame != 0;
|
||||
inline_frame = inline_frame->prev)
|
||||
{
|
||||
RDI_InlineSite *inline_site = inline_frame->inline_site;
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size);
|
||||
str8_list_pushf(scratch.arena, &lines, "0x%I64x: [inlined] \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name);
|
||||
}
|
||||
if(procedure != 0)
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &lines, "0x%I64x: [inlined] \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name);
|
||||
}
|
||||
if(procedure != 0)
|
||||
{
|
||||
String8 name = {0};
|
||||
name.str = rdi_name_from_procedure(rdi, procedure, &name.size);
|
||||
str8_list_pushf(scratch.arena, &lines, "0x%I64x: \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name);
|
||||
}
|
||||
else if(!df_entity_is_nil(module))
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in %S]", rip_vaddr, module->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in ???]", rip_vaddr);
|
||||
}
|
||||
str8_list_pushf(scratch.arena, &lines, "0x%I64x: \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name);
|
||||
}
|
||||
else if(!df_entity_is_nil(module))
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in %S]", rip_vaddr, module->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in ???]", rip_vaddr);
|
||||
}
|
||||
}
|
||||
StringJoin join = {0};
|
||||
join.sep = join.post = str8_lit("\n");
|
||||
@@ -4672,6 +4672,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
|
||||
if(ws->autocomp_lister_params.flags & DF_AutoCompListerFlag_Locals)
|
||||
{
|
||||
E_String2NumMap *locals_map = df_query_cached_locals_map_from_dbgi_key_voff(&dbgi_key, thread_rip_voff);
|
||||
E_String2NumMap *member_map = df_query_cached_member_map_from_dbgi_key_voff(&dbgi_key, thread_rip_voff);
|
||||
for(E_String2NumMapNode *n = locals_map->first; n != 0; n = n->order_next)
|
||||
{
|
||||
DF_AutoCompListerItem item = {0};
|
||||
@@ -4685,6 +4686,19 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
|
||||
df_autocomp_lister_item_chunk_list_push(scratch.arena, &item_list, 256, &item);
|
||||
}
|
||||
}
|
||||
for(E_String2NumMapNode *n = member_map->first; n != 0; n = n->order_next)
|
||||
{
|
||||
DF_AutoCompListerItem item = {0};
|
||||
{
|
||||
item.string = n->string;
|
||||
item.kind_string = str8_lit("Local (Member)");
|
||||
item.matches = fuzzy_match_find(scratch.arena, query, n->string);
|
||||
}
|
||||
if(query.size == 0 || item.matches.count != 0)
|
||||
{
|
||||
df_autocomp_lister_item_chunk_list_push(scratch.arena, &item_list, 256, &item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: gather registers
|
||||
@@ -4750,6 +4764,12 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: gather members
|
||||
if(ws->autocomp_lister_params.flags & DF_AutoCompListerFlag_Members)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//- rjf: gather languages
|
||||
if(ws->autocomp_lister_params.flags & DF_AutoCompListerFlag_Languages)
|
||||
{
|
||||
@@ -8358,12 +8378,12 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: increment per-window frame counter
|
||||
//
|
||||
ws->frames_alive += 1;
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: increment per-window frame counter
|
||||
//
|
||||
ws->frames_alive += 1;
|
||||
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
@@ -8514,7 +8534,10 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
|
||||
}
|
||||
|
||||
// rjf: special-case: strings
|
||||
if(!has_array && direct_type_is_string && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) && eval.mode == E_Mode_Addr)
|
||||
if(!has_array &&
|
||||
direct_type_is_string &&
|
||||
(flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) &&
|
||||
eval.mode == E_Mode_Addr)
|
||||
{
|
||||
U64 string_memory_addr = value_eval.value.u64;
|
||||
U64 element_size = e_type_byte_size_from_key(direct_type_key);
|
||||
@@ -8547,7 +8570,7 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
|
||||
// rjf: descend to pointed-at thing
|
||||
else if(direct_type_has_content && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules))
|
||||
{
|
||||
if(depth < 5)
|
||||
if(depth < 4)
|
||||
{
|
||||
E_Eval pted_eval = zero_struct;
|
||||
pted_eval.type_key = direct_type_key;
|
||||
@@ -8636,8 +8659,8 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
|
||||
{
|
||||
E_Eval element_eval = zero_struct;
|
||||
element_eval.type_key = direct_type_key;
|
||||
element_eval.mode = eval.mode;
|
||||
element_eval.value = eval.value;
|
||||
element_eval.mode = eval.mode;
|
||||
element_eval.value = eval.value;
|
||||
element_eval.value.u64 += direct_type_byte_size*idx;
|
||||
String8List element_strs = df_single_line_eval_value_strings_from_eval(arena, flags, default_radix, font, font_size, max_size-space_taken, depth+1, element_eval, opt_member, cfg_table);
|
||||
space_taken += f_dim_from_tag_size_string_list(font, font_size, 0, 0, element_strs).x;
|
||||
@@ -8695,8 +8718,8 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
|
||||
E_Eval member_eval = zero_struct;
|
||||
member_eval.type_key = mem->type_key;
|
||||
member_eval.mode = eval.mode;
|
||||
member_eval.value = eval.value;
|
||||
member_eval.value.u64 += mem->off;
|
||||
member_eval.value = eval.value;
|
||||
member_eval.value.u64 += mem->off;
|
||||
String8List member_strs = df_single_line_eval_value_strings_from_eval(arena, flags, default_radix, font, font_size, max_size-space_taken, depth+1, member_eval, opt_member, cfg_table);
|
||||
space_taken += f_dim_from_tag_size_string_list(font, font_size, 0, 0, member_strs).x;
|
||||
str8_list_concat_in_place(&list, &member_strs);
|
||||
@@ -8902,9 +8925,9 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DI_Scope *scope,
|
||||
E_Eval member_eval = zero_struct;
|
||||
{
|
||||
member_eval.type_key = member->type_key;
|
||||
member_eval.mode = block->eval.mode;
|
||||
member_eval.value = block->eval.value;
|
||||
member_eval.value.u64 += member->off;
|
||||
member_eval.mode = block->eval.mode;
|
||||
member_eval.value = block->eval.value;
|
||||
member_eval.value.u64 += member->off;
|
||||
}
|
||||
|
||||
// rjf: get view rules
|
||||
@@ -9005,9 +9028,9 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DI_Scope *scope,
|
||||
E_Eval elem_eval = zero_struct;
|
||||
{
|
||||
elem_eval.type_key = direct_type_key;
|
||||
elem_eval.mode = block->eval.mode;
|
||||
elem_eval.value = block->eval.value;
|
||||
elem_eval.value.u64 += idx*direct_type_key_byte_size;
|
||||
elem_eval.mode = block->eval.mode;
|
||||
elem_eval.value = block->eval.value;
|
||||
elem_eval.value.u64 += idx*direct_type_key_byte_size;
|
||||
}
|
||||
|
||||
// rjf: get view rules
|
||||
@@ -9060,8 +9083,8 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DI_Scope *scope,
|
||||
E_Eval link_eval = zero_struct;
|
||||
{
|
||||
link_eval.type_key = block->eval.type_key;
|
||||
link_eval.mode = link_base->mode;
|
||||
link_eval.value.u64= link_base->offset;
|
||||
link_eval.mode = link_base->mode;
|
||||
link_eval.value.u64= link_base->offset;
|
||||
}
|
||||
|
||||
// rjf: get view rules
|
||||
@@ -9111,31 +9134,31 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DI_Scope *scope,
|
||||
}break;
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: all types -> produce rows for visible range
|
||||
//- rjf: all elements of a debug info table -> produce rows for visible range
|
||||
//
|
||||
case DF_EvalVizBlockKind_DebugInfoTable:
|
||||
for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1)
|
||||
{
|
||||
FZY_Item *item = &block->fzy_backing_items.v[idx];
|
||||
|
||||
{
|
||||
FZY_Item *item = &block->fzy_backing_items.v[idx];
|
||||
|
||||
// rjf: determine dbgi/rdi to which this item belongs
|
||||
RDI_Parsed *rdi = &di_rdi_parsed_nil;
|
||||
{
|
||||
U64 base_idx = 0;
|
||||
for(U64 rdi_idx = 0; rdi_idx < e_state->ctx->rdis_count; rdi_idx += 1)
|
||||
for(U64 rdi_idx = 0; rdi_idx < e_parse_ctx->rdis_count; rdi_idx += 1)
|
||||
{
|
||||
U64 all_items_count = 0;
|
||||
rdi_section_raw_table_from_kind(e_state->ctx->rdis[rdi_idx], block->fzy_target, &all_items_count);
|
||||
rdi_section_raw_table_from_kind(e_parse_ctx->rdis[rdi_idx], block->fzy_target, &all_items_count);
|
||||
if(base_idx <= item->idx && item->idx < base_idx + all_items_count)
|
||||
{
|
||||
rdi = e_state->ctx->rdis[rdi_idx];
|
||||
rdi = e_parse_ctx->rdis[rdi_idx];
|
||||
break;
|
||||
}
|
||||
base_idx += all_items_count;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: unpack info about this row
|
||||
}
|
||||
|
||||
// rjf: unpack info about this row
|
||||
String8 name = fzy_item_string_from_rdi_target_element_idx(rdi, block->fzy_target, block->fzy_backing_items.v[idx].idx);
|
||||
|
||||
// rjf: get keys for this row
|
||||
@@ -10586,23 +10609,23 @@ df_entity_tooltips(DF_Window *ws, DF_Entity *entity)
|
||||
DI_Scope *di_scope = di_scope_open();
|
||||
DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process);
|
||||
CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(entity);
|
||||
DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind);
|
||||
for(U64 idx = 0; idx < rich_unwind.frames.concrete_frame_count; idx += 1)
|
||||
{
|
||||
DF_UnwindFrame *f = &rich_unwind.frames.v[idx];
|
||||
DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind);
|
||||
for(U64 idx = 0; idx < rich_unwind.frames.concrete_frame_count; idx += 1)
|
||||
{
|
||||
DF_UnwindFrame *f = &rich_unwind.frames.v[idx];
|
||||
RDI_Parsed *rdi = f->rdi;
|
||||
RDI_Procedure *procedure = f->procedure;
|
||||
RDI_Procedure *procedure = f->procedure;
|
||||
U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, f->regs);
|
||||
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
|
||||
String8 module_name = df_entity_is_nil(module) ? str8_lit("???") : str8_skip_last_slash(module->name);
|
||||
|
||||
// rjf: inline frames
|
||||
for(DF_UnwindInlineFrame *fin = f->last_inline_frame; fin != 0; fin = fin->prev)
|
||||
UI_PrefWidth(ui_children_sum(1)) UI_Row
|
||||
{
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, fin->inline_site->name_string_idx, &name.size);
|
||||
DF_Font(ws, DF_FontSlot_Code) UI_PrefWidth(ui_em(18.f, 1.f)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_labelf("0x%I64x", rip_vaddr);
|
||||
String8 module_name = df_entity_is_nil(module) ? str8_lit("???") : str8_skip_last_slash(module->name);
|
||||
|
||||
// rjf: inline frames
|
||||
for(DF_UnwindInlineFrame *fin = f->last_inline_frame; fin != 0; fin = fin->prev)
|
||||
UI_PrefWidth(ui_children_sum(1)) UI_Row
|
||||
{
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, fin->inline_site->name_string_idx, &name.size);
|
||||
DF_Font(ws, DF_FontSlot_Code) UI_PrefWidth(ui_em(18.f, 1.f)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_labelf("0x%I64x", rip_vaddr);
|
||||
DF_Font(ws, DF_FontSlot_Code) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_text_dim(10, 1)) ui_label(str8_lit("[inlined]"));
|
||||
if(name.size != 0)
|
||||
{
|
||||
@@ -10614,14 +10637,14 @@ df_entity_tooltips(DF_Window *ws, DF_Entity *entity)
|
||||
else
|
||||
{
|
||||
DF_Font(ws, DF_FontSlot_Code) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_text_dim(10, 1)) ui_labelf("[??? in %S]", module_name);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: concrete frame
|
||||
UI_PrefWidth(ui_children_sum(1)) UI_Row
|
||||
{
|
||||
String8 name = {0};
|
||||
name.str = rdi_name_from_procedure(rdi, procedure, &name.size);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: concrete frame
|
||||
UI_PrefWidth(ui_children_sum(1)) UI_Row
|
||||
{
|
||||
String8 name = {0};
|
||||
name.str = rdi_name_from_procedure(rdi, procedure, &name.size);
|
||||
DF_Font(ws, DF_FontSlot_Code) UI_PrefWidth(ui_em(18.f, 1.f)) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_labelf("0x%I64x", rip_vaddr);
|
||||
if(name.size != 0)
|
||||
{
|
||||
@@ -10633,8 +10656,8 @@ df_entity_tooltips(DF_Window *ws, DF_Entity *entity)
|
||||
else
|
||||
{
|
||||
DF_Font(ws, DF_FontSlot_Code) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) UI_PrefWidth(ui_text_dim(10, 1)) ui_labelf("[??? in %S]", module_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
di_scope_close(di_scope);
|
||||
}break;
|
||||
@@ -12201,13 +12224,13 @@ df_code_slice(DF_Window *ws, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *m
|
||||
//
|
||||
UI_Parent(text_container_box) ProfScope("build line text") UI_Focus(UI_FocusKind_Off)
|
||||
{
|
||||
DF_RichHoverInfo rich_hover = df_get_rich_hover_info();
|
||||
Rng1U64 rich_hover_voff_range = rich_hover.voff_range;
|
||||
if(rich_hover_voff_range.min == 0 && rich_hover_voff_range.max == 0)
|
||||
{
|
||||
DF_Entity *module = df_entity_from_handle(rich_hover.module);
|
||||
rich_hover_voff_range = df_voff_range_from_vaddr_range(module, rich_hover.vaddr_range);
|
||||
}
|
||||
DF_RichHoverInfo rich_hover = df_get_rich_hover_info();
|
||||
Rng1U64 rich_hover_voff_range = rich_hover.voff_range;
|
||||
if(rich_hover_voff_range.min == 0 && rich_hover_voff_range.max == 0)
|
||||
{
|
||||
DF_Entity *module = df_entity_from_handle(rich_hover.module);
|
||||
rich_hover_voff_range = df_voff_range_from_vaddr_range(module, rich_hover.vaddr_range);
|
||||
}
|
||||
ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f));
|
||||
UI_WidthFill
|
||||
UI_Column
|
||||
@@ -12306,7 +12329,7 @@ df_code_slice(DF_Window *ws, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *m
|
||||
}
|
||||
if(!mapped_special && token->kind == TXT_TokenKind_Identifier)
|
||||
{
|
||||
U64 local_num = e_num_from_string(e_state->ctx->locals_map, token_string);
|
||||
U64 local_num = e_num_from_string(e_parse_ctx->locals_map, token_string);
|
||||
if(local_num != 0)
|
||||
{
|
||||
mapped_special = 1;
|
||||
@@ -12318,7 +12341,7 @@ df_code_slice(DF_Window *ws, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *m
|
||||
}
|
||||
if(!mapped_special)
|
||||
{
|
||||
U64 reg_num = e_num_from_string(e_state->ctx->regs_map, token_string);
|
||||
U64 reg_num = e_num_from_string(e_parse_ctx->regs_map, token_string);
|
||||
if(reg_num != 0)
|
||||
{
|
||||
mapped_special = 1;
|
||||
@@ -12328,7 +12351,7 @@ df_code_slice(DF_Window *ws, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *m
|
||||
}
|
||||
if(!mapped_special)
|
||||
{
|
||||
U64 alias_num = e_num_from_string(e_state->ctx->reg_alias_map, token_string);
|
||||
U64 alias_num = e_num_from_string(e_parse_ctx->reg_alias_map, token_string);
|
||||
if(alias_num != 0)
|
||||
{
|
||||
mapped_special = 1;
|
||||
@@ -12477,12 +12500,12 @@ df_code_slice(DF_Window *ws, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *m
|
||||
{
|
||||
B32 matches = 0;
|
||||
S64 line_info_line_num = 0;
|
||||
DF_LineList *lines = ¶ms->line_infos[line_idx];
|
||||
DF_LineList *lines = ¶ms->line_infos[line_idx];
|
||||
for(DF_LineNode *n = lines->first; n != 0; n = n->next)
|
||||
{
|
||||
{
|
||||
if((n->v.pt.line == line_num || df_entity_is_nil(df_entity_from_handle(df_interact_regs()->file))) &&
|
||||
((di_key_match(&n->v.dbgi_key, &rich_hover.dbgi_key) &&
|
||||
n->v.voff_range.min <= rich_hover_voff_range.min && rich_hover_voff_range.min < n->v.voff_range.max) ||
|
||||
n->v.voff_range.min <= rich_hover_voff_range.min && rich_hover_voff_range.min < n->v.voff_range.max) ||
|
||||
(params->line_vaddrs[line_idx] == rich_hover.vaddr_range.min && rich_hover.vaddr_range.min != 0)))
|
||||
{
|
||||
matches = 1;
|
||||
@@ -13544,7 +13567,7 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds)
|
||||
|
||||
//- rjf: exiting
|
||||
case DF_CoreCmdKind_Exit:
|
||||
{
|
||||
{
|
||||
// rjf: save
|
||||
{
|
||||
DF_CmdParams params = df_cmd_params_zero();
|
||||
|
||||
+10
-10
@@ -1314,7 +1314,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DI_Scope *di_scope, F
|
||||
//
|
||||
case DF_WatchViewFillKind_Locals:
|
||||
{
|
||||
E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_state->ctx->locals_map);
|
||||
E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_parse_ctx->locals_map);
|
||||
e_string2num_map_node_array_sort__in_place(&nodes);
|
||||
for(U64 idx = 0; idx < nodes.count; idx += 1)
|
||||
{
|
||||
@@ -1671,7 +1671,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
|
||||
//
|
||||
case DF_WatchViewFillKind_Locals:
|
||||
{
|
||||
E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_state->ctx->locals_map);
|
||||
E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_parse_ctx->locals_map);
|
||||
e_string2num_map_node_array_sort__in_place(&nodes);
|
||||
for(U64 idx = 0; idx < nodes.count; idx += 1)
|
||||
{
|
||||
@@ -1806,14 +1806,14 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
|
||||
{
|
||||
for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1)
|
||||
{
|
||||
U64 procedures_count = 0;
|
||||
rdi_section_raw_table_from_kind(rdis[rdi_idx], RDI_SectionKind_Procedures, &procedures_count);
|
||||
if(base_idx <= item->idx && item->idx < base_idx + procedures_count)
|
||||
U64 elements_count = 0;
|
||||
rdi_section_raw_table_from_kind(rdis[rdi_idx], fzy_target, &elements_count);
|
||||
if(base_idx <= item->idx && item->idx < base_idx + elements_count)
|
||||
{
|
||||
rdi = rdis[rdi_idx];
|
||||
break;
|
||||
}
|
||||
base_idx += procedures_count;
|
||||
base_idx += elements_count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4318,7 +4318,7 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
|
||||
U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
|
||||
String8 name = str8(name_base, name_size);
|
||||
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx);
|
||||
E_TypeKey type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, e_idx_from_rdi(rdi));
|
||||
E_TypeKey type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, e_parse_ctx_idx_from_rdi(rdi));
|
||||
|
||||
//- rjf: build item button
|
||||
ui_set_next_hover_cursor(OS_Cursor_HandPoint);
|
||||
@@ -5915,13 +5915,13 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack)
|
||||
{
|
||||
symbol_name.str = rdi_name_from_procedure(row->rdi, row->procedure, &symbol_name.size);
|
||||
RDI_TypeNode *type = rdi_element_from_name_idx(row->rdi, TypeNodes, row->procedure->type_idx);
|
||||
symbol_type_string = e_type_string_from_key(scratch.arena, e_type_key_ext(e_type_kind_from_rdi(type->kind), row->procedure->type_idx, e_idx_from_rdi(row->rdi)));
|
||||
symbol_type_string = e_type_string_from_key(scratch.arena, e_type_key_ext(e_type_kind_from_rdi(type->kind), row->procedure->type_idx, e_parse_ctx_idx_from_rdi(row->rdi)));
|
||||
}
|
||||
if(row->inline_site != 0)
|
||||
{
|
||||
symbol_name.str = rdi_string_from_idx(row->rdi, row->inline_site->name_string_idx, &symbol_name.size);
|
||||
RDI_TypeNode *type = rdi_element_from_name_idx(row->rdi, TypeNodes, row->inline_site->type_idx);
|
||||
symbol_type_string = e_type_string_from_key(scratch.arena, e_type_key_ext(e_type_kind_from_rdi(type->kind), row->inline_site->type_idx, e_idx_from_rdi(row->rdi)));
|
||||
symbol_type_string = e_type_string_from_key(scratch.arena, e_type_key_ext(e_type_kind_from_rdi(type->kind), row->inline_site->type_idx, e_parse_ctx_idx_from_rdi(row->rdi)));
|
||||
}
|
||||
|
||||
// rjf: build row
|
||||
@@ -7632,7 +7632,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
|
||||
df_rgba_from_theme_color(DF_ThemeColor_Thread7),
|
||||
};
|
||||
U64 thread_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, df_interact_regs()->unwind_count);
|
||||
for(E_String2NumMapNode *n = e_ctx()->locals_map->first; n != 0; n = n->order_next)
|
||||
for(E_String2NumMapNode *n = e_parse_ctx->locals_map->first; n != 0; n = n->order_next)
|
||||
{
|
||||
String8 local_name = n->string;
|
||||
E_Eval local_eval = e_eval_from_string(scratch.arena, local_name);
|
||||
|
||||
-5603
File diff suppressed because it is too large
Load Diff
-661
@@ -1,661 +0,0 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef EVAL_H
|
||||
#define EVAL_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Generated Code
|
||||
|
||||
#include "generated/eval.meta.h"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Messages
|
||||
|
||||
typedef enum E_MsgKind
|
||||
{
|
||||
E_MsgKind_Null,
|
||||
E_MsgKind_MalformedInput,
|
||||
E_MsgKind_MissingInfo,
|
||||
E_MsgKind_ResolutionFailure,
|
||||
E_MsgKind_InterpretationError,
|
||||
E_MsgKind_COUNT
|
||||
}
|
||||
E_MsgKind;
|
||||
|
||||
typedef struct E_Msg E_Msg;
|
||||
struct E_Msg
|
||||
{
|
||||
E_Msg *next;
|
||||
E_MsgKind kind;
|
||||
void *location;
|
||||
String8 text;
|
||||
};
|
||||
|
||||
typedef struct E_MsgList E_MsgList;
|
||||
struct E_MsgList
|
||||
{
|
||||
E_Msg *first;
|
||||
E_Msg *last;
|
||||
E_MsgKind max_kind;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Token Types
|
||||
|
||||
typedef enum E_TokenKind
|
||||
{
|
||||
E_TokenKind_Null,
|
||||
E_TokenKind_Identifier,
|
||||
E_TokenKind_Numeric,
|
||||
E_TokenKind_StringLiteral,
|
||||
E_TokenKind_CharLiteral,
|
||||
E_TokenKind_Symbol,
|
||||
E_TokenKind_COUNT
|
||||
}
|
||||
E_TokenKind;
|
||||
|
||||
typedef struct E_Token E_Token;
|
||||
struct E_Token
|
||||
{
|
||||
E_TokenKind kind;
|
||||
Rng1U64 range;
|
||||
};
|
||||
|
||||
typedef struct E_TokenChunkNode E_TokenChunkNode;
|
||||
struct E_TokenChunkNode
|
||||
{
|
||||
E_TokenChunkNode *next;
|
||||
E_Token *v;
|
||||
U64 count;
|
||||
U64 cap;
|
||||
};
|
||||
|
||||
typedef struct E_TokenChunkList E_TokenChunkList;
|
||||
struct E_TokenChunkList
|
||||
{
|
||||
E_TokenChunkNode *first;
|
||||
E_TokenChunkNode *last;
|
||||
U64 node_count;
|
||||
U64 total_count;
|
||||
};
|
||||
|
||||
typedef struct E_TokenArray E_TokenArray;
|
||||
struct E_TokenArray
|
||||
{
|
||||
E_Token *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Implicit Type Graph Key Types
|
||||
|
||||
typedef enum E_TypeKeyKind
|
||||
{
|
||||
E_TypeKeyKind_Null,
|
||||
E_TypeKeyKind_Basic,
|
||||
E_TypeKeyKind_Ext,
|
||||
E_TypeKeyKind_Cons,
|
||||
E_TypeKeyKind_Reg,
|
||||
E_TypeKeyKind_RegAlias,
|
||||
}
|
||||
E_TypeKeyKind;
|
||||
|
||||
typedef struct E_TypeKey E_TypeKey;
|
||||
struct E_TypeKey
|
||||
{
|
||||
E_TypeKeyKind kind;
|
||||
U32 u32[3];
|
||||
// [0] -> E_TypeKind (Basic, Cons, Ext); Architecture (Reg, RegAlias)
|
||||
// [1] -> Type Index In RDI (Cons, Ext); Code (Reg, RegAlias)
|
||||
// [2] -> RDI Index (Cons, Ext)
|
||||
};
|
||||
|
||||
typedef struct E_TypeKeyNode E_TypeKeyNode;
|
||||
struct E_TypeKeyNode
|
||||
{
|
||||
E_TypeKeyNode *next;
|
||||
E_TypeKey v;
|
||||
};
|
||||
|
||||
typedef struct E_TypeKeyList E_TypeKeyList;
|
||||
struct E_TypeKeyList
|
||||
{
|
||||
E_TypeKeyNode *first;
|
||||
E_TypeKeyNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Full Extracted Type Information Types
|
||||
|
||||
typedef enum E_MemberKind
|
||||
{
|
||||
E_MemberKind_Null,
|
||||
E_MemberKind_DataField,
|
||||
E_MemberKind_StaticData,
|
||||
E_MemberKind_Method,
|
||||
E_MemberKind_StaticMethod,
|
||||
E_MemberKind_VirtualMethod,
|
||||
E_MemberKind_VTablePtr,
|
||||
E_MemberKind_Base,
|
||||
E_MemberKind_VirtualBase,
|
||||
E_MemberKind_NestedType,
|
||||
E_MemberKind_Padding,
|
||||
E_MemberKind_COUNT
|
||||
}
|
||||
E_MemberKind;
|
||||
|
||||
typedef U32 E_TypeFlags;
|
||||
enum
|
||||
{
|
||||
E_TypeFlag_Const = (1<<0),
|
||||
E_TypeFlag_Volatile = (1<<1),
|
||||
};
|
||||
|
||||
typedef struct E_Member E_Member;
|
||||
struct E_Member
|
||||
{
|
||||
E_MemberKind kind;
|
||||
E_TypeKey type_key;
|
||||
String8 name;
|
||||
U64 off;
|
||||
E_TypeKeyList inheritance_key_chain;
|
||||
};
|
||||
|
||||
typedef struct E_MemberNode E_MemberNode;
|
||||
struct E_MemberNode
|
||||
{
|
||||
E_MemberNode *next;
|
||||
E_Member v;
|
||||
};
|
||||
|
||||
typedef struct E_MemberList E_MemberList;
|
||||
struct E_MemberList
|
||||
{
|
||||
E_MemberNode *first;
|
||||
E_MemberNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct E_MemberArray E_MemberArray;
|
||||
struct E_MemberArray
|
||||
{
|
||||
E_Member *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct E_EnumVal E_EnumVal;
|
||||
struct E_EnumVal
|
||||
{
|
||||
String8 name;
|
||||
U64 val;
|
||||
};
|
||||
|
||||
typedef struct E_EnumValArray E_EnumValArray;
|
||||
struct E_EnumValArray
|
||||
{
|
||||
E_EnumVal *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct E_Type E_Type;
|
||||
struct E_Type
|
||||
{
|
||||
E_TypeKind kind;
|
||||
E_TypeFlags flags;
|
||||
String8 name;
|
||||
U64 byte_size;
|
||||
U64 count;
|
||||
U32 off;
|
||||
E_TypeKey direct_type_key;
|
||||
E_TypeKey owner_type_key;
|
||||
E_TypeKey *param_type_keys;
|
||||
E_Member *members;
|
||||
E_EnumVal *enum_vals;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression Tree Types
|
||||
|
||||
typedef enum E_Mode
|
||||
{
|
||||
E_Mode_Null,
|
||||
E_Mode_Value,
|
||||
E_Mode_Addr,
|
||||
E_Mode_Reg,
|
||||
}
|
||||
E_Mode;
|
||||
|
||||
typedef struct E_Expr E_Expr;
|
||||
struct E_Expr
|
||||
{
|
||||
E_Expr *first;
|
||||
E_Expr *last;
|
||||
E_Expr *next;
|
||||
void *location;
|
||||
E_ExprKind kind;
|
||||
E_Mode mode;
|
||||
E_TypeKey type_key;
|
||||
U32 u32;
|
||||
F32 f32;
|
||||
U64 u64;
|
||||
F64 f64;
|
||||
String8 string;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR Tree Types
|
||||
|
||||
typedef struct E_IRNode E_IRNode;
|
||||
struct E_IRNode
|
||||
{
|
||||
E_IRNode *first;
|
||||
E_IRNode *last;
|
||||
E_IRNode *next;
|
||||
RDI_EvalOp op;
|
||||
String8 bytecode;
|
||||
U64 u64;
|
||||
};
|
||||
|
||||
typedef struct E_IRTreeAndType E_IRTreeAndType;
|
||||
struct E_IRTreeAndType
|
||||
{
|
||||
E_IRNode *root;
|
||||
E_TypeKey type_key;
|
||||
E_Mode mode;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bytecode Operation Types
|
||||
|
||||
enum
|
||||
{
|
||||
E_IRExtKind_Bytecode = RDI_EvalOp_COUNT,
|
||||
E_IRExtKind_COUNT
|
||||
};
|
||||
|
||||
typedef struct E_Op E_Op;
|
||||
struct E_Op
|
||||
{
|
||||
E_Op *next;
|
||||
RDI_EvalOp opcode;
|
||||
union
|
||||
{
|
||||
U64 p;
|
||||
String8 bytecode;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct E_OpList E_OpList;
|
||||
struct E_OpList
|
||||
{
|
||||
E_Op *first;
|
||||
E_Op *last;
|
||||
U64 op_count;
|
||||
U64 encoded_size;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Map Types
|
||||
|
||||
//- rjf: string -> num
|
||||
|
||||
typedef struct E_String2NumMapNode E_String2NumMapNode;
|
||||
struct E_String2NumMapNode
|
||||
{
|
||||
E_String2NumMapNode *order_next;
|
||||
E_String2NumMapNode *hash_next;
|
||||
String8 string;
|
||||
U64 num;
|
||||
};
|
||||
|
||||
typedef struct E_String2NumMapNodeArray E_String2NumMapNodeArray;
|
||||
struct E_String2NumMapNodeArray
|
||||
{
|
||||
E_String2NumMapNode **v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct E_String2NumMapSlot E_String2NumMapSlot;
|
||||
struct E_String2NumMapSlot
|
||||
{
|
||||
E_String2NumMapNode *first;
|
||||
E_String2NumMapNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_String2NumMap E_String2NumMap;
|
||||
struct E_String2NumMap
|
||||
{
|
||||
U64 slots_count;
|
||||
U64 node_count;
|
||||
E_String2NumMapSlot *slots;
|
||||
E_String2NumMapNode *first;
|
||||
E_String2NumMapNode *last;
|
||||
};
|
||||
|
||||
//- rjf: string -> expr
|
||||
|
||||
typedef struct E_String2ExprMapNode E_String2ExprMapNode;
|
||||
struct E_String2ExprMapNode
|
||||
{
|
||||
E_String2ExprMapNode *hash_next;
|
||||
String8 string;
|
||||
E_Expr *expr;
|
||||
U64 poison_count;
|
||||
};
|
||||
|
||||
typedef struct E_String2ExprMapSlot E_String2ExprMapSlot;
|
||||
struct E_String2ExprMapSlot
|
||||
{
|
||||
E_String2ExprMapNode *first;
|
||||
E_String2ExprMapNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_String2ExprMap E_String2ExprMap;
|
||||
struct E_String2ExprMap
|
||||
{
|
||||
U64 slots_count;
|
||||
E_String2ExprMapSlot *slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Evaluation Context
|
||||
|
||||
typedef struct E_ConsTypeNode E_ConsTypeNode;
|
||||
struct E_ConsTypeNode
|
||||
{
|
||||
E_ConsTypeNode *key_next;
|
||||
E_ConsTypeNode *content_next;
|
||||
E_TypeKey key;
|
||||
E_TypeKey direct_key;
|
||||
U64 u64;
|
||||
};
|
||||
|
||||
typedef struct E_ConsTypeSlot E_ConsTypeSlot;
|
||||
struct E_ConsTypeSlot
|
||||
{
|
||||
E_ConsTypeNode *first;
|
||||
E_ConsTypeNode *last;
|
||||
};
|
||||
|
||||
typedef B32 E_MemoryReadFunction(void *user_data, void *out, Rng1U64 vaddr_range);
|
||||
|
||||
typedef struct E_Ctx E_Ctx;
|
||||
struct E_Ctx
|
||||
{
|
||||
// rjf: architecture
|
||||
Architecture arch;
|
||||
|
||||
// rjf: instruction pointer info
|
||||
U64 ip_vaddr;
|
||||
U64 ip_voff; // (within module, which uses `rdis[0]` for debug info)
|
||||
|
||||
// rjf: debug info
|
||||
RDI_Parsed **rdis;
|
||||
Rng1U64 *rdis_vaddr_ranges;
|
||||
U64 rdis_count;
|
||||
|
||||
// rjf: identifier resolution maps
|
||||
E_String2NumMap *regs_map;
|
||||
E_String2NumMap *reg_alias_map;
|
||||
E_String2NumMap *locals_map; // (within `rdis[0]`)
|
||||
E_String2NumMap *member_map; // (within `rdis[0]`)
|
||||
E_String2ExprMap *macro_map;
|
||||
|
||||
// rjf: interpretation environment info
|
||||
void *memory_read_user_data;
|
||||
E_MemoryReadFunction *memory_read;
|
||||
void *reg_data;
|
||||
U64 reg_size;
|
||||
U64 *module_base;
|
||||
U64 *frame_base;
|
||||
U64 *tls_base;
|
||||
};
|
||||
|
||||
typedef struct E_State E_State;
|
||||
struct E_State
|
||||
{
|
||||
Arena *arena;
|
||||
U64 arena_eval_start_pos;
|
||||
|
||||
// rjf: evaluation context
|
||||
E_Ctx *ctx;
|
||||
|
||||
// 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: Parse Results
|
||||
|
||||
typedef struct E_Parse E_Parse;
|
||||
struct E_Parse
|
||||
{
|
||||
E_Token *last_token;
|
||||
E_Expr *expr;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bytecode Interpretation Types
|
||||
|
||||
typedef union E_Value E_Value;
|
||||
union E_Value
|
||||
{
|
||||
U64 u512[8];
|
||||
U64 u256[4];
|
||||
U64 u128[2];
|
||||
U64 u64;
|
||||
S64 s64;
|
||||
F64 f64;
|
||||
F32 f32;
|
||||
};
|
||||
|
||||
typedef struct E_Interpretation E_Interpretation;
|
||||
struct E_Interpretation
|
||||
{
|
||||
E_Value value;
|
||||
E_InterpretationCode code;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bundled Evaluation Path Types
|
||||
|
||||
typedef struct E_Eval E_Eval;
|
||||
struct E_Eval
|
||||
{
|
||||
E_Value value;
|
||||
E_Mode mode;
|
||||
E_TypeKey type_key;
|
||||
E_InterpretationCode code;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global read_only E_String2NumMap e_string2num_map_nil = {0};
|
||||
global read_only E_String2ExprMap e_string2expr_map_nil = {0};
|
||||
global read_only E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil};
|
||||
global read_only E_Type e_type_nil = {E_TypeKind_Null};
|
||||
global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
|
||||
thread_static E_State *e_state = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Helper Functions
|
||||
|
||||
internal U64 e_hash_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ 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: Type Kind Enum Functions
|
||||
|
||||
internal E_TypeKind e_type_kind_from_rdi(RDI_TypeKind kind);
|
||||
internal E_MemberKind e_member_kind_from_rdi(RDI_MemberKind kind);
|
||||
internal RDI_EvalTypeGroup e_type_group_from_kind(E_TypeKind kind);
|
||||
internal B32 e_type_kind_is_integer(E_TypeKind kind);
|
||||
internal B32 e_type_kind_is_signed(E_TypeKind kind);
|
||||
internal B32 e_type_kind_is_basic_or_enum(E_TypeKind kind);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message Functions
|
||||
|
||||
internal void e_msg(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, String8 text);
|
||||
internal void e_msgf(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, char *fmt, ...);
|
||||
internal void e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Map Functions
|
||||
|
||||
//- rjf: string -> num
|
||||
internal E_String2NumMap e_string2num_map_make(Arena *arena, U64 slot_count);
|
||||
internal void e_string2num_map_insert(Arena *arena, E_String2NumMap *map, String8 string, U64 num);
|
||||
internal U64 e_num_from_string(E_String2NumMap *map, String8 string);
|
||||
internal E_String2NumMapNodeArray e_string2num_map_node_array_from_map(Arena *arena, E_String2NumMap *map);
|
||||
internal int e_string2num_map_node_qsort_compare__num_ascending(E_String2NumMapNode **a, E_String2NumMapNode **b);
|
||||
internal void e_string2num_map_node_array_sort__in_place(E_String2NumMapNodeArray *array);
|
||||
|
||||
//- rjf: string -> expr
|
||||
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_expr_from_string(E_String2ExprMap *map, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Debug-Info-Driven Map Building Functions
|
||||
|
||||
internal E_String2NumMap *e_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff);
|
||||
internal E_String2NumMap *e_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tokenization Functions
|
||||
|
||||
#define e_token_at_it(it, arr) (((it) < (arr)->v+(arr)->count) ? (*(it)) : e_token_zero())
|
||||
internal E_Token e_token_zero(void);
|
||||
internal void e_token_chunk_list_push(Arena *arena, E_TokenChunkList *list, U64 chunk_size, E_Token *token);
|
||||
internal E_TokenArray e_token_array_from_chunk_list(Arena *arena, E_TokenChunkList *list);
|
||||
internal E_TokenArray e_token_array_from_text(Arena *arena, String8 text);
|
||||
internal E_TokenArray e_token_array_make_first_opl(E_Token *first, E_Token *opl);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression Tree Building Functions
|
||||
|
||||
internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, void *location);
|
||||
internal void e_expr_push_child(E_Expr *parent, E_Expr *child);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
|
||||
|
||||
internal E_Ctx *e_ctx(void);
|
||||
internal void e_select_ctx(E_Ctx *ctx);
|
||||
internal U32 e_idx_from_rdi(RDI_Parsed *rdi);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Operation Functions
|
||||
|
||||
//- rjf: key constructors
|
||||
internal E_TypeKey e_type_key_zero(void);
|
||||
internal E_TypeKey e_type_key_basic(E_TypeKind kind);
|
||||
internal E_TypeKey e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_idx);
|
||||
internal E_TypeKey e_type_key_reg(Architecture arch, REGS_RegCode code);
|
||||
internal E_TypeKey e_type_key_reg_alias(Architecture arch, REGS_AliasCode code);
|
||||
internal E_TypeKey e_type_key_cons(E_TypeKind kind, E_TypeKey direct_key, U64 u64);
|
||||
|
||||
//- rjf: basic type key functions
|
||||
internal B32 e_type_key_match(E_TypeKey l, E_TypeKey r);
|
||||
|
||||
//- rjf: key -> info extraction
|
||||
internal E_TypeKind e_type_kind_from_key(E_TypeKey key);
|
||||
internal U64 e_type_byte_size_from_key(E_TypeKey key);
|
||||
internal E_Type *e_type_from_key(Arena *arena, E_TypeKey key);
|
||||
internal E_TypeKey e_type_direct_from_key(E_TypeKey key);
|
||||
internal E_TypeKey e_type_owner_from_key(E_TypeKey key);
|
||||
internal E_TypeKey e_type_ptee_from_key(E_TypeKey key);
|
||||
internal E_TypeKey e_type_unwrap_enum(E_TypeKey key);
|
||||
internal E_TypeKey e_type_unwrap(E_TypeKey key);
|
||||
internal E_TypeKey e_type_promote(E_TypeKey key);
|
||||
internal B32 e_type_match(E_TypeKey l, E_TypeKey r);
|
||||
internal E_Member *e_type_member_copy(Arena *arena, E_Member *src);
|
||||
internal int e_type_qsort_compare_members_offset(E_Member *a, E_Member *b);
|
||||
internal E_MemberArray e_type_data_members_from_key(Arena *arena, E_TypeKey key);
|
||||
internal void e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec, B32 skip_return);
|
||||
internal void e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec);
|
||||
internal String8 e_type_string_from_key(Arena *arena, E_TypeKey key);
|
||||
|
||||
//- rjf: type key data structures
|
||||
internal void e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key);
|
||||
internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parsing Functions
|
||||
|
||||
internal E_TypeKey e_leaf_type_from_name(String8 name);
|
||||
internal E_TypeKey e_type_from_expr(E_Expr *expr);
|
||||
internal void e_push_leaf_ident_exprs_from_expr__in_place(Arena *arena, E_String2ExprMap *map, E_Expr *expr);
|
||||
internal E_Parse e_parse_type_from_text_tokens(Arena *arena, String8 text, E_TokenArray *tokens);
|
||||
internal E_Parse e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *tokens, S64 max_precedence);
|
||||
internal E_Parse e_parse_expr_from_text_tokens(Arena *arena, String8 text, E_TokenArray *tokens);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR-ization Functions
|
||||
|
||||
//- rjf: op list functions
|
||||
internal void e_oplist_push_op(Arena *arena, E_OpList *list, RDI_EvalOp opcode, U64 p);
|
||||
internal void e_oplist_push_uconst(Arena *arena, E_OpList *list, U64 x);
|
||||
internal void e_oplist_push_sconst(Arena *arena, E_OpList *list, S64 x);
|
||||
internal void e_oplist_push_bytecode(Arena *arena, E_OpList *list, String8 bytecode);
|
||||
internal void e_oplist_concat_in_place(E_OpList *dst, E_OpList *to_push);
|
||||
|
||||
//- rjf: ir tree core building helpers
|
||||
internal E_IRNode *e_push_irnode(Arena *arena, RDI_EvalOp op);
|
||||
internal void e_irnode_push_child(E_IRNode *parent, E_IRNode *child);
|
||||
|
||||
//- rjf: ir subtree building helpers
|
||||
internal E_IRNode *e_irtree_const_u(Arena *arena, U64 v);
|
||||
internal E_IRNode *e_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *c);
|
||||
internal E_IRNode *e_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *l, E_IRNode *r);
|
||||
internal E_IRNode *e_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, E_IRNode *l, E_IRNode *r);
|
||||
internal E_IRNode *e_irtree_conditional(Arena *arena, E_IRNode *c, E_IRNode *l, E_IRNode *r);
|
||||
internal E_IRNode *e_irtree_bytecode_no_copy(Arena *arena, String8 bytecode);
|
||||
internal E_IRNode *e_irtree_string_literal(Arena *arena, String8 string);
|
||||
internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_IRNode *c, E_TypeKey type_key);
|
||||
internal E_IRNode *e_irtree_convert_lo(Arena *arena, E_IRNode *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in);
|
||||
internal E_IRNode *e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key);
|
||||
internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in);
|
||||
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
|
||||
|
||||
//- rjf: top-level irtree/type extraction
|
||||
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
|
||||
|
||||
//- rjf: irtree -> linear ops/bytecode
|
||||
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out);
|
||||
internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root);
|
||||
internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Interpretation Functions
|
||||
|
||||
internal E_Interpretation e_interpret(String8 bytecode);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bundled Evaluation Functions
|
||||
|
||||
internal E_Eval e_eval_from_string(Arena *arena, String8 string);
|
||||
internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval);
|
||||
internal E_Eval e_dynamically_typed_eval_from_eval(E_Eval eval);
|
||||
internal E_Eval e_value_eval_from_eval(E_Eval eval);
|
||||
|
||||
#endif // EVAL_H
|
||||
@@ -0,0 +1,202 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bundled Evaluation Functions
|
||||
|
||||
internal E_Eval
|
||||
e_eval_from_string(Arena *arena, String8 string)
|
||||
{
|
||||
E_TokenArray tokens = e_token_array_from_text(arena, string);
|
||||
E_Parse parse = e_parse_expr_from_text_tokens(arena, string, &tokens);
|
||||
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, parse.expr);
|
||||
E_OpList oplist = e_oplist_from_irtree(arena, irtree.root);
|
||||
String8 bytecode = e_bytecode_from_oplist(arena, &oplist);
|
||||
E_Interpretation interp = e_interpret(bytecode);
|
||||
E_Eval eval =
|
||||
{
|
||||
.value = interp.value,
|
||||
.mode = irtree.mode,
|
||||
.type_key = irtree.type_key,
|
||||
.code = interp.code,
|
||||
};
|
||||
e_msg_list_concat_in_place(&eval.msgs, &parse.msgs);
|
||||
e_msg_list_concat_in_place(&eval.msgs, &irtree.msgs);
|
||||
if(E_InterpretationCode_Good < eval.code && eval.code < E_InterpretationCode_COUNT)
|
||||
{
|
||||
e_msg(arena, &eval.msgs, E_MsgKind_InterpretationError, 0, e_interpretation_code_display_strings[eval.code]);
|
||||
}
|
||||
return eval;
|
||||
}
|
||||
|
||||
internal E_Eval
|
||||
e_autoresolved_eval_from_eval(E_Eval eval)
|
||||
{
|
||||
if(e_parse_ctx &&
|
||||
e_interpret_ctx &&
|
||||
e_parse_ctx->rdis_count > 0 &&
|
||||
e_interpret_ctx->module_base != 0 &&
|
||||
(eval.mode == E_Mode_Value || eval.mode == E_Mode_Reg) &&
|
||||
(e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_S64)) ||
|
||||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_U64)) ||
|
||||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_S32)) ||
|
||||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_U32))))
|
||||
{
|
||||
U64 vaddr = eval.value.u64;
|
||||
U64 voff = vaddr - e_interpret_ctx->module_base[0];
|
||||
RDI_Parsed *rdi = e_parse_ctx->rdi_primary;
|
||||
RDI_Scope *scope = rdi_scope_from_voff(rdi, voff);
|
||||
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff);
|
||||
RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff);
|
||||
U32 string_idx = 0;
|
||||
if(string_idx == 0) { string_idx = procedure->name_string_idx; }
|
||||
if(string_idx == 0) { string_idx = gvar->name_string_idx; }
|
||||
if(string_idx != 0)
|
||||
{
|
||||
eval.type_key = e_type_key_cons(E_TypeKind_Ptr, e_type_key_basic(E_TypeKind_Void), 0);
|
||||
}
|
||||
}
|
||||
return eval;
|
||||
}
|
||||
|
||||
internal E_Eval
|
||||
e_dynamically_typed_eval_from_eval(E_Eval eval)
|
||||
{
|
||||
E_TypeKey type_key = eval.type_key;
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
if(e_type_state != 0 &&
|
||||
e_interpret_ctx != 0 &&
|
||||
e_interpret_ctx->memory_read != 0 &&
|
||||
e_interpret_ctx->module_base != 0 &&
|
||||
type_kind == E_TypeKind_Ptr)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
E_TypeKey ptee_type_key = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(type_key)));
|
||||
E_TypeKind ptee_type_kind = e_type_kind_from_key(ptee_type_key);
|
||||
if(ptee_type_kind == E_TypeKind_Struct || ptee_type_kind == E_TypeKind_Class)
|
||||
{
|
||||
E_Type *ptee_type = e_type_from_key(scratch.arena, ptee_type_key);
|
||||
B32 has_vtable = 0;
|
||||
for(U64 idx = 0; idx < ptee_type->count; idx += 1)
|
||||
{
|
||||
if(ptee_type->members[idx].kind == E_MemberKind_VirtualMethod)
|
||||
{
|
||||
has_vtable = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(has_vtable)
|
||||
{
|
||||
U64 ptr_vaddr = eval.value.u64;
|
||||
U64 addr_size = bit_size_from_arch(e_interpret_ctx->arch)/8;
|
||||
U64 class_base_vaddr = 0;
|
||||
U64 vtable_vaddr = 0;
|
||||
if(e_interpret_ctx->memory_read(e_interpret_ctx->memory_read_user_data, &class_base_vaddr, r1u64(ptr_vaddr, ptr_vaddr+addr_size)) &&
|
||||
e_interpret_ctx->memory_read(e_interpret_ctx->memory_read_user_data, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size)))
|
||||
{
|
||||
U32 rdi_idx = 0;
|
||||
RDI_Parsed *rdi = 0;
|
||||
U64 module_base = 0;
|
||||
for(U64 idx = 0; idx < e_type_state->ctx->rdis_count; idx += 1)
|
||||
{
|
||||
if(contains_1u64(e_type_state->ctx->rdis_vaddr_ranges[idx], vtable_vaddr))
|
||||
{
|
||||
rdi_idx = (U32)idx;
|
||||
rdi = e_type_state->ctx->rdis[idx];
|
||||
module_base = e_type_state->ctx->rdis_vaddr_ranges[idx].min;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(rdi != 0)
|
||||
{
|
||||
U64 vtable_voff = vtable_vaddr - module_base;
|
||||
U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, vtable_voff);
|
||||
RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx);
|
||||
if(global_var->link_flags & RDI_LinkFlag_TypeScoped)
|
||||
{
|
||||
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx);
|
||||
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
|
||||
E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, rdi_idx);
|
||||
E_TypeKey ptr_to_derived_type_key = e_type_key_cons(E_TypeKind_Ptr, derived_type_key, 0);
|
||||
eval.type_key = ptr_to_derived_type_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
return eval;
|
||||
}
|
||||
|
||||
internal E_Eval
|
||||
e_value_eval_from_eval(E_Eval eval)
|
||||
{
|
||||
switch(eval.mode)
|
||||
{
|
||||
//- rjf: no work to be done. already in value mode
|
||||
default:
|
||||
case E_Mode_Value:{}break;
|
||||
|
||||
//- rjf: address => resolve into value, if leaf
|
||||
case E_Mode_Addr:
|
||||
{
|
||||
E_TypeKey type_key = e_type_unwrap(eval.type_key);
|
||||
E_TypeKind type_kind = e_type_kind_from_key(type_key);
|
||||
if(type_kind == E_TypeKind_Array)
|
||||
{
|
||||
eval.mode = E_Mode_Value;
|
||||
}
|
||||
else if(e_interpret_ctx->memory_read != 0)
|
||||
{
|
||||
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_interpret_ctx->memory_read(e_interpret_ctx->memory_read_user_data, &eval.value, value_vaddr_range))
|
||||
{
|
||||
eval.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(scratch.arena, type_key);
|
||||
U64 valid_bits_mask = 0;
|
||||
for(U64 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
valid_bits_mask |= (1<<idx);
|
||||
}
|
||||
eval.value.u64 = eval.value.u64 >> type->off;
|
||||
eval.value.u64 = eval.value.u64 & valid_bits_mask;
|
||||
eval.type_key = type->direct_type_key;
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
// rjf: manually sign-extend
|
||||
switch(type_kind)
|
||||
{
|
||||
default: break;
|
||||
case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u64);}break;
|
||||
case E_TypeKind_S16: {eval.value.s64 = (S64)*((S16 *)&eval.value.u64);}break;
|
||||
case E_TypeKind_S32: {eval.value.s64 = (S64)*((S32 *)&eval.value.u64);}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: register => resolve into value
|
||||
case E_Mode_Reg:
|
||||
{
|
||||
E_TypeKey type_key = eval.type_key;
|
||||
U64 type_byte_size = e_type_byte_size_from_key(type_key);
|
||||
U64 reg_off = eval.value.u64;
|
||||
MemoryZeroStruct(&eval.value);
|
||||
MemoryCopy(&eval.value.u256, ((U8 *)e_interpret_ctx->reg_data + reg_off), Min(type_byte_size, sizeof(U64)*4));
|
||||
eval.mode = E_Mode_Value;
|
||||
}break;
|
||||
}
|
||||
|
||||
return eval;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef EVAL_BUNDLES_H
|
||||
#define EVAL_BUNDLES_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bundled Evaluation Path Types
|
||||
|
||||
typedef struct E_Eval E_Eval;
|
||||
struct E_Eval
|
||||
{
|
||||
E_Value value;
|
||||
E_Mode mode;
|
||||
E_TypeKey type_key;
|
||||
E_InterpretationCode code;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bundled Evaluation Functions
|
||||
|
||||
internal E_Eval e_eval_from_string(Arena *arena, String8 string);
|
||||
internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval);
|
||||
internal E_Eval e_dynamically_typed_eval_from_eval(E_Eval eval);
|
||||
internal E_Eval e_value_eval_from_eval(E_Eval eval);
|
||||
|
||||
#endif // EVAL_BUNDLES_H
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "eval/generated/eval.meta.c"
|
||||
#include "eval/eval_types.c"
|
||||
#include "eval/eval_parse.c"
|
||||
#include "eval/eval_ir.c"
|
||||
#include "eval/eval_interpret.c"
|
||||
#include "eval/eval_bundles.c"
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef EVAL_INC_H
|
||||
#define EVAL_INC_H
|
||||
|
||||
#include "eval/generated/eval.meta.h"
|
||||
#include "eval/eval_types.h"
|
||||
#include "eval/eval_parse.h"
|
||||
#include "eval/eval_ir.h"
|
||||
#include "eval/eval_interpret.h"
|
||||
#include "eval/eval_bundles.h"
|
||||
|
||||
#endif // EVAL_INC_H
|
||||
@@ -0,0 +1,754 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
|
||||
|
||||
internal E_InterpretCtx *
|
||||
e_selected_interpret_ctx(void)
|
||||
{
|
||||
return e_interpret_ctx;
|
||||
}
|
||||
|
||||
internal void
|
||||
e_select_interpret_ctx(E_InterpretCtx *ctx)
|
||||
{
|
||||
e_interpret_ctx = ctx;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Interpretation Functions
|
||||
|
||||
internal E_Interpretation
|
||||
e_interpret(String8 bytecode)
|
||||
{
|
||||
E_Interpretation result = {0};
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
//- rjf: allocate stack
|
||||
U64 stack_cap = 128; // TODO(rjf): scan bytecode; determine maximum stack depth
|
||||
E_Value *stack = push_array_no_zero(scratch.arena, E_Value, stack_cap);
|
||||
U64 stack_count = 0;
|
||||
|
||||
//- rjf: iterate bytecode & perform ops
|
||||
U8 *ptr = bytecode.str;
|
||||
U8 *opl = bytecode.str + bytecode.size;
|
||||
for(;ptr < opl;)
|
||||
{
|
||||
// rjf: consume next opcode
|
||||
RDI_EvalOp op = (RDI_EvalOp)*ptr;
|
||||
if(op >= RDI_EvalOp_COUNT)
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOp;
|
||||
goto done;
|
||||
}
|
||||
U8 ctrlbits = rdi_eval_op_ctrlbits_table[op];
|
||||
ptr += 1;
|
||||
|
||||
// rjf: decode
|
||||
U64 imm = 0;
|
||||
{
|
||||
U32 decode_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits);
|
||||
U8 *next_ptr = ptr + decode_size;
|
||||
if(next_ptr > opl)
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOp;
|
||||
goto done;
|
||||
}
|
||||
// TODO(rjf): guarantee 8 bytes padding after the end of serialized
|
||||
// bytecode; read 8 bytes and mask
|
||||
switch(decode_size)
|
||||
{
|
||||
case 1:{imm = *ptr;}break;
|
||||
case 2:{imm = *(U16*)ptr;}break;
|
||||
case 4:{imm = *(U32*)ptr;}break;
|
||||
case 8:{imm = *(U64*)ptr;}break;
|
||||
}
|
||||
ptr = next_ptr;
|
||||
}
|
||||
|
||||
// rjf: pop
|
||||
E_Value *svals = 0;
|
||||
{
|
||||
U32 pop_count = RDI_POPN_FROM_CTRLBITS(ctrlbits);
|
||||
if(pop_count > stack_count)
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOp;
|
||||
goto done;
|
||||
}
|
||||
if(pop_count <= stack_count)
|
||||
{
|
||||
stack_count -= pop_count;
|
||||
svals = stack + stack_count;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: interpret op, given decodes/pops
|
||||
E_Value nval = {0};
|
||||
switch(op)
|
||||
{
|
||||
case RDI_EvalOp_Stop:
|
||||
{
|
||||
goto done;
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Noop:
|
||||
{
|
||||
// do nothing
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Cond:
|
||||
if(svals[0].u64)
|
||||
{
|
||||
ptr += imm;
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Skip:
|
||||
{
|
||||
ptr += imm;
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_MemRead:
|
||||
{
|
||||
U64 addr = svals[0].u64;
|
||||
U64 size = imm;
|
||||
B32 good_read = 0;
|
||||
if(e_interpret_ctx->memory_read != 0 && e_interpret_ctx->memory_read(e_interpret_ctx->memory_read_user_data, &nval, r1u64(addr, addr+size)))
|
||||
{
|
||||
good_read = 1;
|
||||
}
|
||||
if(!good_read)
|
||||
{
|
||||
result.code = E_InterpretationCode_BadMemRead;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_RegRead:
|
||||
{
|
||||
U8 rdi_reg_code = (imm&0x0000FF)>>0;
|
||||
U8 byte_size = (imm&0x00FF00)>>8;
|
||||
U8 byte_off = (imm&0xFF0000)>>16;
|
||||
REGS_RegCode base_reg_code = regs_reg_code_from_arch_rdi_code(e_interpret_ctx->arch, rdi_reg_code);
|
||||
REGS_Rng rng = regs_reg_code_rng_table_from_architecture(e_interpret_ctx->arch)[base_reg_code];
|
||||
U64 off = (U64)rng.byte_off + byte_off;
|
||||
U64 size = (U64)byte_size;
|
||||
if(off + size <= e_interpret_ctx->reg_size)
|
||||
{
|
||||
MemoryCopy(&nval, (U8*)e_interpret_ctx->reg_data + off, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadRegRead;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_RegReadDyn:
|
||||
{
|
||||
U64 off = svals[0].u64;
|
||||
U64 size = bit_size_from_arch(e_interpret_ctx->arch)/8;
|
||||
if(off + size <= e_interpret_ctx->reg_size)
|
||||
{
|
||||
MemoryCopy(&nval, (U8*)e_interpret_ctx->reg_data + off, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadRegRead;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_FrameOff:
|
||||
{
|
||||
if(e_interpret_ctx->frame_base != 0)
|
||||
{
|
||||
nval.u64 = *e_interpret_ctx->frame_base + imm;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadFrameBase;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_ModuleOff:
|
||||
{
|
||||
if(e_interpret_ctx->module_base != 0)
|
||||
{
|
||||
nval.u64 = *e_interpret_ctx->module_base + imm;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadModuleBase;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_TLSOff:
|
||||
{
|
||||
if(e_interpret_ctx->tls_base != 0)
|
||||
{
|
||||
nval.u64 = *e_interpret_ctx->tls_base + imm;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadTLSBase;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_ConstU8:
|
||||
case RDI_EvalOp_ConstU16:
|
||||
case RDI_EvalOp_ConstU32:
|
||||
case RDI_EvalOp_ConstU64:
|
||||
{
|
||||
nval.u64 = imm;
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Abs:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.f32 = svals[0].f32;
|
||||
if(svals[0].f32 < 0)
|
||||
{
|
||||
nval.f32 = -svals[0].f32;
|
||||
}
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.f64 = svals[0].f64;
|
||||
if(svals[0].f64 < 0)
|
||||
{
|
||||
nval.f64 = -svals[0].f64;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nval.s64 = svals[0].s64;
|
||||
if(svals[0].s64 < 0)
|
||||
{
|
||||
nval.s64 = -svals[0].s64;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Neg:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.f32 = -svals[0].f32;
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.f64 = -svals[0].f64;
|
||||
}
|
||||
else
|
||||
{
|
||||
nval.u64 = (~svals[0].u64) + 1;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Add:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.f32 = svals[0].f32 + svals[1].f32;
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.f64 = svals[0].f64 + svals[1].f64;
|
||||
}
|
||||
else
|
||||
{
|
||||
nval.u64 = svals[0].u64 + svals[1].u64;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Sub:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.f32 = svals[0].f32 - svals[1].f32;
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.f64 = svals[0].f64 - svals[1].f64;
|
||||
}
|
||||
else
|
||||
{
|
||||
nval.u64 = svals[0].u64 - svals[1].u64;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Mul:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.f32 = svals[0].f32*svals[1].f32;
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.f64 = svals[0].f64*svals[1].f64;
|
||||
}
|
||||
else
|
||||
{
|
||||
nval.u64 = svals[0].u64*svals[1].u64;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Div:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
if(svals[1].f32 != 0.f)
|
||||
{
|
||||
nval.f32 = svals[0].f32/svals[1].f32;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_DivideByZero;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
if(svals[1].f64 != 0.)
|
||||
{
|
||||
nval.f64 = svals[0].f64/svals[1].f64;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_DivideByZero;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
if(svals[1].u64 != 0)
|
||||
{
|
||||
nval.u64 = svals[0].u64/svals[1].u64;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_DivideByZero;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Mod:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
if(svals[1].u64 != 0)
|
||||
{
|
||||
nval.u64 = svals[0].u64%svals[1].u64;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_LShift:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = svals[0].u64 << svals[1].u64;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_RShift:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U)
|
||||
{
|
||||
nval.u64 = svals[0].u64 >> svals[1].u64;
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = svals[0].s64 >> svals[1].u64;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_BitAnd:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = svals[0].u64&svals[1].u64;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_BitOr:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = svals[0].u64|svals[1].u64;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_BitXor:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = svals[0].u64^svals[1].u64;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_BitNot:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = ~svals[0].u64;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_LogAnd:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = (svals[0].u64 && svals[1].u64);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_LogOr:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = (svals[0].u64 || svals[1].u64);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_LogNot:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_U ||
|
||||
imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = (!svals[0].u64);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_EqEq:
|
||||
{
|
||||
nval.u64 = (svals[0].u64 == svals[1].u64);
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_NtEq:
|
||||
{
|
||||
nval.u64 = (svals[0].u64 != svals[1].u64);
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_LsEq:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.u64 = (svals[0].f32 <= svals[1].f32);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.u64 = (svals[0].f64 <= svals[1].f64);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_U)
|
||||
{
|
||||
nval.u64 = (svals[0].u64 <= svals[1].u64);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = (svals[0].s64 <= svals[1].s64);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_GrEq:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.u64 = (svals[0].f32 >= svals[1].f32);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.u64 = (svals[0].f64 >= svals[1].f64);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_U)
|
||||
{
|
||||
nval.u64 = (svals[0].u64 >= svals[1].u64);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = (svals[0].s64 >= svals[1].s64);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Less:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.u64 = (svals[0].f32 < svals[1].f32);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.u64 = (svals[0].f64 < svals[1].f64);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_U)
|
||||
{
|
||||
nval.u64 = (svals[0].u64 < svals[1].u64);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = (svals[0].s64 < svals[1].s64);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Grtr:
|
||||
{
|
||||
if(imm == RDI_EvalTypeGroup_F32)
|
||||
{
|
||||
nval.u64 = (svals[0].f32 > svals[1].f32);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_F64)
|
||||
{
|
||||
nval.u64 = (svals[0].f64 > svals[1].f64);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_U)
|
||||
{
|
||||
nval.u64 = (svals[0].u64 > svals[1].u64);
|
||||
}
|
||||
else if(imm == RDI_EvalTypeGroup_S)
|
||||
{
|
||||
nval.u64 = (svals[0].s64 > svals[1].s64);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOpTypes;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Trunc:
|
||||
{
|
||||
if(0 < imm)
|
||||
{
|
||||
U64 mask = 0;
|
||||
if(imm < 64)
|
||||
{
|
||||
mask = max_U64 >> (64 - imm);
|
||||
}
|
||||
nval.u64 = svals[0].u64&mask;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_TruncSigned:
|
||||
{
|
||||
if(0 < imm)
|
||||
{
|
||||
U64 mask = 0;
|
||||
if(imm < 64)
|
||||
{
|
||||
mask = max_U64 >> (64 - imm);
|
||||
}
|
||||
U64 high = 0;
|
||||
if(svals[0].u64 & (1 << (imm - 1)))
|
||||
{
|
||||
high = ~mask;
|
||||
}
|
||||
nval.u64 = high|(svals[0].u64&mask);
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Convert:
|
||||
{
|
||||
U32 in = imm&0xFF;
|
||||
U32 out = (imm >> 8)&0xFF;
|
||||
if(in != out)
|
||||
{
|
||||
switch(in + out*RDI_EvalTypeGroup_COUNT)
|
||||
{
|
||||
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.u64 = (U64)svals[0].f32;
|
||||
}break;
|
||||
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.u64 = (U64)svals[0].f64;
|
||||
}break;
|
||||
|
||||
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.s64 = (S64)svals[0].f32;
|
||||
}break;
|
||||
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.s64 = (S64)svals[0].f64;
|
||||
}break;
|
||||
|
||||
case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.f32 = (F32)svals[0].u64;
|
||||
}break;
|
||||
case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.f32 = (F32)svals[0].s64;
|
||||
}break;
|
||||
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.f32 = (F32)svals[0].f64;
|
||||
}break;
|
||||
|
||||
case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.f64 = (F64)svals[0].u64;
|
||||
}break;
|
||||
case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.f64 = (F64)svals[0].s64;
|
||||
}break;
|
||||
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
|
||||
{
|
||||
nval.f64 = (F64)svals[0].f32;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Pick:
|
||||
{
|
||||
if(stack_count > imm)
|
||||
{
|
||||
nval = stack[stack_count - imm - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOp;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Pop:
|
||||
{
|
||||
// do nothing - the pop is handled by the control bits
|
||||
}break;
|
||||
|
||||
case RDI_EvalOp_Insert:
|
||||
{
|
||||
if(stack_count > imm)
|
||||
{
|
||||
if(imm > 0)
|
||||
{
|
||||
E_Value tval = stack[stack_count - 1];
|
||||
E_Value *dst = stack + stack_count - 1 - imm;
|
||||
E_Value *shift = dst + 1;
|
||||
MemoryCopy(shift, dst, imm*sizeof(E_Value));
|
||||
*dst = tval;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_BadOp;
|
||||
goto done;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
// rjf: push
|
||||
{
|
||||
U64 push_count = RDI_PUSHN_FROM_CTRLBITS(ctrlbits);
|
||||
if(push_count == 1)
|
||||
{
|
||||
if(stack_count < stack_cap)
|
||||
{
|
||||
stack[stack_count] = nval;
|
||||
stack_count += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.code = E_InterpretationCode_InsufficientStackSpace;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
done:;
|
||||
|
||||
if(stack_count >= 1)
|
||||
{
|
||||
result.value = stack[0];
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef EVAL_INTERPRET_H
|
||||
#define EVAL_INTERPRET_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bytecode Interpretation Types
|
||||
|
||||
typedef union E_Value E_Value;
|
||||
union E_Value
|
||||
{
|
||||
U64 u512[8];
|
||||
U64 u256[4];
|
||||
U64 u128[2];
|
||||
U64 u64;
|
||||
S64 s64;
|
||||
F64 f64;
|
||||
F32 f32;
|
||||
};
|
||||
|
||||
typedef struct E_Interpretation E_Interpretation;
|
||||
struct E_Interpretation
|
||||
{
|
||||
E_Value value;
|
||||
E_InterpretationCode code;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Interpretation Context
|
||||
|
||||
typedef B32 E_MemoryReadFunction(void *user_data, void *out, Rng1U64 vaddr_range);
|
||||
|
||||
typedef struct E_InterpretCtx E_InterpretCtx;
|
||||
struct E_InterpretCtx
|
||||
{
|
||||
Architecture arch;
|
||||
void *memory_read_user_data;
|
||||
E_MemoryReadFunction *memory_read;
|
||||
void *reg_data;
|
||||
U64 reg_size;
|
||||
U64 *module_base;
|
||||
U64 *frame_base;
|
||||
U64 *tls_base;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
thread_static E_InterpretCtx *e_interpret_ctx = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
|
||||
|
||||
internal E_InterpretCtx *e_selected_interpret_ctx(void);
|
||||
internal void e_select_interpret_ctx(E_InterpretCtx *ctx);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Interpretation Functions
|
||||
|
||||
internal E_Interpretation e_interpret(String8 bytecode);
|
||||
|
||||
#endif //EVAL_INTERPRET_H
|
||||
+1302
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef EVAL_IR_H
|
||||
#define EVAL_IR_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bytecode Operation Types
|
||||
|
||||
enum
|
||||
{
|
||||
E_IRExtKind_Bytecode = RDI_EvalOp_COUNT,
|
||||
E_IRExtKind_Data,
|
||||
E_IRExtKind_COUNT
|
||||
};
|
||||
|
||||
typedef struct E_Op E_Op;
|
||||
struct E_Op
|
||||
{
|
||||
E_Op *next;
|
||||
RDI_EvalOp opcode;
|
||||
union
|
||||
{
|
||||
U64 p;
|
||||
String8 bytecode;
|
||||
String8 data;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct E_OpList E_OpList;
|
||||
struct E_OpList
|
||||
{
|
||||
E_Op *first;
|
||||
E_Op *last;
|
||||
U64 op_count;
|
||||
U64 encoded_size;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR Tree Types
|
||||
|
||||
typedef struct E_IRNode E_IRNode;
|
||||
struct E_IRNode
|
||||
{
|
||||
E_IRNode *first;
|
||||
E_IRNode *last;
|
||||
E_IRNode *next;
|
||||
RDI_EvalOp op;
|
||||
String8 string;
|
||||
U64 u64;
|
||||
};
|
||||
|
||||
typedef struct E_IRTreeAndType E_IRTreeAndType;
|
||||
struct E_IRTreeAndType
|
||||
{
|
||||
E_IRNode *root;
|
||||
E_TypeKey type_key;
|
||||
E_Mode mode;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parse Context
|
||||
|
||||
typedef struct E_IRCtx E_IRCtx;
|
||||
struct E_IRCtx
|
||||
{
|
||||
E_String2ExprMap *macro_map;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
|
||||
thread_static E_IRCtx *e_ir_ctx = 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 E_IRCtx *e_selected_ir_ctx(void);
|
||||
internal void e_select_ir_ctx(E_IRCtx *ctx);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR-ization Functions
|
||||
|
||||
//- rjf: op list functions
|
||||
internal void e_oplist_push_op(Arena *arena, E_OpList *list, RDI_EvalOp opcode, U64 p);
|
||||
internal void e_oplist_push_uconst(Arena *arena, E_OpList *list, U64 x);
|
||||
internal void e_oplist_push_sconst(Arena *arena, E_OpList *list, S64 x);
|
||||
internal void e_oplist_push_bytecode(Arena *arena, E_OpList *list, String8 bytecode);
|
||||
internal void e_oplist_push_data(Arena *arena, E_OpList *list, String8 data);
|
||||
internal void e_oplist_concat_in_place(E_OpList *dst, E_OpList *to_push);
|
||||
|
||||
//- rjf: ir tree core building helpers
|
||||
internal E_IRNode *e_push_irnode(Arena *arena, RDI_EvalOp op);
|
||||
internal void e_irnode_push_child(E_IRNode *parent, E_IRNode *child);
|
||||
|
||||
//- rjf: ir subtree building helpers
|
||||
internal E_IRNode *e_irtree_const_u(Arena *arena, U64 v);
|
||||
internal E_IRNode *e_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *c);
|
||||
internal E_IRNode *e_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *l, E_IRNode *r);
|
||||
internal E_IRNode *e_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, E_IRNode *l, E_IRNode *r);
|
||||
internal E_IRNode *e_irtree_conditional(Arena *arena, E_IRNode *c, E_IRNode *l, E_IRNode *r);
|
||||
internal E_IRNode *e_irtree_bytecode_no_copy(Arena *arena, String8 bytecode);
|
||||
internal E_IRNode *e_irtree_string_literal(Arena *arena, String8 string);
|
||||
internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_IRNode *c, E_TypeKey type_key);
|
||||
internal E_IRNode *e_irtree_convert_lo(Arena *arena, E_IRNode *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in);
|
||||
internal E_IRNode *e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key);
|
||||
internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in);
|
||||
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
|
||||
|
||||
//- rjf: top-level irtree/type extraction
|
||||
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
|
||||
|
||||
//- rjf: irtree -> linear ops/bytecode
|
||||
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out);
|
||||
internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root);
|
||||
internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist);
|
||||
|
||||
#endif // EVAL_IR_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,298 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef EVAL_PARSE_H
|
||||
#define EVAL_PARSE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Generated Code
|
||||
|
||||
#include "generated/eval.meta.h"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Messages
|
||||
|
||||
typedef enum E_MsgKind
|
||||
{
|
||||
E_MsgKind_Null,
|
||||
E_MsgKind_MalformedInput,
|
||||
E_MsgKind_MissingInfo,
|
||||
E_MsgKind_ResolutionFailure,
|
||||
E_MsgKind_InterpretationError,
|
||||
E_MsgKind_COUNT
|
||||
}
|
||||
E_MsgKind;
|
||||
|
||||
typedef struct E_Msg E_Msg;
|
||||
struct E_Msg
|
||||
{
|
||||
E_Msg *next;
|
||||
E_MsgKind kind;
|
||||
void *location;
|
||||
String8 text;
|
||||
};
|
||||
|
||||
typedef struct E_MsgList E_MsgList;
|
||||
struct E_MsgList
|
||||
{
|
||||
E_Msg *first;
|
||||
E_Msg *last;
|
||||
E_MsgKind max_kind;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Token Types
|
||||
|
||||
typedef enum E_TokenKind
|
||||
{
|
||||
E_TokenKind_Null,
|
||||
E_TokenKind_Identifier,
|
||||
E_TokenKind_Numeric,
|
||||
E_TokenKind_StringLiteral,
|
||||
E_TokenKind_CharLiteral,
|
||||
E_TokenKind_Symbol,
|
||||
E_TokenKind_COUNT
|
||||
}
|
||||
E_TokenKind;
|
||||
|
||||
typedef struct E_Token E_Token;
|
||||
struct E_Token
|
||||
{
|
||||
E_TokenKind kind;
|
||||
Rng1U64 range;
|
||||
};
|
||||
|
||||
typedef struct E_TokenChunkNode E_TokenChunkNode;
|
||||
struct E_TokenChunkNode
|
||||
{
|
||||
E_TokenChunkNode *next;
|
||||
E_Token *v;
|
||||
U64 count;
|
||||
U64 cap;
|
||||
};
|
||||
|
||||
typedef struct E_TokenChunkList E_TokenChunkList;
|
||||
struct E_TokenChunkList
|
||||
{
|
||||
E_TokenChunkNode *first;
|
||||
E_TokenChunkNode *last;
|
||||
U64 node_count;
|
||||
U64 total_count;
|
||||
};
|
||||
|
||||
typedef struct E_TokenArray E_TokenArray;
|
||||
struct E_TokenArray
|
||||
{
|
||||
E_Token *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression Tree Types
|
||||
|
||||
typedef enum E_Mode
|
||||
{
|
||||
E_Mode_Null,
|
||||
E_Mode_Value,
|
||||
E_Mode_Addr,
|
||||
E_Mode_Reg,
|
||||
E_Mode_InlineData,
|
||||
}
|
||||
E_Mode;
|
||||
|
||||
typedef struct E_Expr E_Expr;
|
||||
struct E_Expr
|
||||
{
|
||||
E_Expr *first;
|
||||
E_Expr *last;
|
||||
E_Expr *next;
|
||||
void *location;
|
||||
E_ExprKind kind;
|
||||
E_Mode mode;
|
||||
E_TypeKey type_key;
|
||||
U32 u32;
|
||||
F32 f32;
|
||||
U64 u64;
|
||||
F64 f64;
|
||||
String8 string;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Map Types
|
||||
|
||||
//- rjf: string -> num
|
||||
|
||||
typedef struct E_String2NumMapNode E_String2NumMapNode;
|
||||
struct E_String2NumMapNode
|
||||
{
|
||||
E_String2NumMapNode *order_next;
|
||||
E_String2NumMapNode *hash_next;
|
||||
String8 string;
|
||||
U64 num;
|
||||
};
|
||||
|
||||
typedef struct E_String2NumMapNodeArray E_String2NumMapNodeArray;
|
||||
struct E_String2NumMapNodeArray
|
||||
{
|
||||
E_String2NumMapNode **v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct E_String2NumMapSlot E_String2NumMapSlot;
|
||||
struct E_String2NumMapSlot
|
||||
{
|
||||
E_String2NumMapNode *first;
|
||||
E_String2NumMapNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_String2NumMap E_String2NumMap;
|
||||
struct E_String2NumMap
|
||||
{
|
||||
U64 slots_count;
|
||||
U64 node_count;
|
||||
E_String2NumMapSlot *slots;
|
||||
E_String2NumMapNode *first;
|
||||
E_String2NumMapNode *last;
|
||||
};
|
||||
|
||||
//- rjf: string -> expr
|
||||
|
||||
typedef struct E_String2ExprMapNode E_String2ExprMapNode;
|
||||
struct E_String2ExprMapNode
|
||||
{
|
||||
E_String2ExprMapNode *hash_next;
|
||||
String8 string;
|
||||
E_Expr *expr;
|
||||
U64 poison_count;
|
||||
};
|
||||
|
||||
typedef struct E_String2ExprMapSlot E_String2ExprMapSlot;
|
||||
struct E_String2ExprMapSlot
|
||||
{
|
||||
E_String2ExprMapNode *first;
|
||||
E_String2ExprMapNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_String2ExprMap E_String2ExprMap;
|
||||
struct E_String2ExprMap
|
||||
{
|
||||
U64 slots_count;
|
||||
E_String2ExprMapSlot *slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parse Context
|
||||
|
||||
typedef struct E_ParseCtx E_ParseCtx;
|
||||
struct E_ParseCtx
|
||||
{
|
||||
// rjf: architecture
|
||||
Architecture arch;
|
||||
|
||||
// rjf: instruction pointer info
|
||||
U64 ip_vaddr;
|
||||
U64 ip_voff; // (within module, which uses `rdi_primary` for debug info)
|
||||
|
||||
// rjf: debug info
|
||||
RDI_Parsed *rdi_primary;
|
||||
RDI_Parsed **rdis;
|
||||
Rng1U64 *rdis_vaddr_ranges;
|
||||
U64 rdis_count;
|
||||
|
||||
// rjf: identifier resolution maps
|
||||
E_String2NumMap *regs_map;
|
||||
E_String2NumMap *reg_alias_map;
|
||||
E_String2NumMap *locals_map; // (within `rdi_primary`)
|
||||
E_String2NumMap *member_map; // (within `rdi_primary`)
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parse Results
|
||||
|
||||
typedef struct E_Parse E_Parse;
|
||||
struct E_Parse
|
||||
{
|
||||
E_Token *last_token;
|
||||
E_Expr *expr;
|
||||
E_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global read_only E_String2NumMap e_string2num_map_nil = {0};
|
||||
global read_only E_String2ExprMap e_string2expr_map_nil = {0};
|
||||
global read_only E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil};
|
||||
thread_static E_ParseCtx *e_parse_ctx = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Helper Functions
|
||||
|
||||
internal U64 e_hash_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Map Functions
|
||||
|
||||
//- rjf: string -> num
|
||||
internal E_String2NumMap e_string2num_map_make(Arena *arena, U64 slot_count);
|
||||
internal void e_string2num_map_insert(Arena *arena, E_String2NumMap *map, String8 string, U64 num);
|
||||
internal U64 e_num_from_string(E_String2NumMap *map, String8 string);
|
||||
internal E_String2NumMapNodeArray e_string2num_map_node_array_from_map(Arena *arena, E_String2NumMap *map);
|
||||
internal int e_string2num_map_node_qsort_compare__num_ascending(E_String2NumMapNode **a, E_String2NumMapNode **b);
|
||||
internal void e_string2num_map_node_array_sort__in_place(E_String2NumMapNodeArray *array);
|
||||
|
||||
//- rjf: string -> expr
|
||||
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_expr_from_string(E_String2ExprMap *map, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Debug-Info-Driven Map Building Functions
|
||||
|
||||
internal E_String2NumMap *e_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff);
|
||||
internal E_String2NumMap *e_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message Functions
|
||||
|
||||
internal void e_msg(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, String8 text);
|
||||
internal void e_msgf(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, char *fmt, ...);
|
||||
internal void e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tokenization Functions
|
||||
|
||||
#define e_token_at_it(it, arr) (((it) < (arr)->v+(arr)->count) ? (*(it)) : e_token_zero())
|
||||
internal E_Token e_token_zero(void);
|
||||
internal void e_token_chunk_list_push(Arena *arena, E_TokenChunkList *list, U64 chunk_size, E_Token *token);
|
||||
internal E_TokenArray e_token_array_from_chunk_list(Arena *arena, E_TokenChunkList *list);
|
||||
internal E_TokenArray e_token_array_from_text(Arena *arena, String8 text);
|
||||
internal E_TokenArray e_token_array_make_first_opl(E_Token *first, E_Token *opl);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
|
||||
|
||||
internal E_ParseCtx *e_selected_parse_ctx(void);
|
||||
internal void e_select_parse_ctx(E_ParseCtx *ctx);
|
||||
internal U32 e_parse_ctx_idx_from_rdi(RDI_Parsed *rdi);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression Tree Building Functions
|
||||
|
||||
internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, void *location);
|
||||
internal void e_expr_push_child(E_Expr *parent, E_Expr *child);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parsing Functions
|
||||
|
||||
internal E_TypeKey e_leaf_type_from_name(String8 name);
|
||||
internal E_TypeKey e_type_from_expr(E_Expr *expr);
|
||||
internal void e_push_leaf_ident_exprs_from_expr__in_place(Arena *arena, E_String2ExprMap *map, E_Expr *expr);
|
||||
internal E_Parse e_parse_type_from_text_tokens(Arena *arena, String8 text, E_TokenArray *tokens);
|
||||
internal E_Parse e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *tokens, S64 max_precedence);
|
||||
internal E_Parse e_parse_expr_from_text_tokens(Arena *arena, String8 text, E_TokenArray *tokens);
|
||||
|
||||
#endif // EVAL_PARSE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,247 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef EVAL_TYPES_H
|
||||
#define EVAL_TYPES_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Implicit Type Graph Key Types
|
||||
|
||||
typedef enum E_TypeKeyKind
|
||||
{
|
||||
E_TypeKeyKind_Null,
|
||||
E_TypeKeyKind_Basic,
|
||||
E_TypeKeyKind_Ext,
|
||||
E_TypeKeyKind_Cons,
|
||||
E_TypeKeyKind_Reg,
|
||||
E_TypeKeyKind_RegAlias,
|
||||
}
|
||||
E_TypeKeyKind;
|
||||
|
||||
typedef struct E_TypeKey E_TypeKey;
|
||||
struct E_TypeKey
|
||||
{
|
||||
E_TypeKeyKind kind;
|
||||
U32 u32[3];
|
||||
// [0] -> E_TypeKind (Basic, Cons, Ext); Architecture (Reg, RegAlias)
|
||||
// [1] -> Type Index In RDI (Cons, Ext); Code (Reg, RegAlias)
|
||||
// [2] -> RDI Index (Cons, Ext)
|
||||
};
|
||||
|
||||
typedef struct E_TypeKeyNode E_TypeKeyNode;
|
||||
struct E_TypeKeyNode
|
||||
{
|
||||
E_TypeKeyNode *next;
|
||||
E_TypeKey v;
|
||||
};
|
||||
|
||||
typedef struct E_TypeKeyList E_TypeKeyList;
|
||||
struct E_TypeKeyList
|
||||
{
|
||||
E_TypeKeyNode *first;
|
||||
E_TypeKeyNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Full Extracted Type Information Types
|
||||
|
||||
typedef enum E_MemberKind
|
||||
{
|
||||
E_MemberKind_Null,
|
||||
E_MemberKind_DataField,
|
||||
E_MemberKind_StaticData,
|
||||
E_MemberKind_Method,
|
||||
E_MemberKind_StaticMethod,
|
||||
E_MemberKind_VirtualMethod,
|
||||
E_MemberKind_VTablePtr,
|
||||
E_MemberKind_Base,
|
||||
E_MemberKind_VirtualBase,
|
||||
E_MemberKind_NestedType,
|
||||
E_MemberKind_Padding,
|
||||
E_MemberKind_COUNT
|
||||
}
|
||||
E_MemberKind;
|
||||
|
||||
typedef U32 E_TypeFlags;
|
||||
enum
|
||||
{
|
||||
E_TypeFlag_Const = (1<<0),
|
||||
E_TypeFlag_Volatile = (1<<1),
|
||||
};
|
||||
|
||||
typedef struct E_Member E_Member;
|
||||
struct E_Member
|
||||
{
|
||||
E_MemberKind kind;
|
||||
E_TypeKey type_key;
|
||||
String8 name;
|
||||
U64 off;
|
||||
E_TypeKeyList inheritance_key_chain;
|
||||
};
|
||||
|
||||
typedef struct E_MemberNode E_MemberNode;
|
||||
struct E_MemberNode
|
||||
{
|
||||
E_MemberNode *next;
|
||||
E_Member v;
|
||||
};
|
||||
|
||||
typedef struct E_MemberList E_MemberList;
|
||||
struct E_MemberList
|
||||
{
|
||||
E_MemberNode *first;
|
||||
E_MemberNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct E_MemberArray E_MemberArray;
|
||||
struct E_MemberArray
|
||||
{
|
||||
E_Member *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct E_EnumVal E_EnumVal;
|
||||
struct E_EnumVal
|
||||
{
|
||||
String8 name;
|
||||
U64 val;
|
||||
};
|
||||
|
||||
typedef struct E_EnumValArray E_EnumValArray;
|
||||
struct E_EnumValArray
|
||||
{
|
||||
E_EnumVal *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct E_Type E_Type;
|
||||
struct E_Type
|
||||
{
|
||||
E_TypeKind kind;
|
||||
E_TypeFlags flags;
|
||||
String8 name;
|
||||
U64 byte_size;
|
||||
U64 count;
|
||||
U32 off;
|
||||
E_TypeKey direct_type_key;
|
||||
E_TypeKey owner_type_key;
|
||||
E_TypeKey *param_type_keys;
|
||||
E_Member *members;
|
||||
E_EnumVal *enum_vals;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Evaluation Context
|
||||
|
||||
typedef struct E_ConsTypeNode E_ConsTypeNode;
|
||||
struct E_ConsTypeNode
|
||||
{
|
||||
E_ConsTypeNode *key_next;
|
||||
E_ConsTypeNode *content_next;
|
||||
E_TypeKey key;
|
||||
E_TypeKey direct_key;
|
||||
U64 u64;
|
||||
};
|
||||
|
||||
typedef struct E_ConsTypeSlot E_ConsTypeSlot;
|
||||
struct E_ConsTypeSlot
|
||||
{
|
||||
E_ConsTypeNode *first;
|
||||
E_ConsTypeNode *last;
|
||||
};
|
||||
|
||||
typedef struct E_TypeCtx E_TypeCtx;
|
||||
struct E_TypeCtx
|
||||
{
|
||||
// rjf: architecture
|
||||
Architecture arch;
|
||||
|
||||
// rjf: instruction pointer info
|
||||
U64 ip_vaddr;
|
||||
U64 ip_voff; // (within module, which uses `rdi_primary` for debug info)
|
||||
|
||||
// rjf: debug info
|
||||
RDI_Parsed *rdi_primary;
|
||||
RDI_Parsed **rdis;
|
||||
Rng1U64 *rdis_vaddr_ranges;
|
||||
U64 rdis_count;
|
||||
};
|
||||
|
||||
typedef struct E_TypeState E_TypeState;
|
||||
struct E_TypeState
|
||||
{
|
||||
Arena *arena;
|
||||
U64 arena_eval_start_pos;
|
||||
|
||||
// rjf: evaluation context
|
||||
E_TypeCtx *ctx;
|
||||
|
||||
// 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: Globals
|
||||
|
||||
global read_only E_Type e_type_nil = {E_TypeKind_Null};
|
||||
thread_static E_TypeState *e_type_state = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Kind Enum Functions
|
||||
|
||||
internal E_TypeKind e_type_kind_from_rdi(RDI_TypeKind kind);
|
||||
internal E_MemberKind e_member_kind_from_rdi(RDI_MemberKind kind);
|
||||
internal RDI_EvalTypeGroup e_type_group_from_kind(E_TypeKind kind);
|
||||
internal B32 e_type_kind_is_integer(E_TypeKind kind);
|
||||
internal B32 e_type_kind_is_signed(E_TypeKind kind);
|
||||
internal B32 e_type_kind_is_basic_or_enum(E_TypeKind kind);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
|
||||
|
||||
internal E_TypeCtx *e_selected_type_ctx(void);
|
||||
internal void e_select_type_ctx(E_TypeCtx *ctx);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Operation Functions
|
||||
|
||||
//- rjf: key constructors
|
||||
internal E_TypeKey e_type_key_zero(void);
|
||||
internal E_TypeKey e_type_key_basic(E_TypeKind kind);
|
||||
internal E_TypeKey e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_idx);
|
||||
internal E_TypeKey e_type_key_reg(Architecture arch, REGS_RegCode code);
|
||||
internal E_TypeKey e_type_key_reg_alias(Architecture arch, REGS_AliasCode code);
|
||||
internal E_TypeKey e_type_key_cons(E_TypeKind kind, E_TypeKey direct_key, U64 u64);
|
||||
|
||||
//- rjf: basic type key functions
|
||||
internal B32 e_type_key_match(E_TypeKey l, E_TypeKey r);
|
||||
|
||||
//- rjf: key -> info extraction
|
||||
internal E_TypeKind e_type_kind_from_key(E_TypeKey key);
|
||||
internal U64 e_type_byte_size_from_key(E_TypeKey key);
|
||||
internal E_Type *e_type_from_key(Arena *arena, E_TypeKey key);
|
||||
internal E_TypeKey e_type_direct_from_key(E_TypeKey key);
|
||||
internal E_TypeKey e_type_owner_from_key(E_TypeKey key);
|
||||
internal E_TypeKey e_type_ptee_from_key(E_TypeKey key);
|
||||
internal E_TypeKey e_type_unwrap_enum(E_TypeKey key);
|
||||
internal E_TypeKey e_type_unwrap(E_TypeKey key);
|
||||
internal E_TypeKey e_type_promote(E_TypeKey key);
|
||||
internal B32 e_type_match(E_TypeKey l, E_TypeKey r);
|
||||
internal E_Member *e_type_member_copy(Arena *arena, E_Member *src);
|
||||
internal int e_type_qsort_compare_members_offset(E_Member *a, E_Member *b);
|
||||
internal E_MemberArray e_type_data_members_from_key(Arena *arena, E_TypeKey key);
|
||||
internal void e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec, B32 skip_return);
|
||||
internal void e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec);
|
||||
internal String8 e_type_string_from_key(Arena *arena, E_TypeKey key);
|
||||
|
||||
//- rjf: type key data structures
|
||||
internal void e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key);
|
||||
internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src);
|
||||
|
||||
#endif // EVAL_TYPES_H
|
||||
@@ -97,7 +97,7 @@ RDI_U8 rdi_eval_op_ctrlbits_table[45] =
|
||||
RDI_EVAL_CTRLBITS(0, 0, 0),
|
||||
RDI_EVAL_CTRLBITS(0, 0, 0),
|
||||
RDI_EVAL_CTRLBITS(1, 1, 0),
|
||||
RDI_EVAL_CTRLBITS(1, 0, 0),
|
||||
RDI_EVAL_CTRLBITS(2, 0, 0),
|
||||
RDI_EVAL_CTRLBITS(1, 1, 1),
|
||||
RDI_EVAL_CTRLBITS(4, 0, 1),
|
||||
RDI_EVAL_CTRLBITS(0, 1, 1),
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
#include "dasm_cache/dasm_cache.h"
|
||||
#include "fuzzy_search/fuzzy_search.h"
|
||||
#include "demon/demon_inc.h"
|
||||
#include "eval/eval.h"
|
||||
#include "eval/eval_inc.h"
|
||||
#include "ctrl/ctrl_inc.h"
|
||||
#include "font_provider/font_provider_inc.h"
|
||||
#include "render/render_inc.h"
|
||||
@@ -93,7 +93,7 @@
|
||||
#include "dasm_cache/dasm_cache.c"
|
||||
#include "fuzzy_search/fuzzy_search.c"
|
||||
#include "demon/demon_inc.c"
|
||||
#include "eval/eval.c"
|
||||
#include "eval/eval_inc.c"
|
||||
#include "ctrl/ctrl_inc.c"
|
||||
#include "font_provider/font_provider_inc.c"
|
||||
#include "render/render_inc.c"
|
||||
|
||||
@@ -1232,7 +1232,7 @@ RDI_EvalOpTable:
|
||||
{Stop 0 0 0 0}
|
||||
{Noop 1 0 0 0}
|
||||
{Cond 2 1 1 0}
|
||||
{Skip 3 1 0 0}
|
||||
{Skip 3 2 0 0}
|
||||
{MemRead 4 1 1 1}
|
||||
{RegRead 5 4 0 1}
|
||||
{RegReadDyn 6 0 1 1}
|
||||
|
||||
Reference in New Issue
Block a user