stage1 修复类型体内部函数前向引用时 CALL 地址错误

This commit is contained in:
zzy
2026-07-12 22:16:17 +08:00
parent 1ceda90207
commit b67edc5cee
7 changed files with 273 additions and 44 deletions

View File

@@ -13,11 +13,13 @@ void spl_comp_init(spl_comp_t *ctx) {
vec_init(ctx->toks);
vec_init(ctx->scopes);
vec_init(ctx->funcs);
vec_init(ctx->ns_chain);
map_init(ctx->type_defs, MAP_HASH_STR, MAP_CMP_STR);
map_init(ctx->const_values, MAP_HASH_STR, MAP_CMP_STR);
vec_init(ctx->call_fixups);
vec_init(ctx->call_fixup_funcs);
spl_prog_init(&ctx->prog);
ctx->error_msg[0] = '\0';
ctx->current_type_name = NULL;
}
void spl_comp_drop(spl_comp_t *ctx) {
@@ -27,9 +29,12 @@ void spl_comp_drop(spl_comp_t *ctx) {
vec_for(ctx->scopes, i) { vec_free(vec_at(ctx->scopes, i).vars); }
vec_free(ctx->scopes);
vec_free(ctx->funcs);
vec_free(ctx->ns_chain);
/* Free type defs — complex, leak for now in bootstrap */
map_free(ctx->type_defs);
map_free(ctx->const_values);
vec_free(ctx->call_fixups);
vec_free(ctx->call_fixup_funcs);
spl_prog_drop(&ctx->prog);
free(ctx->break_patches);
}
@@ -41,6 +46,8 @@ void spl_comp_reset(spl_comp_t *ctx) {
vec_for(ctx->scopes, i) { vec_free(vec_at(ctx->scopes, i).vars); }
vec_free(ctx->scopes);
vec_init(ctx->scopes);
vec_free(ctx->ns_chain);
vec_init(ctx->ns_chain);
ctx->scope_depth = 0;
ctx->tok_idx = 0;
ctx->has_error = 0;
@@ -56,9 +63,12 @@ void spl_comp_reset(spl_comp_t *ctx) {
ctx->defer_count = 0;
ctx->next_gdata_idx = 0;
ctx->addr_of_mode = 0;
ctx->current_type_name = NULL;
free(ctx->break_patches);
ctx->break_patches = NULL;
vec_free(ctx->call_fixups);
vec_init(ctx->call_fixups);
vec_free(ctx->call_fixup_funcs);
vec_init(ctx->call_fixup_funcs);
}
void spl_comp_error(spl_comp_t *ctx, const char *fmt, ...) {
@@ -164,6 +174,18 @@ void spl_pop_scope(spl_comp_t *ctx) {
}
}
/* ---- Namespace chain management ---- */
void spl_ns_push(spl_comp_t *ctx, spl_type_info_t *type) {
if (type)
vec_push(ctx->ns_chain, type);
}
void spl_ns_pop(spl_comp_t *ctx) {
if (vec_size(ctx->ns_chain) > 0)
ctx->ns_chain.size--;
}
/* ---- Variable management ---- */
int spl_declare_var(spl_comp_t *ctx, const char *name, spl_type_info_t *type, int is_const) {
@@ -214,6 +236,20 @@ int spl_get_var_offset(spl_comp_t *ctx, const char *name) {
int spl_declare_func(spl_comp_t *ctx, const char *name, spl_type_info_t *ret_type, int nparams,
int is_extern, int is_pub) {
/* Check if already declared — allows pre-registration */
vec_for(ctx->funcs, i) {
spl_func_info_t *existing = &vec_at(ctx->funcs, i);
if (strcmp(existing->name, name) == 0) {
existing->ret_type = ret_type;
existing->nparams = nparams;
existing->is_extern = is_extern;
existing->is_pub = is_pub;
existing->func_idx =
spl_prog_update_func(&ctx->prog, existing->func_idx, name, nparams);
return (int)i;
}
}
spl_func_info_t fi;
memset(&fi, 0, sizeof(fi));
fi.name = strdup(name);
@@ -233,9 +269,19 @@ int spl_declare_func(spl_comp_t *ctx, const char *name, spl_type_info_t *ret_typ
}
int spl_lookup_func(spl_comp_t *ctx, const char *name) {
vec_for(ctx->funcs, i) {
if (strcmp(vec_at(ctx->funcs, i).name, name) == 0)
return (int)i;
/* 1. Walk ns_chain from innermost to outermost, check each type's methods */
for (usize i = vec_size(ctx->ns_chain); i > 0; i--) {
spl_type_info_t *type = vec_at(ctx->ns_chain, i - 1);
vec_for(type->methods, j) {
if (strcmp(vec_at(type->methods, j).name, name) == 0)
return vec_at(type->methods, j).func_idx;
}
}
/* 2. Fallback to flat func table (top-level functions and qualified names) */
vec_for(ctx->funcs, j) {
if (strcmp(vec_at(ctx->funcs, j).name, name) == 0)
return (int)j;
}
return -1;
}
@@ -340,6 +386,19 @@ void spl_comp_register(spl_prog_t *prog) {
(void)prog;
}
/* ---- Patch call fixups ---- */
void spl_patch_call_fixups(spl_comp_t *ctx) {
for (usize i = 0; i < vec_size(ctx->call_fixups); i++) {
spl_val_t insn_idx = vec_at(ctx->call_fixups, i);
int pfi = vec_at(ctx->call_fixup_funcs, i);
if (pfi >= 0 && pfi < (int)vec_size(ctx->prog.funcs)) {
spl_val_t addr = vec_at(ctx->prog.funcs, pfi).address;
vec_at(ctx->prog.insns, insn_idx).imm = addr;
}
}
}
/* ---- Main compilation ---- */
int spl_compile(spl_comp_t *ctx, const char *source, const char *fname) {
@@ -358,5 +417,9 @@ int spl_compile(spl_comp_t *ctx, const char *source, const char *fname) {
spl_parse_prog(ctx);
if (ctx->has_error)
return -1;
/* Phase 5: Patch all function call fixups (forward references) */
spl_patch_call_fixups(ctx);
return 0;
}