stage1 vm abi更新 修复更多问题
This commit is contained in:
1 parent
09d05e3a34
commit
f6a0bce9f0
6 files changed
+121
-57
No files matched your search
+16
-28
@@ -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
@@ -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
@@ -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;
|
||||||
|
|
||||||
|
|||||||
+44
-5
@@ -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,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, 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) {
|
||||||
|
/* 结果槽保存 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)
|
if (rk != SPL_VOID)
|
||||||
cg_store_slot(cg, ref, rk);
|
cg_store_slot(cg, ref, rk);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-11
@@ -260,8 +260,13 @@ 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) {
|
||||||
|
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;
|
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) {
|
||||||
spl_lang_type_node_t *n = spl_lang_type_node(sema->type, lang_tid);
|
spl_lang_type_node_t *n = spl_lang_type_node(sema->type, 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;
|
|
||||||
}
|
}
|
||||||
spl_lang_type_id_t u = spl_lang_make_unit(sema->type);
|
r = t;
|
||||||
n->resolved_lang_tid = u;
|
} else {
|
||||||
return u;
|
r = spl_lang_make_unit(sema->type);
|
||||||
|
}
|
||||||
|
sema_pop_scope(sema);
|
||||||
|
n->resolved_lang_tid = r;
|
||||||
|
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
@@ -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;
|
||||||
|
|||||||
Reference in new issue
Block a user