stage1 vm abi更新 修复更多问题

This commit is contained in:
zzy committed 2026-09-16 10:35:36 +08:00
1 parent 09d05e3a34
commit f6a0bce9f0
6 files changed
+124 -60

No files matched your search

+46 -7
View File
@@ -306,7 +306,10 @@ static void frame_build(frame_layout_t *fl, spl_ir2vm_t *ctx, spl_ir_func_ref_t
spl_type_node_t *ftn = spl_type_node(ctx->type, f->fn_tid);
usize nargs = (ftn && ftn->kind == SPL_TYPE_FN) ? vec_size(ftn->fn_type.params) : 0;
fl->args_bytes = nargs * sizeof(spl_vm_val_t);
spl_type_id_t ret_t = (ftn && ftn->kind == SPL_TYPE_FN) ? ftn->fn_type.ret : 0;
/* 聚合返回时 fp+0 是 caller 传入的 sret 指针,占用一个隐藏参数槽 */
usize hidden_sret = ir_is_aggregate(ctx, ret_t) ? 1 : 0;
fl->args_bytes = (nargs + hidden_sret) * sizeof(spl_vm_val_t);
usize off = fl->args_bytes;
@@ -743,14 +746,35 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
if (idx_node->kind == SPL_IR_TYPE_CONST)
idx = (usize)idx_node->type_const.int_lit;
}
CG_LADDR(cg, idx * sizeof(spl_vm_val_t));
/* 聚合返回时 fp+0 是 sret 指针,实参从 fp+8 起 */
spl_type_node_t *ftn = spl_type_node(ctx->type, cg->irf->fn_tid);
spl_type_id_t cur_ret = (ftn && ftn->kind == SPL_TYPE_FN) ? ftn->fn_type.ret : 0;
usize shift = ir_is_aggregate(ctx, cur_ret) ? 1 : 0;
CG_LADDR(cg, (idx + shift) * sizeof(spl_vm_val_t));
CG_LOAD(cg, k);
cg_store_slot(cg, ref, k);
break;
}
case SPL_IR_CONTROL_RET: {
uint8_t k = vm_kind_of(ctx, n->control_ret.tid);
spl_type_id_t ret_tid = n->control_ret.tid;
if (ir_is_aggregate(ctx, ret_tid)) {
/* sret:把返回值写入 *(fp+0),然后以 void 返回 */
if (n->control_ret.val) {
usize sz = ir_type_size(ctx, ret_tid);
CG_LADDR(cg, 0);
CG_LOAD(cg, SPL_PTR);
cg_load_slot(cg, n->control_ret.val, SPL_PTR);
CG_PUSH(cg, SPL_U64, sz);
int nat = get_or_add_native(ctx, "vm_memcpy");
CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat);
emit(cg, SPL_NCALL, SPL_VOID, 3);
emit(cg, SPL_DROP, SPL_VOID, 0);
}
emit(cg, SPL_RET, SPL_VOID, 0);
break;
}
uint8_t k = vm_kind_of(ctx, ret_tid);
if (k != SPL_VOID && n->control_ret.val)
cg_load_slot(cg, n->control_ret.val, k);
emit(cg, SPL_RET, k, 0);
@@ -807,6 +831,14 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
else
cg_store_slot(cg, ref, rk);
} else {
spl_type_id_t ret_t = n->control_call.tid;
bool ret_is_sret = ir_is_aggregate(ctx, ret_t);
usize sret_off = 0;
if (ret_is_sret) {
sret_off = vec_at(cg->frame.slots, ref).data_off;
CG_LADDR(cg, sret_off);
}
for (usize i = 0; i < nargs; ++i) {
spl_ir_node_ref_t pref = vec_at(n->control_call.params, i);
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
@@ -815,11 +847,18 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
cg_load_slot(cg, pref, pk);
}
cg_load_slot(cg, fref, SPL_PTR);
emit(cg, SPL_CALL, SPL_VOID, (spl_vm_val_t)nargs);
spl_vm_val_t actual_nargs = nargs + (ret_is_sret ? 1 : 0);
emit(cg, SPL_CALL, SPL_VOID, actual_nargs);
uint8_t rk = vm_kind_of(ctx, n->control_call.tid);
if (rk != SPL_VOID)
cg_store_slot(cg, ref, rk);
if (ret_is_sret) {
/* 结果槽保存 sret 指针,后续 agg_extract 把它当聚合首地址 */
CG_LADDR(cg, sret_off);
cg_store_slot(cg, ref, SPL_PTR);
} else {
uint8_t rk = vm_kind_of(ctx, ret_t);
if (rk != SPL_VOID)
cg_store_slot(cg, ref, rk);
}
}
break;
}