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

+16 -28
View File
@@ -115,38 +115,26 @@ typedef enum {
* [strtab] each: slen, str(pad8) * [strtab] each: slen, str(pad8)
* [gdata] each: dsize(8), data(dsize bytes, padded to 8) * [gdata] each: dsize(8), data(dsize bytes, padded to 8)
* *
* === Calling Convention === * === Aggregate Return ABI (sret) ===
*
* 凡返回值类型为聚合(struct / union / enum / array / shape),
* 采用调用者分配 / 被调用者填充的间接返回约定:
* *
* Before CALL: * Before CALL:
* - args pushed left-to-right * - caller 在自己的帧里 alloca 一块 RetTy 大小的空间
* - target address pushed last * - 该空间的地址作为第 0 个实参先压栈
* - 其余实参照常从左到右压栈
* - target 地址最后压栈
* - CALL imm = 普通实参个数 + 1
* *
* CALL (imm = nargs): * Callee 进入后:
* 1. pop target address * - fp+0 存放 sret 指针
* 2. callstack[cp++] = {saved_fp, saved_ip, nargs} * - 形参 i 位于 fp + 8*(i+1)
* 3. fp = sp - nargs (fp points to arg0) * - 返回值直接写入 *(fp+0),然后执行 RET void
* 4. ip = target address
* *
* ALLOC k: * Caller 侧:
* sp += k (slots zeroed; local[j] = stacks.data[fp + nargs + j]) * - 调用完成后,CALL 结果槽保存 sret 指针;
* * 后续对聚合值的所有读取都通过该指针进行
* 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
*/ */
#define SPL_BINFMT_MAGIC "SPLBIN\0\0" #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++] = t->lexeme[i];
} }
buf[j] = 0; buf[j] = 0;
/* 字面量按无符号位模式解析,以容纳完整的 u64 值域 */
if (j >= 3 && buf[0] == '0' && (buf[1] == 'b' || buf[1] == 'B')) 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')) if (j >= 3 && buf[0] == '0' && (buf[1] == 'o' || buf[1] == 'O'))
return (isize)strtoll(buf + 2, NULL, 8); return (isize)strtoull(buf + 2, NULL, 8);
return (isize)strtoll(buf, NULL, 0); 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) { 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; 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: default:
return 0; 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_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_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) if (!base)
return 0; return 0;
+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); 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; 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; 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) if (idx_node->kind == SPL_IR_TYPE_CONST)
idx = (usize)idx_node->type_const.int_lit; 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_LOAD(cg, k);
cg_store_slot(cg, ref, k); cg_store_slot(cg, ref, k);
break; break;
} }
case SPL_IR_CONTROL_RET: { 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) if (k != SPL_VOID && n->control_ret.val)
cg_load_slot(cg, n->control_ret.val, k); cg_load_slot(cg, n->control_ret.val, k);
emit(cg, SPL_RET, k, 0); 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 else
cg_store_slot(cg, ref, rk); cg_store_slot(cg, ref, rk);
} else { } 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) { for (usize i = 0; i < nargs; ++i) {
spl_ir_node_ref_t pref = vec_at(n->control_call.params, 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); 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, pref, pk);
} }
cg_load_slot(cg, fref, SPL_PTR); 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) {
if (rk != SPL_VOID) /* 结果槽保存 sret 指针,后续 agg_extract 把它当聚合首地址 */
cg_store_slot(cg, ref, rk); 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; break;
} }
+25 -12
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) { static inline void sema_pop_scope(spl_sema_t *sema) {
sema->scope->current_scope = sema->store_scope; 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) { 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: { case SPL_AST_EXPR_BLOCK: {
sema_push_scope(sema);
for (usize i = 0; i < vec_size(n->block.stmts); ++i) for (usize i = 0; i < vec_size(n->block.stmts); ++i)
sema_infer(sema, vec_at(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) { if (n->block.tail_expr) {
spl_lang_type_id_t t = sema_coerce(sema, n->block.tail_expr, expected); spl_lang_type_id_t t = sema_coerce(sema, n->block.tail_expr, expected);
if (!t) if (!t) {
sema_pop_scope(sema);
return 0; return 0;
n->resolved_lang_tid = t; }
return t; r = t;
} else {
r = spl_lang_make_unit(sema->type);
} }
spl_lang_type_id_t u = spl_lang_make_unit(sema->type); sema_pop_scope(sema);
n->resolved_lang_tid = u; n->resolved_lang_tid = r;
return u; return r;
} }
default: 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)) if (!sema_coerce(sema, vec_at(n->call.args, i), pt))
return 0; return 0;
} }
/* varargs:默认提升到 isize */
if (has_varargs) { 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) {
for (usize i = fixed; i < nargs; ++i) if (!sema_infer(sema, vec_at(n->call.args, i)))
sema_coerce(sema, vec_at(n->call.args, i), vt); return 0;
}
} }
spl_lang_type_id_t ret = fn->extra.fn.ret; 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 ---------- */ /* ---------- BLOCK ---------- */
case SPL_AST_EXPR_BLOCK: { case SPL_AST_EXPR_BLOCK: {
sema_push_scope(sema);
spl_lang_type_id_t last = 0; spl_lang_type_id_t last = 0;
for (usize i = 0; i < vec_size(n->block.stmts); ++i) 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) if (n->block.tail_expr)
last = sema_infer(sema, n->block.tail_expr); last = sema_infer(sema, n->block.tail_expr);
sema_pop_scope(sema);
n->resolved_lang_tid = last; n->resolved_lang_tid = last;
return 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) if (bits == 0)
return true; return true;
bool target_signed = ir->int_type.is_signed != 0; bool target_signed = ir->int_type.is_signed != 0;
/* 字面量是无符号位模式:负号由 unary MINUS 承担 */
int64_t val = (int64_t)v.bits; uint64_t uval = v.bits;
if (target_signed) { if (target_signed) {
if (bits >= 64) if (bits >= 64)
return true; return true;
int64_t lo = -((int64_t)1 << (bits - 1)); uint64_t hi = ((uint64_t)1 << (bits - 1)) - 1;
int64_t hi = ((int64_t)1 << (bits - 1)) - 1; return uval <= hi;
return val >= lo && val <= hi;
} }
if (val < 0)
return false;
uint64_t uval = (uint64_t)val;
if (bits >= 64) if (bits >= 64)
return true; return true;
uint64_t hi = ((uint64_t)1 << bits) - 1; uint64_t hi = ((uint64_t)1 << bits) - 1;