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
+121 -57

No files matched your search

+16 -28
View File
@@ -115,38 +115,26 @@ typedef enum {
* [strtab] each: slen, str(pad8)
* [gdata] each: dsize(8), data(dsize bytes, padded to 8)
*
* === Calling Convention ===
* === Aggregate Return ABI (sret) ===
*
* 凡返回值类型为聚合(struct / union / enum / array / shape),
* 采用调用者分配 / 被调用者填充的间接返回约定:
*
* Before CALL:
* - args pushed left-to-right
* - target address pushed last
* - caller 在自己的帧里 alloca 一块 RetTy 大小的空间
* - 该空间的地址作为第 0 个实参先压栈
* - 其余实参照常从左到右压栈
* - target 地址最后压栈
* - CALL imm = 普通实参个数 + 1
*
* CALL (imm = nargs):
* 1. pop target address
* 2. callstack[cp++] = {saved_fp, saved_ip, nargs}
* 3. fp = sp - nargs (fp points to arg0)
* 4. ip = target address
* Callee 进入后:
* - fp+0 存放 sret 指针
* - 形参 i 位于 fp + 8*(i+1)
* - 返回值直接写入 *(fp+0),然后执行 RET void
*
* ALLOC k:
* sp += k (slots zeroed; local[j] = stacks.data[fp + nargs + j])
*
* LADDR imm:
* push &stacks.data[fp + imm]
* (imm < nargs accesses args; imm >= nargs accesses locals)
*
* GADDR imm:
* push prog->gdata[imm] (pointer to global data blob)
*
* RET:
* 1. pop retval if non-void type
* 2. sp = fp
* 3. pop frame; fp = saved_fp, ip = saved_ip
* 4. push retval if non-void type
*
* CALLI (indirect call):
* - stack before: ..., arg0, ..., argN-1, nargs, func_addr
* 1. pop func_addr, then pop nargs
* 2. same as CALL steps 2-4
* Caller 侧:
* - 调用完成后,CALL 结果槽保存 sret 指针;
* 后续对聚合值的所有读取都通过该指针进行
*/
#define SPL_BINFMT_MAGIC "SPLBIN\0\0"
+6 -3
View File
@@ -175,11 +175,14 @@ static isize parse_int_literal(const spl_tok_t *t) {
buf[j++] = t->lexeme[i];
}
buf[j] = 0;
/* 字面量按无符号位模式解析,以容纳完整的 u64 值域 */
if (j >= 3 && buf[0] == '0' && (buf[1] == 'b' || buf[1] == 'B'))
return (isize)strtoll(buf + 2, NULL, 2);
return (isize)strtoull(buf + 2, NULL, 2);
if (j >= 3 && buf[0] == '0' && (buf[1] == 'o' || buf[1] == 'O'))
return (isize)strtoll(buf + 2, NULL, 8);
return (isize)strtoll(buf, NULL, 0);
return (isize)strtoull(buf + 2, NULL, 8);
if (j >= 3 && buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X'))
return (isize)strtoull(buf, NULL, 16);
return (isize)strtoull(buf, NULL, 10);
}
static double parse_float_literal(const spl_tok_t *t) {
+27 -1
View File
@@ -630,6 +630,16 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
return 0;
}
}
case SPL_OP_BOOL_OR: {
spl_ast_node_t *bmln = spl_ast_node(a->sema->ast, n->binary.left);
spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0;
return spl_ir_builder_arith_or(a->ir, op_tid, l, r);
}
case SPL_OP_BOOL_AND: {
spl_ast_node_t *bmln = spl_ast_node(a->sema->ast, n->binary.left);
spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0;
return spl_ir_builder_arith_and(a->ir, op_tid, l, r);
}
default:
return 0;
}
@@ -888,7 +898,23 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
spl_type_id_t usize_ir = to_ir_type(a, usize_lang);
spl_ir_node_ref_t base = emit_lvalue(a, n->slice.obj);
/* base = 元素数据首地址 */
spl_ir_node_ref_t base = 0;
if (obj_kind == SPL_LANG_TYPE_PTR) {
/* ptr 值本身就是首元素地址 */
base = emit_expr(a, n->slice.obj);
} else if (obj_kind == SPL_LANG_TYPE_SLICE) {
/* 取 slice 的 ptr 字段 */
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
if (!slice_val)
return 0;
spl_type_id_t ptr_ir = spl_type_builder_ptr((spl_type_t *)a->sema->type, elem_ir);
base = spl_ir_builder_agg_extract(a->ir, obj_ir, ptr_ir, SPL_SLICE_PTR_FIELD_IDX,
slice_val);
} else {
/* ARRAY:&arr 即首元素地址 */
base = emit_lvalue(a, n->slice.obj);
}
if (!base)
return 0;
+44 -5
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,12 +847,19 @@ 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 (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;
}
+24 -11
View File
@@ -260,7 +260,12 @@ static inline void sema_push_scope(spl_sema_t *sema) {
}
static inline void sema_pop_scope(spl_sema_t *sema) {
spl_scope_id_t cur = sema->scope->current_scope;
if (cur != 0 && cur < vec_size(sema->scope->scopes)) {
sema->scope->current_scope = vec_at(sema->scope->scopes, cur).parent;
} else {
sema->scope->current_scope = sema->store_scope;
}
}
static spl_lang_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_lang_type_id_t lang_tid) {
@@ -869,18 +874,23 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
}
case SPL_AST_EXPR_BLOCK: {
sema_push_scope(sema);
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
sema_infer(sema, vec_at(n->block.stmts, i));
spl_lang_type_id_t r = 0;
if (n->block.tail_expr) {
spl_lang_type_id_t t = sema_coerce(sema, n->block.tail_expr, expected);
if (!t)
if (!t) {
sema_pop_scope(sema);
return 0;
n->resolved_lang_tid = t;
return t;
}
spl_lang_type_id_t u = spl_lang_make_unit(sema->type);
n->resolved_lang_tid = u;
return u;
r = t;
} else {
r = spl_lang_make_unit(sema->type);
}
sema_pop_scope(sema);
n->resolved_lang_tid = r;
return r;
}
default:
@@ -1218,11 +1228,12 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
if (!sema_coerce(sema, vec_at(n->call.args, i), pt))
return 0;
}
/* varargs:默认提升到 isize */
if (has_varargs) {
spl_lang_type_id_t vt = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1);
for (usize i = fixed; i < nargs; ++i)
sema_coerce(sema, vec_at(n->call.args, i), vt);
for (usize i = fixed; i < nargs; ++i) {
if (!sema_infer(sema, vec_at(n->call.args, i)))
return 0;
}
}
spl_lang_type_id_t ret = fn->extra.fn.ret;
@@ -1495,11 +1506,13 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
/* ---------- BLOCK ---------- */
case SPL_AST_EXPR_BLOCK: {
sema_push_scope(sema);
spl_lang_type_id_t last = 0;
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
last = sema_infer(sema, vec_at(n->block.stmts, i));
sema_infer(sema, vec_at(n->block.stmts, i));
if (n->block.tail_expr)
last = sema_infer(sema, n->block.tail_expr);
sema_pop_scope(sema);
n->resolved_lang_tid = last;
return last;
}
+4 -9
View File
@@ -575,20 +575,15 @@ bool spl_lang_mpa_int_fits(const spl_type_t *type, spl_lang_type_id_t target, sp
if (bits == 0)
return true;
bool target_signed = ir->int_type.is_signed != 0;
int64_t val = (int64_t)v.bits;
/* 字面量是无符号位模式:负号由 unary MINUS 承担 */
uint64_t uval = v.bits;
if (target_signed) {
if (bits >= 64)
return true;
int64_t lo = -((int64_t)1 << (bits - 1));
int64_t hi = ((int64_t)1 << (bits - 1)) - 1;
return val >= lo && val <= hi;
uint64_t hi = ((uint64_t)1 << (bits - 1)) - 1;
return uval <= hi;
}
if (val < 0)
return false;
uint64_t uval = (uint64_t)val;
if (bits >= 64)
return true;
uint64_t hi = ((uint64_t)1 << bits) - 1;