eval extended opcode for setting base offset - used for correct cross-module evaluations, fixes go-to-definition when thread is not in module of resolved identifier's symbol

This commit is contained in:
Ryan Fleury
2026-05-13 11:23:48 -07:00
parent 0563cd3b80
commit a1778421c9
6 changed files with 55 additions and 16 deletions
+2 -4
View File
@@ -4575,12 +4575,10 @@ d_ctrl_thread__eval_scope_begin(Arena *arena, D_BreakpointList *user_bps, D_Enti
// //
U64 eval_modules_count = Max(1, entity_ctx->entity_kind_counts[D_EntityKind_Module]); U64 eval_modules_count = Max(1, entity_ctx->entity_kind_counts[D_EntityKind_Module]);
E_Module *eval_modules = push_array(arena, E_Module, eval_modules_count); E_Module *eval_modules = push_array(arena, E_Module, eval_modules_count);
E_Module *eval_modules_primary = &eval_modules[0]; E_Module *eval_modules_primary = &e_module_nil;
eval_modules_primary->vaddr_range = r1u64(0, max_U64);
U64 eval_dbg_infos_count = Max(1, entity_ctx->entity_kind_counts[D_EntityKind_Module]); U64 eval_dbg_infos_count = Max(1, entity_ctx->entity_kind_counts[D_EntityKind_Module]);
E_DbgInfo *eval_dbg_infos = push_array(arena, E_DbgInfo, eval_dbg_infos_count); E_DbgInfo *eval_dbg_infos = push_array(arena, E_DbgInfo, eval_dbg_infos_count);
E_DbgInfo *eval_dbg_infos_primary = &eval_dbg_infos[0]; E_DbgInfo *eval_dbg_infos_primary = &e_dbg_info_nil;
MemoryCopyStruct(eval_dbg_infos_primary, &e_dbg_info_nil);
{ {
U64 eval_module_idx = 0; U64 eval_module_idx = 0;
U64 eval_dbg_info_idx = 0; U64 eval_dbg_info_idx = 0;
+1
View File
@@ -73,6 +73,7 @@ enum
{ {
E_IRExtKind_Bytecode = RDI_EvalOp_COUNT, E_IRExtKind_Bytecode = RDI_EvalOp_COUNT,
E_IRExtKind_SetSpace, E_IRExtKind_SetSpace,
E_IRExtKind_SetBaseOff,
E_IRExtKind_COUNT E_IRExtKind_COUNT
}; };
+11 -9
View File
@@ -173,6 +173,11 @@ e_interpret(String8 bytecode)
{ {
selected_space = e_interpret_ctx->primary_space; selected_space = e_interpret_ctx->primary_space;
} }
U64 base_off = 0;
if(e_interpret_ctx->module_base != 0)
{
base_off = e_interpret_ctx->module_base[0];
}
//- rjf: iterate bytecode & perform ops //- rjf: iterate bytecode & perform ops
U8 *ptr = bytecode.str; U8 *ptr = bytecode.str;
@@ -189,6 +194,7 @@ e_interpret(String8 bytecode)
else switch(op) else switch(op)
{ {
case E_IRExtKind_SetSpace:{ctrlbits = RDI_EVAL_CTRLBITS(32, 0, 0);}break; case E_IRExtKind_SetSpace:{ctrlbits = RDI_EVAL_CTRLBITS(32, 0, 0);}break;
case E_IRExtKind_SetBaseOff:{ctrlbits = RDI_EVAL_CTRLBITS(8, 0, 0);}break;
default: default:
{ {
result.code = E_InterpretationCode_BadOp; result.code = E_InterpretationCode_BadOp;
@@ -241,6 +247,10 @@ e_interpret(String8 bytecode)
{ {
MemoryCopy(&selected_space, &imm, sizeof(selected_space)); MemoryCopy(&selected_space, &imm, sizeof(selected_space));
}break; }break;
case E_IRExtKind_SetBaseOff:
{
base_off = imm.u64;
}break;
case RDI_EvalOp_Stop: case RDI_EvalOp_Stop:
{ {
@@ -325,15 +335,7 @@ e_interpret(String8 bytecode)
case RDI_EvalOp_ModuleOff: case RDI_EvalOp_ModuleOff:
{ {
if(e_interpret_ctx->module_base != 0) nval.u64 = base_off + imm.u64;
{
nval.u64 = *e_interpret_ctx->module_base + imm.u64;
}
else
{
result.code = E_InterpretationCode_BadModuleBase;
goto done;
}
}break; }break;
case RDI_EvalOp_TLSOff: case RDI_EvalOp_TLSOff:
+39 -1
View File
@@ -76,6 +76,18 @@ e_oplist_push_set_space(Arena *arena, E_OpList *list, E_Space space)
list->encoded_size += 1 + sizeof(space); list->encoded_size += 1 + sizeof(space);
} }
internal void
e_oplist_push_set_base_off(Arena *arena, E_OpList *list, U64 off)
{
E_Op *node = push_array_no_zero(arena, E_Op, 1);
node->opcode = E_IRExtKind_SetBaseOff;
StaticAssert(sizeof(node->value) >= sizeof(off), node_value_size_check);
MemoryCopy(&node->value, &off, sizeof(off));
SLLQueuePush(list->first, list->last, node);
list->op_count += 1;
list->encoded_size += 1 + sizeof(off);
}
internal void internal void
e_oplist_push_string_literal(Arena *arena, E_OpList *list, String8 string) e_oplist_push_string_literal(Arena *arena, E_OpList *list, String8 string)
{ {
@@ -2065,8 +2077,14 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
Arch arch = module->arch; Arch arch = module->arch;
RDI_Parsed *rdi = dbg_info->rdi; RDI_Parsed *rdi = dbg_info->rdi;
RDI_Location location = mapped_location; RDI_Location location = mapped_location;
E_OpList base_off_adjusted_oplist = {0};
if(module != e_base_ctx->primary_module)
{
e_oplist_push_set_base_off(scratch.arena, &base_off_adjusted_oplist, module->vaddr_range.min);
}
E_OpList oplist = e_oplist_from_location(scratch.arena, rdi, location); E_OpList oplist = e_oplist_from_location(scratch.arena, rdi, location);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); e_oplist_concat_in_place(&base_off_adjusted_oplist, &oplist);
mapped_bytecode = e_bytecode_from_oplist(arena, &base_off_adjusted_oplist);
mapped_bytecode_space = space; mapped_bytecode_space = space;
if(rdi_kind_from_location(location) == RDI_LocationKind_ConstantDataOff) if(rdi_kind_from_location(location) == RDI_LocationKind_ConstantDataOff)
{ {
@@ -2540,6 +2558,11 @@ e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space
e_oplist_push_set_space(arena, out, space); e_oplist_push_set_space(arena, out, space);
}break; }break;
case E_IRExtKind_SetBaseOff:
{
e_oplist_push_set_base_off(arena, out, root->value.u64);
}break;
case RDI_EvalOp_Cond: case RDI_EvalOp_Cond:
{ {
// rjf: generate oplists for each child // rjf: generate oplists for each child
@@ -2682,6 +2705,21 @@ e_bytecode_from_oplist(Arena *arena, E_OpList *oplist)
// rjf: advance // rjf: advance
ptr = next_ptr; ptr = next_ptr;
}break; }break;
case E_IRExtKind_SetBaseOff:
{
// rjf: compute bytecode advance
U64 extra_byte_count = sizeof(U64);
U8 *next_ptr = ptr + 1 + extra_byte_count;
Assert(next_ptr <= opl);
// rjf: fill bytecode
ptr[0] = opcode;
MemoryCopy(ptr + 1, &op->value.u64, extra_byte_count);
// rjf: advance
ptr = next_ptr;
}break;
} }
} }
+1
View File
@@ -124,6 +124,7 @@ 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_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_bytecode(Arena *arena, E_OpList *list, String8 bytecode);
internal void e_oplist_push_set_space(Arena *arena, E_OpList *list, E_Space space); internal void e_oplist_push_set_space(Arena *arena, E_OpList *list, E_Space space);
internal void e_oplist_push_set_base_off(Arena *arena, E_OpList *list, U64 off);
internal void e_oplist_push_string_literal(Arena *arena, E_OpList *list, String8 string); internal void e_oplist_push_string_literal(Arena *arena, E_OpList *list, String8 string);
internal void e_oplist_concat_in_place(E_OpList *dst, E_OpList *to_push); internal void e_oplist_concat_in_place(E_OpList *dst, E_OpList *to_push);
+1 -2
View File
@@ -11173,8 +11173,7 @@ rd_frame(void)
D_EntityArray all_modules = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Module); D_EntityArray all_modules = d_entity_array_from_kind(&d_user_state->ctrl_entity_store->ctx, D_EntityKind_Module);
U64 eval_modules_count = Max(1, all_modules.count); U64 eval_modules_count = Max(1, all_modules.count);
E_Module *eval_modules = push_array(scratch.arena, E_Module, eval_modules_count); E_Module *eval_modules = push_array(scratch.arena, E_Module, eval_modules_count);
E_Module *eval_modules_primary = &eval_modules[0]; E_Module *eval_modules_primary = &e_module_nil;
eval_modules_primary->vaddr_range = r1u64(0, max_U64);
ProfScope("produce all eval modules") ProfScope("produce all eval modules")
{ {
for EachIndex(eval_module_idx, all_modules.count) for EachIndex(eval_module_idx, all_modules.count)