/* spl_ir2vm.c IR SIR (spl_prog_t) 降级 * * ABI 约定spl_ir2vm.h。要点: * - 布局(C ABI)唯一来源在此文件 * - 每个产生IR 节点 = 一vreg(locals 区按类型对齐的字节块* * - 纯值节点(type.const / gdata.addr / mem.alloca / sizeof 折叠 / param * 不落 vreg,引用处重算 * * - 聚合= 字节块,整体搬运NCALL vm_memcpy * - 聚合返回sret(隐*T 参数,最后一个) * - * 两遍发射:先发指令记label→地址,回JMP/BZ/BNZ;全部函 * 生成后回const_fnref 的函数地址 */ #include "spl_ir2vm.h" /* VM 枚举 spl_type_t stage1 spl_type_t(struct)重名:局部重命名 */ #define spl_type_t spl_vm_tag_t #include "../stage0/spl_mcode.h" #undef spl_type_t #include "../stage0/include/core_vec.h" #include #include #include static spl_type_node_t *tn(const spl_type_t *ty, spl_type_id_t tid) { return spl_type_node((spl_type_t *)ty, tid); } static spl_type_id_t under(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, tid); return (t && t->kind == SPL_TYPE_ID) ? t->type_id : tid; } static usize align_up(usize v, usize a) { return (v + a - 1) & ~(a - 1); } static int is_agg(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, under(ty, tid)); return t && (t->kind == SPL_TYPE_STRUCT || t->kind == SPL_TYPE_UNION || t->kind == SPL_TYPE_ENUM || t->kind == SPL_TYPE_SLICE || t->kind == SPL_TYPE_RANGE || t->kind == SPL_TYPE_ARRAY); } static usize type_align(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, under(ty, tid)); if (!t) return 1; switch (t->kind) { case SPL_TYPE_VOID: case SPL_TYPE_BOOL: return 1; case SPL_TYPE_INT: return t->int_type.bits / 8; case SPL_TYPE_FLOAT: return t->float_type.bits / 8; case SPL_TYPE_PTR: case SPL_TYPE_FN: case SPL_TYPE_SLICE: case SPL_TYPE_RANGE: case SPL_TYPE_ENUM: return sizeof(usize); case SPL_TYPE_ARRAY: return type_align(ty, t->array_type.element); case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: { usize a = 1; for (usize i = 0; i < t->agg_field_types.size; i++) { usize fa = type_align(ty, t->agg_field_types.data[i]); if (fa > a) a = fa; } return a; } default: return 1; } } static usize type_size(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, under(ty, tid)); if (!t) return 0; switch (t->kind) { case SPL_TYPE_VOID: return 0; case SPL_TYPE_BOOL: case SPL_TYPE_INT: return t->kind == SPL_TYPE_BOOL ? 1 : t->int_type.bits / 8; case SPL_TYPE_FLOAT: return t->float_type.bits / 8; case SPL_TYPE_PTR: case SPL_TYPE_FN: return sizeof(usize); case SPL_TYPE_SLICE: case SPL_TYPE_RANGE: return sizeof(usize) * 2; case SPL_TYPE_ARRAY: return t->array_type.len * type_size(ty, t->array_type.element); case SPL_TYPE_STRUCT: { usize sz = 0; for (usize i = 0; i < t->agg_field_types.size; i++) { usize fa = type_align(ty, t->agg_field_types.data[i]); sz = align_up(sz, fa); sz += type_size(ty, t->agg_field_types.data[i]); } return align_up(sz, type_align(ty, tid)); /* 尾填*/ } case SPL_TYPE_UNION: { usize sz = 0; for (usize i = 0; i < t->agg_field_types.size; i++) { usize fs = type_size(ty, t->agg_field_types.data[i]); if (fs > sz) sz = fs; } return align_up(sz, type_align(ty, tid)); } case SPL_TYPE_ENUM: { usize payload = 0; spl_type_id_t self = under(ty, tid); for (usize i = 0; i < t->enum_type.variants.size; i++) { spl_type_id_t v = under(ty, t->enum_type.variants.data[i]); if (v == self) continue; usize vs = type_size(ty, v); if (vs > payload) payload = vs; } return align_up(sizeof(usize) + payload, sizeof(usize)); } default: return 0; } } /* 聚合字段字节偏移(struct 顺序对齐;union 0;enum tag=0/payload=8 * slice/range = idx*8*/ static usize field_offset(const spl_type_t *ty, spl_type_id_t agg_tid, isize idx) { spl_type_node_t *t = tn(ty, under(ty, agg_tid)); if (!t) return 0; switch (t->kind) { case SPL_TYPE_SLICE: case SPL_TYPE_RANGE: return (usize)idx * sizeof(usize); case SPL_TYPE_ARRAY: return (usize)idx * type_size(ty, t->array_type.element); case SPL_TYPE_ENUM: return idx <= 0 ? 0 : sizeof(usize); case SPL_TYPE_UNION: return 0; case SPL_TYPE_STRUCT: { if (idx < 0 || (usize)idx >= t->agg_field_types.size) return 0; usize off = 0; for (isize i = 0; i < idx; i++) { usize fa = type_align(ty, t->agg_field_types.data[i]); off = align_up(off, fa); off += type_size(ty, t->agg_field_types.data[i]); } return align_up(off, type_align(ty, t->agg_field_types.data[idx])); } default: return 0; } } /* 聚合字段类型(enum idx0=tag usize;idx1=payload 首个非自身变体) */ static spl_type_id_t field_type(const spl_type_t *ty, spl_type_id_t agg_tid, isize idx) { spl_type_node_t *t = tn(ty, under(ty, agg_tid)); if (!t) return 0; switch (t->kind) { case SPL_TYPE_SLICE: if (idx == 0) return spl_type_ptr((spl_type_t *)ty, t->slice_element); if (idx == 1) return spl_type_int((spl_type_t *)ty, sizeof(usize) * 8, 0); return 0; case SPL_TYPE_RANGE: return t->range_element; case SPL_TYPE_ARRAY: return t->array_type.element; case SPL_TYPE_ENUM: if (idx <= 0) return spl_type_int((spl_type_t *)ty, sizeof(usize) * 8, 0); { spl_type_id_t self = under(ty, agg_tid); for (usize i = 0; i < t->enum_type.variants.size; i++) { spl_type_id_t v = under(ty, t->enum_type.variants.data[i]); if (v != self) return v; } } return spl_type_int((spl_type_t *)ty, sizeof(usize) * 8, 0); default: if (idx < 0 || (usize)idx >= t->agg_field_types.size) return 0; return t->agg_field_types.data[idx]; } } /* IR 类型 SIR 标量 tag;聚合返SPL_VOID */ static spl_vm_tag_t vm_tag(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, under(ty, tid)); if (!t) return SPL_VOID; switch (t->kind) { case SPL_TYPE_VOID: return SPL_VOID; case SPL_TYPE_BOOL: return SPL_BOOL; case SPL_TYPE_INT: switch (t->int_type.bits / 8) { case 1: return t->int_type.is_signed ? SPL_I8 : SPL_U8; case 2: return t->int_type.is_signed ? SPL_I16 : SPL_U16; case 4: return t->int_type.is_signed ? SPL_I32 : SPL_U32; default: return t->int_type.is_signed ? SPL_I64 : SPL_U64; } case SPL_TYPE_FLOAT: return t->float_type.bits == 32 ? SPL_F32 : SPL_F64; case SPL_TYPE_PTR: case SPL_TYPE_FN: return SPL_PTR; default: return SPL_VOID; /* 聚合 */ } } /* 算术/比较 tag:bool I32(VM 的算术宏BOOL case,值已零扩展等价) */ static spl_vm_tag_t arith_tag(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, under(ty, tid)); if (t && t->kind == SPL_TYPE_BOOL) return SPL_I32; return vm_tag(ty, tid); } static int is_void(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, under(ty, tid)); return t && t->kind == SPL_TYPE_VOID; } /* ================================================================ * 发射上下 * ================================================================ */ typedef struct { usize insn_idx; isize target_node; /* >=0: IR label node0: 绝对地址 */ isize abs_addr; int is_call_pad; /* 0 = 跳转 = const_fnref PUSH 占位(imm=函数地址*/ spl_ir_func_ref_t fn; } fix_t; typedef VEC(fix_t) fix_vec_t; typedef struct { spl_ir2vm_t *pub; spl_prog_t prog; int err; VEC(isize) func_addr; /* IR func id SIR 地址;native = -1 */ VEC(isize) native_idx; /* IR func id native 表下标;native = -1 */ VEC(usize) cstr_gdata; /* cstr 去重:字符串 prog.gdata 下标 */ VEC(const char *) cstr_list; fix_vec_t fnfixes; /* const_fnref PUSH 占位(函数地址回填*/ } ctx_t; typedef struct { ctx_t *c; spl_ir_func_ref_t fid; spl_ir_func_t *f; spl_type_id_t ret_tid; int sret; usize sret_off; /* sret 参数在参数区字节偏移 */ usize param_bytes; usize *param_off; /* 每参数偏*/ usize nparams; usize *vreg_off; /* node ref locals 偏移 */ usize nvreg; isize *label_addr; /* node ref 指令地址1 未定 */ usize nlabel; usize locals_bytes; usize temp_off; /* mem.set 计数器槽 */ usize insn_base; fix_vec_t fixes; } fctx_t; static void diag(ctx_t *c, spl_ir_func_ref_t fid, spl_ir_node_ref_t ref, const char *msg) { c->err++; const spl_ir_t *ir = c->pub->ir; const char *fname = (fid && fid < ir->funcs.size && ir->funcs.data[fid].name) ? ir->funcs.data[fid].name : "?"; LOG_ERROR("ir2vm: func @%s node %zu: %s", fname, ref, msg); } /* ---- 指令发射 ---- */ static usize add_insn(fctx_t *fc, uint8_t opcode, uint8_t type, spl_val_t imm) { return (usize)spl_prog_add_instr(&fc->c->prog, opcode, type, imm) - 1; } static void emit_push(fctx_t *fc, spl_val_t imm) { add_insn(fc, SPL_PUSH, SPL_VOID, imm); } static void emit_load_insn(fctx_t *fc, spl_vm_tag_t tag) { add_insn(fc, SPL_LOAD, tag, 0); } static void emit_store_insn(fctx_t *fc, spl_vm_tag_t tag) { add_insn(fc, SPL_STORE, tag, 0); } static void emit_laddr(fctx_t *fc, usize byte_off) { add_insn(fc, SPL_LADDR, SPL_VOID, byte_off); } static void emit_gaddr(fctx_t *fc, usize idx) { add_insn(fc, SPL_GADDR, SPL_VOID, idx); } static void emit_arith(fctx_t *fc, spl_opcode_t op, spl_vm_tag_t tag) { add_insn(fc, op, tag, 0); } static void emit_jmp_fix(fctx_t *fc, isize target_node, isize abs_addr) { usize idx = add_insn(fc, SPL_JMP, SPL_VOID, 0); fix_t fx = {idx, target_node, abs_addr, 0, 0}; vec_push(fc->fixes, fx); } static void emit_bnz_fix(fctx_t *fc, isize target_node, isize abs_addr) { usize idx = add_insn(fc, SPL_BNZ, SPL_VOID, 0); fix_t fx = {idx, target_node, abs_addr, 0, 0}; vec_push(fc->fixes, fx); } /* ---- native 辅助:vm_memcpy ---- */ static isize native_index(ctx_t *c, const char *name) { for (usize i = 0; i < c->prog.natives.size; i++) if (c->prog.natives.data[i].name && strcmp(c->prog.natives.data[i].name, name) == 0) return (isize)i; return -1; } static void emit_memcpy(fctx_t *fc, usize size) { isize ni = native_index(fc->c, "vm_memcpy"); if (ni < 0) diag(fc->c, fc->fid, 0, "vm_memcpy native not registered"); emit_push(fc, (spl_val_t)size); emit_push(fc, (spl_val_t)ni); add_insn(fc, SPL_NCALL, SPL_VOID, 3); } /* ================================================================ * 节点信息 * ================================================================ */ static spl_ir_node_t *n_at(spl_ir_func_t *f, spl_ir_node_ref_t ref) { if (!ref || ref >= f->nodes.size) return NULL; return &f->nodes.data[ref]; } static spl_type_id_t fn_ret(const spl_type_t *ty, spl_type_id_t fn_tid) { spl_type_node_t *t = tn(ty, under(ty, fn_tid)); return (t && t->kind == SPL_TYPE_FN) ? t->fn_type.ret : 0; } static spl_type_id_t node_type(const spl_ir_t *ir, const spl_type_t *ty, spl_ir_func_t *f, spl_ir_node_ref_t ref) { spl_ir_node_t *n = n_at(f, ref); if (!n) return 0; switch (n->kind) { case SPL_IR_TYPE_CONST: return n->type_const.tid; case SPL_IR_ARITH_ADD: case SPL_IR_ARITH_SUB: case SPL_IR_ARITH_MUL: case SPL_IR_ARITH_DIV: case SPL_IR_ARITH_REM: case SPL_IR_ARITH_NEG: case SPL_IR_ARITH_ABS: case SPL_IR_ARITH_AND: case SPL_IR_ARITH_OR: case SPL_IR_ARITH_XOR: case SPL_IR_ARITH_SHL: case SPL_IR_ARITH_SHR: case SPL_IR_ARITH_NOT: return n->arith.tid; case SPL_IR_CMP_EQ: case SPL_IR_CMP_NE: case SPL_IR_CMP_LT: case SPL_IR_CMP_LE: case SPL_IR_CMP_GT: case SPL_IR_CMP_GE: return spl_type_bool((spl_type_t *)ty); case SPL_IR_CAST_TRUNC: case SPL_IR_CAST_ZEXT: case SPL_IR_CAST_SEXT: case SPL_IR_CAST_FEXT: case SPL_IR_CAST_FTRUNC: case SPL_IR_CAST_BITCAST: case SPL_IR_CAST_PTR2INT: case SPL_IR_CAST_INT2PTR: case SPL_IR_CAST_BOOL2INT: case SPL_IR_CASE_INT2FLOAT: case SPL_IR_CASE_FLOAT2INT: return n->cast.to_tid; case SPL_IR_MEM_ALLOCA: return spl_type_ptr((spl_type_t *)ty, n->mem_alloc.tid); case SPL_IR_MEM_LOAD: return n->mem_load.tid; case SPL_IR_MEM_OFFSET: return spl_type_ptr((spl_type_t *)ty, n->mem_offset.tid); case SPL_IR_MEM_FIELD_PTR: return spl_type_ptr((spl_type_t *)ty, field_type(ty, n->mem_field_ptr.tid, (isize)n->mem_field_ptr.field_idx)); case SPL_IR_MEM_GLOBAL_ALLOC: { spl_type_id_t gt = 0; if (ir && n->mem_global_alloc.const_node < ir->gdata.size) gt = ir->gdata.data[n->mem_global_alloc.const_node].type_const.tid; return spl_type_ptr((spl_type_t *)ty, gt); } case SPL_IR_AGG_CONSTRUCT: return n->agg_construct.tid; case SPL_IR_AGG_EXTRACT: return n->agg_extract.field_tid; case SPL_IR_AGG_INSERT: return n->agg_insert.tid; case SPL_IR_CONTROL_SELECT: return n->control_select.tid; case SPL_IR_CONTROL_CALL: return fn_ret(ty, n->control_call.tid); case SPL_IR_CONTROL_PARAM: return n->control_param.tid; case SPL_IR_CONTROL_RET: return n->control_ret.tid; case SPL_IR_TYPE_BITSIZEOF: case SPL_IR_TYPE_SIZEOF: case SPL_IR_TYPE_ALIGNOF: case SPL_IR_TYPE_OFFSETOF: case SPL_IR_TYPE_FIELD_COUNT: return spl_type_int((spl_type_t *)ty, sizeof(usize) * 8, 0); default: return 0; } } /* 是否需vreg 槽(布局用)。const/gaddr/param/sizeof 折叠不落 vreg * alloca 的槽即缓冲区本体,仍需分配*/ static int needs_vreg_slot(spl_ir_func_t *f, spl_ir_node_ref_t ref) { spl_ir_node_t *n = n_at(f, ref); if (!n) return 0; switch (n->kind) { case SPL_IR_TYPE_CONST: case SPL_IR_MEM_GLOBAL_ALLOC: case SPL_IR_CONTROL_PARAM: case SPL_IR_TYPE_BITSIZEOF: case SPL_IR_TYPE_SIZEOF: case SPL_IR_TYPE_ALIGNOF: case SPL_IR_TYPE_OFFSETOF: case SPL_IR_TYPE_FIELD_COUNT: return 0; default: return 1; } } /* ================================================================ * 发射(emit_value / emit_node * ================================================================ */ static int produces_value(spl_ir_kind_t k) { switch (k) { case SPL_IR_MEM_STORE: case SPL_IR_MEM_COPY: case SPL_IR_MEM_SET: case SPL_IR_MEM_FENCE: case SPL_IR_CONTROL_BR: case SPL_IR_CONTROL_JMP: case SPL_IR_CONTROL_RET: case SPL_IR_CONTROL_UNREACHABLE: case SPL_IR_CONTROL_TRAP: case SPL_IR_DBG_BREAKPOINT: case SPL_IR_DBG_DECLARE: return 0; default: return 1; } } static spl_opcode_t arith_op(spl_ir_kind_t k, int is_signed); static int is_signed_type(const spl_type_t *ty, spl_type_id_t tid); static void emit_value(fctx_t *fc, spl_ir_node_ref_t ref); /* 整数字宽(bool = 1;其余取 int bits*/ static usize int_bits(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, under(ty, tid)); if (!t) return 0; if (t->kind == SPL_TYPE_BOOL) return 1; if (t->kind == SPL_TYPE_INT) return t->int_type.bits; return 0; } static void emit_store_vreg(fctx_t *fc, spl_ir_node_ref_t ref) { const spl_type_t *ty = fc->c->pub->type; spl_type_id_t tid = node_type(fc->c->pub->ir, ty, fc->f, ref); if (!tid) return; if (is_agg(ty, tid)) { /* 栈顶 = 聚合值地址;memcpy(栈顶 vreg(ref)) */ emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); add_insn(fc, SPL_SWAP, SPL_VOID, 0); emit_memcpy(fc, type_size(ty, tid)); } else { emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); add_insn(fc, SPL_SWAP, SPL_VOID, 0); emit_store_insn(fc, vm_tag(ty, tid)); } } static void emit_const_push(fctx_t *fc, spl_ir_node_t *n) { const spl_type_t *ty = fc->c->pub->type; spl_type_id_t tid = n->type_const.tid; spl_type_node_t *t = tn(ty, under(ty, tid)); if (!t) { diag(fc->c, fc->fid, 0, "bad const type"); return; } switch (t->kind) { case SPL_TYPE_INT: emit_push(fc, (spl_val_t)(usize)n->type_const.int_lit); return; case SPL_TYPE_BOOL: emit_push(fc, n->type_const.int_lit ? 1 : 0); return; case SPL_TYPE_FLOAT: { double d = n->type_const.float_lit; if (t->float_type.bits == 32) { float f = (float)d; spl_val_t b = 0; memcpy(&b, &f, 4); emit_push(fc, b); } else { spl_val_t b = 0; memcpy(&b, &d, 8); emit_push(fc, b); } return; } case SPL_TYPE_PTR: if (n->type_const.cstr_lit) { /* 字符串常量:gdata 条目地址 */ isize gi = -1; for (usize i = 0; i < fc->c->cstr_list.size; i++) if (strcmp(fc->c->cstr_list.data[i], n->type_const.cstr_lit) == 0) { gi = (isize)fc->c->cstr_gdata.data[i]; break; } if (gi < 0) diag(fc->c, fc->fid, 0, "string const not registered"); emit_gaddr(fc, (usize)gi); } else { emit_push(fc, 0); } return; case SPL_TYPE_FN: { spl_ir_func_ref_t fn = n->type_const.fn; if (fn && fn < fc->c->func_addr.size && fc->c->native_idx.data[fn] >= 0) { diag(fc->c, fc->fid, 0, "native function used as value"); emit_push(fc, 0); return; } usize idx = add_insn(fc, SPL_PUSH, SPL_VOID, 0); fix_t fx = {idx, -1, 0, 1, fn}; vec_push(fc->c->fnfixes, fx); return; } case SPL_TYPE_SLICE: case SPL_TYPE_RANGE: case SPL_TYPE_ARRAY: case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: case SPL_TYPE_ENUM: diag(fc->c, fc->fid, 0, "aggregate const not supported"); emit_push(fc, 0); return; default: diag(fc->c, fc->fid, 0, "bad const kind"); emit_push(fc, 0); return; } } static void emit_value(fctx_t *fc, spl_ir_node_ref_t ref) { const spl_ir_t *ir = fc->c->pub->ir; const spl_type_t *ty = fc->c->pub->type; spl_ir_node_t *n = n_at(fc->f, ref); if (!n) { diag(fc->c, fc->fid, ref, "bad operand"); emit_push(fc, 0); return; } switch (n->kind) { case SPL_IR_TYPE_CONST: emit_const_push(fc, n); return; case SPL_IR_MEM_GLOBAL_ALLOC: { const spl_ir_t *ir2 = fc->c->pub->ir; usize idx = n->mem_global_alloc.const_node; if (idx >= ir2->gdata.size) { diag(fc->c, fc->fid, ref, "unknown global symbol"); emit_push(fc, 0); } else { emit_gaddr(fc, idx); } return; } case SPL_IR_MEM_ALLOCA: emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); return; case SPL_IR_CONTROL_PARAM: { if (is_agg(ty, n->control_param.tid)) { /* 聚合值参数:prologue 已 memcpy 到 param vreg,取 vreg 地址 */ emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); } else { usize po = fc->param_off ? fc->param_off[n->control_param.idx] : 0; emit_laddr(fc, po); emit_load_insn(fc, vm_tag(ty, n->control_param.tid)); } return; } case SPL_IR_TYPE_BITSIZEOF: emit_push(fc, type_size(ty, n->bitsizeof.tid) * 8); return; case SPL_IR_TYPE_SIZEOF: emit_push(fc, type_size(ty, n->ir_sizeof.tid)); return; case SPL_IR_TYPE_ALIGNOF: emit_push(fc, type_align(ty, n->ir_alignof.tid)); return; case SPL_IR_TYPE_OFFSETOF: { spl_ir_node_t *fi = n_at(fc->f, n->ir_offsetof.field_idx); isize idx = 0; if (fi && fi->kind == SPL_IR_TYPE_CONST) idx = fi->type_const.int_lit; emit_push(fc, field_offset(ty, n->ir_offsetof.tid, idx)); return; } case SPL_IR_TYPE_FIELD_COUNT: { spl_type_node_t *tt = tn(ty, under(ty, n->field_count.tid)); usize cnt = 0; if (tt && (tt->kind == SPL_TYPE_STRUCT || tt->kind == SPL_TYPE_UNION)) cnt = tt->agg_field_types.size; else if (tt && tt->kind == SPL_TYPE_ENUM) cnt = tt->enum_type.variants.size; emit_push(fc, cnt); return; } default: { spl_type_id_t tid = node_type(ir, ty, fc->f, ref); if (!tid) { diag(fc->c, fc->fid, ref, "value node has no type"); emit_push(fc, 0); return; } if (is_agg(ty, tid)) { emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); } else { emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); emit_load_insn(fc, vm_tag(ty, tid)); } return; } } } static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref); /* 记录 IR 块首 label 当前指令地址 */ static void mark_label(fctx_t *fc, spl_ir_node_ref_t ref) { if (ref >= fc->nlabel) return; if (fc->label_addr[ref] < 0) fc->label_addr[ref] = (isize)fc->c->prog.insns.size; } static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref) { const spl_ir_t *ir = fc->c->pub->ir; const spl_type_t *ty = fc->c->pub->type; spl_ir_node_t *n = n_at(fc->f, ref); if (!n) return; mark_label(fc, ref); switch (n->kind) { case SPL_IR_TYPE_CONST: case SPL_IR_MEM_GLOBAL_ALLOC: case SPL_IR_MEM_ALLOCA: case SPL_IR_CONTROL_PARAM: case SPL_IR_TYPE_BITSIZEOF: case SPL_IR_TYPE_SIZEOF: case SPL_IR_TYPE_ALIGNOF: case SPL_IR_TYPE_OFFSETOF: case SPL_IR_TYPE_FIELD_COUNT: return; /* 纯节点:引用时重*/ case SPL_IR_ARITH_ADD: case SPL_IR_ARITH_SUB: case SPL_IR_ARITH_MUL: case SPL_IR_ARITH_DIV: case SPL_IR_ARITH_REM: case SPL_IR_ARITH_AND: case SPL_IR_ARITH_OR: case SPL_IR_ARITH_XOR: case SPL_IR_ARITH_SHL: case SPL_IR_ARITH_SHR: { spl_type_id_t tid = n->arith.tid; emit_value(fc, n->arith.left); if (n->arith.right) emit_value(fc, n->arith.right); spl_opcode_t aop = arith_op(n->kind, is_signed_type(ty, tid)); /* 浮点除法/取余:VM 的 DIV_S/REM_S 宏(DIV_REM_S)含 float 分支,DIV_U/REM_U 无 */ spl_type_node_t *at = tn(ty, under(ty, tid)); if (at && at->kind == SPL_TYPE_FLOAT) { if (n->kind == SPL_IR_ARITH_DIV) aop = SPL_DIV_S; else if (n->kind == SPL_IR_ARITH_REM) aop = SPL_REM_S; } emit_arith(fc, aop, arith_tag(ty, tid)); emit_store_vreg(fc, ref); return; } case SPL_IR_ARITH_NEG: { emit_value(fc, n->arith.left); emit_arith(fc, SPL_NEG, arith_tag(ty, n->arith.tid)); emit_store_vreg(fc, ref); return; } case SPL_IR_ARITH_NOT: { emit_value(fc, n->arith.left); emit_arith(fc, SPL_NOT, SPL_VOID); emit_store_vreg(fc, ref); return; } case SPL_IR_ARITH_ABS: { spl_vm_tag_t tag = arith_tag(ty, n->arith.tid); emit_value(fc, n->arith.left); /* x */ emit_push(fc, 0); emit_arith(fc, SPL_SLT, tag); /* x<0 */ usize bz = add_insn(fc, SPL_BZ, SPL_VOID, 0); emit_value(fc, n->arith.left); emit_arith(fc, SPL_NEG, arith_tag(ty, n->arith.tid)); usize jmp = add_insn(fc, SPL_JMP, SPL_VOID, 0); usize pos_addr = fc->c->prog.insns.size; fc->c->prog.insns.data[bz].imm = pos_addr - (bz + 1); emit_value(fc, n->arith.left); usize end_addr = fc->c->prog.insns.size; fc->c->prog.insns.data[jmp].imm = end_addr - (jmp + 1); emit_store_vreg(fc, ref); return; } case SPL_IR_CMP_EQ: case SPL_IR_CMP_NE: case SPL_IR_CMP_LT: case SPL_IR_CMP_LE: case SPL_IR_CMP_GT: case SPL_IR_CMP_GE: { spl_type_id_t tid = n->cmp.tid; emit_value(fc, n->cmp.a); emit_value(fc, n->cmp.b); spl_opcode_t op; /* 浮点顺序比较:VM 的 CMP_U 无 float 分支,须走 CMP_S(SLT/SLE/SGT/SGE 含 float case) */ int is_f = 0; spl_type_node_t *ct = tn(ty, under(ty, tid)); if (ct && ct->kind == SPL_TYPE_FLOAT) is_f = 1; switch (n->kind) { case SPL_IR_CMP_EQ: op = SPL_EQ; break; case SPL_IR_CMP_NE: op = SPL_NE; break; case SPL_IR_CMP_LT: op = (is_signed_type(ty, tid) || is_f) ? SPL_SLT : SPL_ULT; break; case SPL_IR_CMP_LE: op = (is_signed_type(ty, tid) || is_f) ? SPL_SLE : SPL_ULE; break; case SPL_IR_CMP_GT: op = (is_signed_type(ty, tid) || is_f) ? SPL_SGT : SPL_UGT; break; default: op = (is_signed_type(ty, tid) || is_f) ? SPL_SGE : SPL_UGE; break; } emit_arith(fc, op, arith_tag(ty, tid)); emit_store_vreg(fc, ref); return; } case SPL_IR_CAST_TRUNC: { usize bits = int_bits(ty, n->cast.to_tid); emit_value(fc, n->cast.val); add_insn(fc, SPL_TRUNC, SPL_VOID, bits); emit_store_vreg(fc, ref); return; } case SPL_IR_CAST_SEXT: { usize bits = int_bits(ty, n->cast.from_tid); emit_value(fc, n->cast.val); add_insn(fc, SPL_SEXT, SPL_VOID, bits); emit_store_vreg(fc, ref); return; } case SPL_IR_CAST_ZEXT: { usize bits = int_bits(ty, n->cast.from_tid); emit_value(fc, n->cast.val); add_insn(fc, SPL_ZEXT, SPL_VOID, bits); emit_store_vreg(fc, ref); return; } case SPL_IR_CAST_BITCAST: case SPL_IR_CAST_PTR2INT: case SPL_IR_CAST_INT2PTR: case SPL_IR_CAST_BOOL2INT: emit_value(fc, n->cast.val); emit_store_vreg(fc, ref); return; case SPL_IR_CAST_FEXT: case SPL_IR_CAST_FTRUNC: case SPL_IR_CASE_INT2FLOAT: case SPL_IR_CASE_FLOAT2INT: diag(fc->c, fc->fid, ref, "float/int conversion not implemented in ir2vm"); emit_value(fc, n->cast.val); emit_store_vreg(fc, ref); return; case SPL_IR_MEM_LOAD: { spl_type_id_t tid = n->mem_load.tid; if (is_agg(ty, tid)) { emit_value(fc, n->mem_load.ptr); /* [src] */ emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); add_insn(fc, SPL_SWAP, SPL_VOID, 0); /* [dst, src] */ emit_memcpy(fc, type_size(ty, tid)); } else { emit_value(fc, n->mem_load.ptr); emit_load_insn(fc, vm_tag(ty, tid)); emit_store_vreg(fc, ref); } return; } case SPL_IR_MEM_STORE: { spl_type_id_t tid = n->mem_store.tid; if (is_agg(ty, tid)) { emit_value(fc, n->mem_store.ptr); /* [dst] */ emit_value(fc, n->mem_store.val); /* [dst, src] */ emit_memcpy(fc, type_size(ty, tid)); } else { emit_value(fc, n->mem_store.ptr); emit_value(fc, n->mem_store.val); emit_store_insn(fc, vm_tag(ty, tid)); } return; } case SPL_IR_MEM_OFFSET: { emit_value(fc, n->mem_offset.ptr); emit_value(fc, n->mem_offset.offset); /* 指针运算(C 语义):*_(void 元素)看成整数,偏移即字节、不 scale; * *T(非 void)偏移为元素索引,乘 sizeof(T)。 */ spl_type_id_t ut = under(ty, n->mem_offset.tid); if (!is_void(ty, ut)) { emit_push(fc, type_size(ty, n->mem_offset.tid)); emit_arith(fc, SPL_MUL, SPL_USIZE); } emit_arith(fc, SPL_ADD, SPL_USIZE); emit_store_vreg(fc, ref); return; } case SPL_IR_MEM_FIELD_PTR: { emit_value(fc, n->mem_field_ptr.agg); emit_push(fc, field_offset(ty, n->mem_field_ptr.tid, (isize)n->mem_field_ptr.field_idx)); emit_arith(fc, SPL_ADD, SPL_USIZE); emit_store_vreg(fc, ref); return; } case SPL_IR_MEM_COPY: { emit_value(fc, n->mem_copy.dst); emit_value(fc, n->mem_copy.src); emit_value(fc, n->mem_copy.size); isize ni = native_index(fc->c, "vm_memcpy"); emit_push(fc, (spl_val_t)ni); add_insn(fc, SPL_NCALL, SPL_VOID, 3); return; } case SPL_IR_MEM_SET: { /* 字节填充循环:i=0; L: if i>=size goto E; dst[i]=val; i++; jmp L; E: */ usize temp = fc->temp_off; emit_laddr(fc, fc->param_bytes + temp); emit_push(fc, 0); emit_store_insn(fc, SPL_U64); usize l1 = fc->c->prog.insns.size; emit_laddr(fc, fc->param_bytes + temp); emit_load_insn(fc, SPL_U64); emit_value(fc, n->mem_set.size); emit_arith(fc, SPL_ULT, SPL_USIZE); usize bz = add_insn(fc, SPL_BZ, SPL_VOID, 0); emit_value(fc, n->mem_set.dst); emit_laddr(fc, fc->param_bytes + temp); emit_load_insn(fc, SPL_U64); emit_arith(fc, SPL_ADD, SPL_USIZE); emit_value(fc, n->mem_set.val); emit_store_insn(fc, SPL_U8); emit_laddr(fc, fc->param_bytes + temp); emit_load_insn(fc, SPL_U64); emit_push(fc, 1); emit_arith(fc, SPL_ADD, SPL_U64); emit_store_insn(fc, SPL_U64); usize jmp = add_insn(fc, SPL_JMP, SPL_VOID, 0); usize e_addr = fc->c->prog.insns.size; fc->c->prog.insns.data[bz].imm = e_addr - (bz + 1); fc->c->prog.insns.data[jmp].imm = l1 - (jmp + 1); return; } case SPL_IR_MEM_FENCE: return; case SPL_IR_AGG_CONSTRUCT: { spl_type_id_t agg_tid = n->agg_construct.tid; for (usize i = 0; i < n->agg_construct.fields.size; i++) { /* 字段实际类型取字段节点(enum payload 因变体而异*/ spl_type_id_t ft = node_type(ir, ty, fc->f, n->agg_construct.fields.data[i]); if (!ft) ft = field_type(ty, agg_tid, (isize)i); emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); usize foff = field_offset(ty, agg_tid, (isize)i); if (foff) { emit_push(fc, foff); emit_arith(fc, SPL_ADD, SPL_USIZE); } emit_value(fc, n->agg_construct.fields.data[i]); if (is_agg(ty, ft)) emit_memcpy(fc, type_size(ty, ft)); else emit_store_insn(fc, vm_tag(ty, ft)); } return; } case SPL_IR_AGG_EXTRACT: { spl_type_id_t agg_tid = n->agg_extract.tid; isize idx = n->agg_extract.field_idx; spl_type_id_t ft = n->agg_extract.field_tid; if (!ft) ft = field_type(ty, agg_tid, idx); emit_value(fc, n->agg_extract.val); /* [val 地址] */ usize foff = field_offset(ty, agg_tid, idx); if (foff) { emit_push(fc, foff); emit_arith(fc, SPL_ADD, SPL_USIZE); } if (is_agg(ty, ft)) { emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); add_insn(fc, SPL_SWAP, SPL_VOID, 0); emit_memcpy(fc, type_size(ty, ft)); } else { emit_load_insn(fc, vm_tag(ty, ft)); emit_store_vreg(fc, ref); } return; } case SPL_IR_AGG_INSERT: { spl_type_id_t agg_tid = n->agg_insert.tid; isize idx = n->agg_insert.field_idx; spl_type_id_t ft = node_type(ir, ty, fc->f, n->agg_insert.field); if (!ft) ft = field_type(ty, agg_tid, idx); emit_value(fc, n->agg_insert.agg); emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); add_insn(fc, SPL_SWAP, SPL_VOID, 0); emit_memcpy(fc, type_size(ty, agg_tid)); emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); usize foff = field_offset(ty, agg_tid, idx); if (foff) { emit_push(fc, foff); emit_arith(fc, SPL_ADD, SPL_USIZE); } emit_value(fc, n->agg_insert.field); if (is_agg(ty, ft)) emit_memcpy(fc, type_size(ty, ft)); else emit_store_insn(fc, vm_tag(ty, ft)); return; } case SPL_IR_CONTROL_SELECT: { emit_value(fc, n->control_select.cond); usize bz = add_insn(fc, SPL_BZ, SPL_VOID, 0); emit_value(fc, n->control_select.true_val); usize jmp = add_insn(fc, SPL_JMP, SPL_VOID, 0); usize else_addr = fc->c->prog.insns.size; fc->c->prog.insns.data[bz].imm = else_addr - (bz + 1); emit_value(fc, n->control_select.false_val); usize end_addr = fc->c->prog.insns.size; fc->c->prog.insns.data[jmp].imm = end_addr - (jmp + 1); emit_store_vreg(fc, ref); return; } case SPL_IR_CONTROL_BR: { emit_value(fc, n->control_br.cond); emit_bnz_fix(fc, n->control_br.true_label, -1); emit_jmp_fix(fc, n->control_br.false_label, -1); return; } case SPL_IR_CONTROL_JMP: emit_jmp_fix(fc, n->control_jmp.label, -1); return; case SPL_IR_CONTROL_CALL: { spl_type_id_t fn_tid = n->control_call.tid; spl_type_id_t ret = fn_ret(ty, fn_tid); int sret = is_agg(ty, ret); /* 槽数:标量 1 槽;聚合按 C ABI 块数;sret 地址 1 槽 */ usize nargs = 0; for (usize i = 0; i < n->control_call.params.size; i++) { spl_type_id_t pt = node_type(ir, ty, fc->f, n->control_call.params.data[i]); if (is_agg(ty, pt)) nargs += align_up(type_size(ty, pt), 8) / 8; else nargs += 1; } if (sret) nargs += 1; for (usize i = 0; i < n->control_call.params.size; i++) { spl_ir_node_ref_t pref = n->control_call.params.data[i]; spl_type_id_t pt = node_type(ir, ty, fc->f, pref); if (is_agg(ty, pt)) { /* 聚合值按值:逐 8 字节块压栈(vreg 已 8 对齐) */ usize sz = align_up(type_size(ty, pt), 8); for (usize j = 0; j < sz / 8; j++) { emit_laddr(fc, fc->param_bytes + fc->vreg_off[pref] + j * 8); emit_load_insn(fc, SPL_U64); } } else { emit_value(fc, pref); } } if (sret) emit_laddr(fc, fc->param_bytes + fc->vreg_off[ref]); spl_ir_node_t *fn = n_at(fc->f, n->control_call.func); if (fn && fn->kind == SPL_IR_TYPE_CONST && fn->type_const.fn && fn->type_const.fn < fc->c->func_addr.size) { spl_ir_func_ref_t fid = fn->type_const.fn; if (fc->c->native_idx.data[fid] >= 0) { emit_push(fc, (spl_val_t)fc->c->native_idx.data[fid]); add_insn(fc, SPL_NCALL, SPL_VOID, nargs); } else { usize idx = add_insn(fc, SPL_PUSH, SPL_VOID, 0); fix_t fx = {idx, -1, 0, 1, fid}; vec_push(fc->c->fnfixes, fx); add_insn(fc, SPL_CALL, SPL_VOID, nargs); } if (ret && !is_agg(ty, ret)) emit_store_vreg(fc, ref); } else { /* 间接调用:栈 [args, nargs, func_addr] CALLI(VM: POP addr, POP nargs) * 先 push 实参(上方循环),再 push nargs,最后 push func_addr */ emit_push(fc, nargs); emit_value(fc, n->control_call.func); add_insn(fc, SPL_CALLI, SPL_VOID, 0); /* 返回值留在栈顶,与直接调用一致:存入 vreg */ if (ret && !is_agg(ty, ret)) emit_store_vreg(fc, ref); } return; } case SPL_IR_CONTROL_RET: { spl_type_id_t tid = n->control_ret.tid; if (is_agg(ty, tid)) { if (n->control_ret.val) { emit_value(fc, n->control_ret.val); emit_laddr(fc, fc->sret_off); emit_load_insn(fc, SPL_PTR); add_insn(fc, SPL_SWAP, SPL_VOID, 0); emit_memcpy(fc, type_size(ty, tid)); } add_insn(fc, SPL_RET, SPL_VOID, 0); } else if (!is_void(ty, tid)) { if (n->control_ret.val) emit_value(fc, n->control_ret.val); else emit_push(fc, 0); /* 空体函数:返回未定义0 */ add_insn(fc, SPL_RET, vm_tag(ty, tid), 0); } else { add_insn(fc, SPL_RET, SPL_VOID, 0); } return; } case SPL_IR_CONTROL_UNREACHABLE: add_insn(fc, SPL_HALT, SPL_VOID, 0); return; case SPL_IR_CONTROL_TRAP: /* trap → halt 带非零退出码(assert 失败语义) */ add_insn(fc, SPL_HALT, SPL_VOID, 1); return; case SPL_IR_DBG_BREAKPOINT: add_insn(fc, SPL_BK, SPL_VOID, 0); return; case SPL_IR_DBG_DECLARE: return; default: diag(fc->c, fc->fid, ref, "unsupported IR node"); return; } } /* ---- 算术 opcode 映射 ---- */ static spl_opcode_t arith_op(spl_ir_kind_t k, int is_signed) { switch (k) { case SPL_IR_ARITH_ADD: return SPL_ADD; case SPL_IR_ARITH_SUB: return SPL_SUB; case SPL_IR_ARITH_MUL: return SPL_MUL; case SPL_IR_ARITH_DIV: return is_signed ? SPL_DIV_S : SPL_DIV_U; case SPL_IR_ARITH_REM: return is_signed ? SPL_REM_S : SPL_REM_U; case SPL_IR_ARITH_AND: return SPL_AND; case SPL_IR_ARITH_OR: return SPL_OR; case SPL_IR_ARITH_XOR: return SPL_XOR; case SPL_IR_ARITH_SHL: return SPL_SHL; case SPL_IR_ARITH_SHR: return is_signed ? SPL_SHR_S : SPL_SHR_U; default: return SPL_ADD; } } static int is_signed_type(const spl_type_t *ty, spl_type_id_t tid) { spl_type_node_t *t = tn(ty, under(ty, tid)); return t && t->kind == SPL_TYPE_INT && t->int_type.is_signed; } /* ================================================================ * 函数生成 + 主流 * ================================================================ */ static void gdata_bytes(ctx_t *c, const spl_ir_node_t *g, unsigned char *out) { const spl_type_t *ty = c->pub->type; spl_type_id_t tid = g->type_const.tid; usize sz = type_size(ty, tid); memset(out, 0, sz); spl_type_node_t *t = tn(ty, under(ty, tid)); if (!t) return; if (t->kind == SPL_TYPE_INT || t->kind == SPL_TYPE_BOOL) { isize v = (isize)g->type_const.int_lit; usize n = sz < sizeof(isize) ? sz : sizeof(isize); memcpy(out, &v, n); } else if (t->kind == SPL_TYPE_FLOAT) { if (t->float_type.bits == 32) { float f = (float)g->type_const.float_lit; memcpy(out, &f, sz < 4 ? sz : 4); } else { double d = g->type_const.float_lit; memcpy(out, &d, sz < 8 ? sz : 8); } } } static void gen_func(ctx_t *c, spl_ir_func_ref_t fid) { const spl_ir_t *ir = c->pub->ir; const spl_type_t *ty = c->pub->type; fctx_t fc; memset(&fc, 0, sizeof fc); fc.c = c; fc.fid = fid; fc.f = &ir->funcs.data[fid]; vec_init(fc.fixes); spl_type_id_t fn_tid = fc.f->fn_tid; spl_type_node_t *ftn = tn(ty, under(ty, fn_tid)); usize nparams = (ftn && ftn->kind == SPL_TYPE_FN) ? ftn->fn_type.params.size : 0; /* 参数布局(C ABI):标量 align8 一槽 8B;聚合 align8 + size 跨多槽 */ usize off = 0; fc.nparams = nparams; fc.param_off = (usize *)malloc((nparams ? nparams : 1) * sizeof(usize)); for (usize i = 0; i < nparams; i++) { spl_type_id_t pt = ftn->fn_type.params.data[i]; off = align_up(off, 8); fc.param_off[i] = off; if (is_agg(ty, pt)) off += align_up(type_size(ty, pt), 8); else off += 8; } fc.ret_tid = (ftn && ftn->kind == SPL_TYPE_FN) ? ftn->fn_type.ret : 0; fc.sret = is_agg(ty, fc.ret_tid); fc.sret_off = align_up(off, 8); if (fc.sret) off = fc.sret_off + 8; fc.param_bytes = off; /* vreg / label 布局*/ fc.nvreg = fc.f->nodes.size; fc.vreg_off = (usize *)calloc(fc.nvreg ? fc.nvreg : 1, sizeof(usize)); fc.nlabel = fc.f->nodes.size; fc.label_addr = (isize *)malloc((fc.nlabel ? fc.nlabel : 1) * sizeof(isize)); for (usize i = 0; i < fc.nlabel; i++) fc.label_addr[i] = -1; usize locals = 0; for (usize ref = 1; ref < fc.f->nodes.size; ref++) { spl_ir_node_t *rn = &fc.f->nodes.data[ref]; /* 无条件分配(不按 produces_value 过滤):某些节点 produces_value 误报 0 但 * 仍会被 emit_value 引用并 store_vreg(如聚合字段提取编译成的节点)。若跳过则 * vreg_off 保持 calloc 的 0,多个节点共享槽 0 互相覆盖(指针偏移/写地址损坏根源)。 */ spl_type_id_t tid = 0; if (!needs_vreg_slot(fc.f, ref)) { /* 聚合值参数:分配 vreg(prologue 从参数区 memcpy 进来) */ if (rn->kind == SPL_IR_CONTROL_PARAM && is_agg(ty, rn->control_param.tid)) tid = rn->control_param.tid; else continue; } else { tid = node_type(ir, ty, fc.f, ref); /* alloca 的槽 = 缓冲区本体,大小为 mem_alloc.tid 而非 *T */ if (rn->kind == SPL_IR_MEM_ALLOCA) tid = rn->mem_alloc.tid; } if (!tid) { /* tid 未解析(MEM_LOAD / BITCAST 未标 tid 等):占位一个 usize 槽, * 否则 vreg_off 保持 0,多个节点共享槽 0 互相覆盖。 */ fc.vreg_off[ref] = align_up(locals, 8); locals = fc.vreg_off[ref] + 8; continue; } usize sz = type_size(ty, tid); usize al = type_align(ty, tid); if (is_agg(ty, tid)) al = align_up(al, 8); /* 聚合 vreg 8 对齐:聚合参数逐块压栈需 8 字节边界 */ locals = align_up(locals, al); fc.vreg_off[ref] = locals; locals += sz; } fc.temp_off = align_up(locals, 8); /* 临时区(bytes):表达式/调用的 PUSH/POP 堆叠、store/bnz 的弹栈会临时压低 sp, * 若无此区 sp 会降入 vreg 槽区覆盖尚未使用的 vreg(大数组构造等深表达式)。 */ locals = fc.temp_off + 8 + 1024 * 8; fc.locals_bytes = locals; /* prologue:ALLOC + 聚合值参数 memcpy(参数区 → param vreg) */ fc.insn_base = c->prog.insns.size; usize k = (locals + 7) / 8; add_insn(&fc, SPL_ALLOC, SPL_VOID, k); for (usize ref = 1; ref < fc.f->nodes.size; ref++) { spl_ir_node_t *rn = &fc.f->nodes.data[ref]; if (rn->kind != SPL_IR_CONTROL_PARAM) continue; spl_type_id_t pt = rn->control_param.tid; if (!is_agg(ty, pt)) continue; usize pidx = rn->control_param.idx; emit_laddr(&fc, fc.param_off[pidx]); /* 参数区聚合起始 */ emit_laddr(&fc, fc.param_bytes + fc.vreg_off[ref]); /* param vreg */ add_insn(&fc, SPL_SWAP, SPL_VOID, 0); emit_memcpy(&fc, type_size(ty, pt)); } /* 节点发射 */ for (usize ref = 1; ref < fc.f->nodes.size; ref++) emit_node(&fc, ref); /* 末尾兜底:若最后不是终止指令,RET(void) */ if (c->prog.insns.size) { spl_ins_t *last = &c->prog.insns.data[c->prog.insns.size - 1]; spl_opcode_t lop = (spl_opcode_t)last->opcode; if (lop != SPL_RET && lop != SPL_JMP && lop != SPL_BZ && lop != SPL_BNZ && lop != SPL_HALT) { add_insn(&fc, SPL_RET, SPL_VOID, 0); } } /* 回填 IR label 跳转 */ for (usize i = 0; i < fc.fixes.size; i++) { fix_t *fx = &fc.fixes.data[i]; isize addr = fx->target_node >= 0 ? fc.label_addr[fx->target_node] : fx->abs_addr; if (addr < 0) { diag(c, fid, 0, "unresolved branch target"); continue; } c->prog.insns.data[fx->insn_idx].imm = (spl_val_t)(addr - (isize)(fx->insn_idx + 1)); } /* func */ spl_func_t sf; memset(&sf, 0, sizeof sf); sf.name = fc.f->name ? strdup(fc.f->name) : strdup("?"); sf.nargs = (fc.param_bytes + 7) / 8; /* C ABI 参数区槽数(含 sret) */ sf.ninsns = c->prog.insns.size - fc.insn_base; sf.address = fc.insn_base; sf.idx_of_strtab = 0; spl_prog_add_func(&c->prog, &sf); free(fc.param_off); free(fc.vreg_off); free(fc.label_addr); vec_free(fc.fixes); } int spl_ir2vm_run(spl_ir2vm_t *ctx, const char *outpath) { ctx_t c; memset(&c, 0, sizeof c); c.pub = ctx; spl_prog_init(&c.prog); vec_init(c.func_addr); vec_init(c.native_idx); vec_init(c.cstr_gdata); vec_init(c.cstr_list); vec_init(c.fnfixes); const spl_ir_t *ir = ctx->ir; const spl_type_t *ty = ctx->type; for (usize i = 0; i < ir->funcs.size; i++) { vec_push(c.func_addr, (isize)-1); vec_push(c.native_idx, (isize)-1); } /* 收集 native(nodes 为空IR func = @extern 声明*/ for (usize fid = 1; fid < ir->funcs.size; fid++) { spl_ir_func_t *f = &ir->funcs.data[fid]; if (f->nodes.size == 0) { spl_native_t nat; memset(&nat, 0, sizeof nat); nat.name = f->name ? strdup(f->name) : strdup("?"); nat.idx_of_strtab = 0; nat.impl_fn = NULL; c.native_idx.data[fid] = spl_prog_add_native(&c.prog, &nat) - 1; } } /* 辅助 native:聚合拷贝需vm_memcpy */ if (native_index(&c, "vm_memcpy") < 0) { spl_native_t nat; memset(&nat, 0, sizeof nat); nat.name = strdup("vm_memcpy"); nat.impl_fn = NULL; spl_prog_add_native(&c.prog, &nat); } /* 全局 var/const gdata:value 节点(type.const)求值 → SIR blob */ for (usize gi = 0; gi < ir->gdata.size; gi++) { const spl_ir_node_t *g = &ir->gdata.data[gi]; usize sz = type_size(ty, g->type_const.tid); unsigned char *buf = (unsigned char *)malloc(sz ? sz : 1); gdata_bytes(&c, g, buf); spl_prog_add_data(&c.prog, buf, sz); free(buf); } /* 字符串常gdata(去重);仅 PTR 类型const 才可能是 cstr_lit */ for (usize fid = 1; fid < ir->funcs.size; fid++) { spl_ir_func_t *f = &ir->funcs.data[fid]; for (usize r = 1; r < f->nodes.size; r++) { spl_ir_node_t *n = &f->nodes.data[r]; if (n->kind != SPL_IR_TYPE_CONST || !n->type_const.cstr_lit) continue; spl_type_node_t *ct = tn(ty, under(ty, n->type_const.tid)); if (!ct || ct->kind != SPL_TYPE_PTR) continue; int dup = 0; for (usize i = 0; i < c.cstr_list.size; i++) if (strcmp(c.cstr_list.data[i], n->type_const.cstr_lit) == 0) { dup = 1; break; } if (dup) continue; vec_push(c.cstr_list, n->type_const.cstr_lit); vec_push(c.cstr_gdata, c.prog.gdata.size); spl_prog_add_data(&c.prog, (void *)n->type_const.cstr_lit, strlen(n->type_const.cstr_lit) + 1); } } /* 生成普通函*/ for (usize fid = 1; fid < ir->funcs.size; fid++) { if (ir->funcs.data[fid].nodes.size == 0) continue; c.func_addr.data[fid] = (isize)c.prog.insns.size; gen_func(&c, fid); } /* 回填函数引用(const_fnref 函数地址*/ for (usize i = 0; i < c.fnfixes.size; i++) { fix_t *fx = &c.fnfixes.data[i]; isize addr = (fx->fn && fx->fn < c.func_addr.size) ? c.func_addr.data[fx->fn] : -1; if (addr < 0) { diag(&c, fx->fn, 0, "function reference unresolved"); continue; } c.prog.insns.data[fx->insn_idx].imm = (spl_val_t)addr; } if (!c.err && outpath) spl_prog_store_to_file(outpath, &c.prog); if (c.err) fprintf(stderr, "ir2vm errors=%d\n", c.err); /* 释放 native/func name(spl_prog_drop 会释放) */ int rc = c.err; spl_prog_drop(&c.prog); vec_free(c.func_addr); vec_free(c.native_idx); vec_free(c.cstr_gdata); vec_free(c.cstr_list); vec_free(c.fnfixes); return rc; } void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type) { ctx->ir = ir; ctx->type = type; } void spl_ir2vm_drop(spl_ir2vm_t *ctx) { (void)ctx; } void spl_ir2vm_dump(spl_ir2vm_t *ctx) { (void)ctx; }