diff --git a/project_desc.py b/project_desc.py index 8302ad0..000d8ef 100644 --- a/project_desc.py +++ b/project_desc.py @@ -12,6 +12,7 @@ splc0_part = [ "stage1/spl_type.c", "stage1/spl_sema.c", "stage1/spl_ast2ir.c", + "stage1/spl_ir2vm.c", ] exe = { diff --git a/stage0/spl_mcode.c b/stage0/spl_mcode.c index acb32ce..e14fa9e 100644 --- a/stage0/spl_mcode.c +++ b/stage0/spl_mcode.c @@ -343,6 +343,14 @@ int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) { return 0; } +int spl_prog_add_instr(spl_prog_t *prog, uint8_t opcode, uint8_t type, spl_val_t imm) { + if (!prog) + return 0; + spl_ins_t ins = (spl_ins_t){.opcode = opcode, .type = type, .imm = imm}; + vec_push(prog->insns, ins); + return vec_size(prog->insns); +} + int spl_prog_add_func(spl_prog_t *prog, spl_func_t *func) { if (!prog || !func) return 0; diff --git a/stage0/spl_mcode.h b/stage0/spl_mcode.h index 8ac3525..83a8d3a 100644 --- a/stage0/spl_mcode.h +++ b/stage0/spl_mcode.h @@ -201,6 +201,7 @@ void spl_prog_drop(spl_prog_t *prog); int spl_prog_load_from_file(const char *fname, spl_prog_t *prog); int spl_prog_store_to_file(const char *fname, spl_prog_t *prog); +int spl_prog_add_instr(spl_prog_t *prog, uint8_t opcode, uint8_t type, spl_val_t imm); int spl_prog_add_data(spl_prog_t *prog, void *ptr, usize size); int spl_prog_add_func(spl_prog_t *prog, spl_func_t *func); int spl_prog_add_native(spl_prog_t *prog, spl_native_t *native); diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index f524a0e..454b58c 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -147,11 +147,11 @@ static spl_tok_t *peek_next(parser_t *p) { } static void parse_error(parser_t *p, spl_tok_t *t, const char *msg) { - (void)p; + p->failed = 1; /* 出错即停(上层循环以 !p->failed 提前退出) */ const char *fn = (t && t->fname) ? t->fname : ""; usize line = t ? t->line : 0; usize col = t ? t->col : 0; - LOG_FATAL("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col, + LOG_ERROR("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col, msg); } @@ -223,7 +223,7 @@ static spl_ast_node_ref_t wrap_op_expr(parser_t *p, spl_ast_node_ref_t inner, in /* ================================================================ * 字面量解 * ================================================================ */ -/* 整数字面量:去下划线后按0 解析x/0o/0b/十进制,忽略 0b 特判*/ +/* 整数字面量:去下划线后按 0x/0o/0b/十进制解析 */ static isize parse_int_literal(const spl_tok_t *t) { char buf[128]; usize j = 0; @@ -232,6 +232,11 @@ static isize parse_int_literal(const spl_tok_t *t) { buf[j++] = t->lexeme[i]; } buf[j] = 0; + /* strtoll base 0 不认 0b/0o 前缀:单独处理 */ + if (j >= 3 && buf[0] == '0' && (buf[1] == 'b' || buf[1] == 'B')) + return (isize)strtoll(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); } @@ -637,7 +642,7 @@ static spl_ast_node_ref_vec_t parse_block(parser_t *p) { vec_init(vec); if (!expect(p, TOK_L_BRACE, "expected '{'")) return vec; - while (1) { + while (!p->failed) { spl_tok_t *t = peek(p); if (!t || t->type == TOK_EOF) { parse_error(p, t, "block missing '}'"); @@ -1827,7 +1832,7 @@ void spl_ast_prase(spl_ast_t *ast) { spl_ast_node_ref_vec_t members; vec_init(members); - while (1) { + while (!p.failed) { spl_tok_t *t = peek(&p); if (!t || t->type == TOK_EOF) break; diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index 60ae5ce..305182f 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -3,7 +3,7 @@ * 设计要点 * - 名称解析自包含:局部变类型用自身环境栈;顶层类函数sema root scope 与聚合成员表 * - * 变量落在内存槽(@mem.alloca),写走 @mem.load/store;表达式临时值为 SSA * - 控制流用"块表 + * fixup 补丁":分跳转目标在函数末尾回填为块首指令node ref * - - * 聚合字段访问:读@agg.extract,写字节地址直写"(@mem.offset + @mem.store) * - 枚举= + * 聚合字段访问:读@agg.extract,写字节地址直写"(@mem.offset + @mem.store�?* - 枚举= * agg.construct(enum)([tag, payload?]);match tag 分发 * - defer 按作用域逆序执行(正常退/ ret / * break / continue 全覆盖) */ @@ -95,6 +95,7 @@ static int is_ptr_type(const spl_sema_t *sema, spl_type_id_t tid) { /* ---- 符号解析 ---- */ static spl_type_id_t agg_field_tid_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, isize idx); +static isize gdata_index_by_def(spl_ast2ir_t *a, spl_def_id_t def_id); static spl_type_id_t kw_type(spl_ast2ir_t *a, const char *name) { spl_def_id_t def = 0; @@ -132,7 +133,7 @@ static spl_def_id_t def_for_type(spl_ast2ir_t *a, spl_type_id_t tid) { return fallback; } -/* 判断 agg_def 条目是否为结构字段(SPL_DEF_MEMBER) */ +/* 判断 agg_def 条目是否为结构字段(SPL_DEF_MEMBER�?*/ static int agg_entry_is_field(spl_ast2ir_t *a, const spl_var_def_t *e) { if (!e->def_id) return 0; @@ -140,7 +141,7 @@ static int agg_entry_is_field(spl_ast2ir_t *a, const spl_var_def_t *e) { return ed && ed->kind == SPL_DEF_MEMBER; } -/* 命名空间成员类型(方法/嵌套类型/static var):按名任意 kind */ +/* 命名空间成员类型(方�?嵌套类型/static var):按名任意 kind */ static spl_type_id_t agg_member_type(spl_ast2ir_t *a, spl_type_id_t agg_tid, const char *name) { agg_tid = underlying(a->sema, agg_tid); spl_def_id_t d = def_for_type(a, agg_tid); @@ -154,7 +155,7 @@ static spl_type_id_t agg_member_type(spl_ast2ir_t *a, spl_type_id_t agg_tid, con return 0; } -/* 结构字段序号 = 相对 SPL_DEF_MEMBER 的位置(与 type.agg_field_types 按序对齐) */ +/* 结构字段序号 = 相对 SPL_DEF_MEMBER 的位置(�?type.agg_field_types 按序对齐�?*/ static isize agg_member_index(spl_ast2ir_t *a, spl_type_id_t agg_tid, const char *name) { agg_tid = underlying(a->sema, agg_tid); spl_def_id_t d = def_for_type(a, agg_tid); @@ -187,7 +188,7 @@ static spl_type_id_t agg_field_tid_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, is return 0; } -/* 按字段序号查成员名(agg_def 中第 idx 个 SPL_DEF_MEMBER 条目) */ +/* 按字段序号查成员名(agg_def 中第 idx �?SPL_DEF_MEMBER 条目�?*/ static const char *agg_field_name_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, isize idx) { agg_tid = underlying(a->sema, agg_tid); spl_def_id_t d = def_for_type(a, agg_tid); @@ -237,141 +238,6 @@ static spl_type_id_t agg_field_tid_or_builtin(spl_ast2ir_t *a, spl_type_id_t agg return agg_field_tid_at(a, agg_tid, idx); } -/* ================================================================ - * 类型布局(sizeof / alignof / offsetof * - * ================================================================ */ - -static usize align_up(usize v, usize a) { return (v + a - 1) & ~(a - 1); } - -static usize type_align(const spl_sema_t *sema, spl_type_id_t tid) { - spl_type_node_t *t = tn(sema, underlying(sema, tid)); - if (!t) - return 1; - switch (t->kind) { - case SPL_TYPE_VOID: - return 1; - 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: - return sizeof(usize); - case SPL_TYPE_SLICE: - case SPL_TYPE_RANGE: - return sizeof(usize); - case SPL_TYPE_ARRAY: - return type_align(sema, t->array_type.element); - case SPL_TYPE_STRUCT: { - usize a = 1; - for (usize i = 0; i < t->agg_field_types.size; i++) { - usize fa = type_align(sema, t->agg_field_types.data[i]); - if (fa > a) - a = fa; - } - return a; - } - case SPL_TYPE_UNION: { - usize a = 1; - for (usize i = 0; i < t->agg_field_types.size; i++) { - usize fa = type_align(sema, t->agg_field_types.data[i]); - if (fa > a) - a = fa; - } - return a; - } - case SPL_TYPE_ENUM: - return sizeof(usize); - default: - return 1; - } -} - -static usize type_size(const spl_sema_t *sema, spl_type_id_t tid) { - spl_type_node_t *t = tn(sema, underlying(sema, tid)); - if (!t) - return 0; - switch (t->kind) { - case SPL_TYPE_VOID: - return 0; - 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: - return sizeof(usize); - case SPL_TYPE_SLICE: - return sizeof(usize) * 2; - case SPL_TYPE_RANGE: - return sizeof(usize) * 2; - case SPL_TYPE_ARRAY: - return t->array_type.len * type_size(sema, 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(sema, t->agg_field_types.data[i]); - sz = align_up(sz, fa); - sz += type_size(sema, t->agg_field_types.data[i]); - } - return sz; - } - case SPL_TYPE_UNION: { - usize sz = 0; - for (usize i = 0; i < t->agg_field_types.size; i++) { - usize fs = type_size(sema, t->agg_field_types.data[i]); - if (fs > sz) - sz = fs; - } - return sz; - } - case SPL_TYPE_ENUM: { - usize payload = 0; - for (usize i = 0; i < t->enum_type.variants.size; i++) { - spl_type_id_t v = underlying(sema, t->enum_type.variants.data[i]); - if (v == underlying(sema, tid)) - continue; - usize vs = type_size(sema, v); - if (vs > payload) - payload = vs; - } - return sizeof(usize) + payload; - } - default: - return 0; - } -} - -/* 聚合字段字节偏移(struct 顺序对齐;union/enum 偏移 0;slice/range 内置字段*/ -static usize type_field_offset(const spl_sema_t *sema, spl_type_id_t agg_tid, isize idx) { - spl_type_node_t *t = tn(sema, underlying(sema, agg_tid)); - if (!t) - return 0; - if (t->kind == SPL_TYPE_SLICE || t->kind == SPL_TYPE_RANGE) - return (usize)idx * sizeof(usize); - if ((usize)idx >= t->agg_field_types.size) - return 0; - switch (t->kind) { - case SPL_TYPE_STRUCT: { - usize off = 0; - for (isize i = 0; i < idx; i++) { - usize fa = type_align(sema, t->agg_field_types.data[i]); - off = align_up(off, fa); - off += type_size(sema, t->agg_field_types.data[i]); - } - return align_up(off, type_align(sema, t->agg_field_types.data[idx])); - } - case SPL_TYPE_UNION: - case SPL_TYPE_ENUM: - default: - return 0; - } -} - /* ================================================================ * IR 发射(per-function 上下文) * ================================================================ */ @@ -412,6 +278,7 @@ typedef VEC(ir_loop_t) ir_loop_vec_t; typedef struct { spl_ir_func_ref_t fn; + spl_ast2ir_t *a; spl_type_id_t ret_tid; spl_type_id_t ns_tid; /* 所在聚合类型(方法命名空间);顶层0 */ ir_env_stack_t env; @@ -425,8 +292,9 @@ typedef struct { int err; } fnctx_t; -static void fc_init(fnctx_t *fc, spl_ir_func_ref_t fn, spl_type_id_t ret) { +static void fc_init(fnctx_t *fc, spl_ast2ir_t *a, spl_ir_func_ref_t fn, spl_type_id_t ret) { memset(fc, 0, sizeof *fc); + fc->a = a; fc->fn = fn; fc->ret_tid = ret; vec_init(fc->env); @@ -436,8 +304,9 @@ static void fc_init(fnctx_t *fc, spl_ir_func_ref_t fn, spl_type_id_t ret) { vec_init(fc->types); } -static void fc_init_ns(fnctx_t *fc, spl_ir_func_ref_t fn, spl_type_id_t ret, spl_type_id_t ns) { - fc_init(fc, fn, ret); +static void fc_init_ns(fnctx_t *fc, spl_ast2ir_t *a, spl_ir_func_ref_t fn, spl_type_id_t ret, + spl_type_id_t ns) { + fc_init(fc, a, fn, ret); fc->ns_tid = ns; } @@ -664,6 +533,34 @@ static spl_ir_node_ref_t emit_offset(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t return n; } +/* 字段地址:mem.field_ptr(agg_tid, agg, idx) → *field_type。布局偏移由 ir2vm 算,ast2ir 不算。 */ +static spl_ir_node_ref_t emit_field(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t agg_tid, + spl_ir_node_ref_t ptr, isize fidx) { + spl_type_id_t fty = agg_field_tid_or_builtin(a, agg_tid, fidx); + spl_ir_node_ref_t n = emit_node(a, fc); + spl_ir_node_t *e = enode(a, fc, n); + e->kind = SPL_IR_MEM_FIELD_PTR; + e->mem_field_ptr.tid = underlying(a->sema, agg_tid); + e->mem_field_ptr.agg = ptr; + e->mem_field_ptr.field_idx = (usize)fidx; + spl_type_id_t pt = spl_type_ptr((spl_type_t *)&a->sema->type, fty); + set_ntype(fc, n, pt); + return n; +} + +/* 全局静态数据地址:mem.global_alloc(tid, gdata_idx) �?*tid */ +static spl_ir_node_ref_t emit_global_alloc(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, + usize gdata_idx) { + spl_ir_node_ref_t n = emit_node(a, fc); + spl_ir_node_t *e = enode(a, fc, n); + e->kind = SPL_IR_MEM_GLOBAL_ALLOC; + e->mem_global_alloc.tid = tid; + e->mem_global_alloc.const_node = gdata_idx; + spl_type_id_t pt = spl_type_ptr((spl_type_t *)&a->sema->type, tid); + set_ntype(fc, n, pt); + return n; +} + static spl_ir_node_ref_t emit_agg_construct(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); @@ -687,6 +584,7 @@ static spl_ir_node_ref_t emit_agg_extract(spl_ast2ir_t *a, fnctx_t *fc, spl_type spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_AGG_EXTRACT; e->agg_extract.tid = tid; + e->agg_extract.field_tid = field_tid; e->agg_extract.field_idx = fidx; e->agg_extract.val = val; set_ntype(fc, n, field_tid); @@ -767,7 +665,7 @@ static ir_env_t *env_find(fnctx_t *fc, const char *name) { return NULL; } -/* def_id 优先定位(sema 已作用域解析,绕开同名遮蔽歧义);无 def_id 时兜底名字 */ +/* def_id 优先定位(sema 已作用域解析,绕开同名遮蔽歧义);�?def_id 时兜底名�?*/ static ir_env_t *env_find_def(fnctx_t *fc, spl_def_id_t def_id, const char *name) { if (def_id) { for (usize i = fc->env.size; i > 0; i--) { @@ -842,6 +740,17 @@ static spl_ir_node_ref_t enum_tag_of(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t return emit_agg_extract(a, fc, enum_tid, enum_tag_tid(a), 0, val); } +/* tid 是否�?enum */ +static int is_enum_expand(spl_ast2ir_t *a, spl_type_id_t tid, spl_type_id_t *out_enum) { + spl_type_node_t *t = tn(a->sema, underlying(a->sema, tid)); + if (t && t->kind == SPL_TYPE_ENUM) { + if (out_enum) + *out_enum = underlying(a->sema, tid); + return 1; + } + return 0; +} + /* 表达式当作类型引用解析(a / a.b.c,用于枚举变嵌套类型路径*/ static spl_type_id_t type_of_type_ref(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t bref) { spl_ast_node_t *n = node_at(a->sema, bref); @@ -956,13 +865,13 @@ static spl_type_id_t resolve_type_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod spl_ast_node_t *n = node_at(a->sema, ref); if (!n) return 0; - /* 首选 sema 注解:resolved_def_id → def → 类型(聚合/别名/命名类型) */ + /* 首�?sema 注解:resolved_def_id �?def �?类型(聚�?别名/命名类型�?*/ if (n->resolved_def_id) { spl_def_node_t *d = def_at(a->sema, n->resolved_def_id); if (d && d->type_id) return d->type_id; } - /* 兜底:组合/内置类型(sema 不为其建 def 的 *T、[]T、fn(...)、关键字、别名到组合) */ + /* 兜底:组�?内置类型(sema 不为其建 def �?*T、[]T、fn(...)、关键字、别名到组合�?*/ spl_type_id_t base = 0; switch (n->type_expr.kind) { case SPL_AST_BASE_TYPE_PATH: @@ -989,7 +898,7 @@ static spl_type_id_t resolve_type_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: case SPL_AST_TYPE_ENUM: - /* 内联聚合不应走到这里(sema 已注解其 def);防御性报错 */ + /* 内联聚合不应走到这里(sema 已注解其 def);防御性报�?*/ diag(a, fc, ref, "inline aggregate not annotated by sema"); return 0; default: @@ -1110,16 +1019,7 @@ static spl_ast_node_ref_t field_chain_base(spl_ast2ir_t *a, spl_ast_node_t *pf, return bref; } -/* 指针按字节偏移(mem.offset u8 为单位即字节*/ -static spl_ir_node_ref_t ptr_add_bytes(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_node_ref_t addr, - usize bytes) { - if (!bytes || !addr) - return addr; - spl_ir_node_ref_t c = const_int(a, fc, kw_type(a, "usize"), bytes); - return emit_offset(a, fc, kw_type(a, "u8"), addr, c); -} - -/* 字段链的存储地址(root.a.b 地址 + 字段类型*/ +/* 字段链的存储地址(root.a.b 地址 + 字段类型�?*/ static spl_ir_node_ref_t lower_field_address(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t bref, spl_type_id_t *out_tid) { spl_ast_node_t *n = node_at(a->sema, bref); @@ -1131,12 +1031,34 @@ static spl_ir_node_ref_t lower_field_address(spl_ast2ir_t *a, fnctx_t *fc, spl_a const char *names[MAX_FIELD_CHAIN]; int nf = 0; spl_ast_node_ref_t root_ref = field_chain_base(a, pf, names, &nf); + /* 类型命名空间基址:Foo.counter(全局 var/const �?lvalue = �?gdata 地址�?*/ + spl_type_id_t ns = type_of_type_ref(a, fc, root_ref); + if (ns && nf == 1) { + spl_def_id_t gdef = def_for_type(a, ns); + spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL; + for (usize i = 0; gd && i < gd->agg_def.size; i++) { + spl_var_def_t *e = &gd->agg_def.data[i]; + if (e->name && strcmp(e->name, names[0]) == 0 && e->def_id) { + spl_def_node_t *ed = def_at(a->sema, e->def_id); + if (ed && ed->kind == SPL_DEF_VAR) { + isize gi = gdata_index_by_def(a, e->def_id); + if (gi >= 0) { + *out_tid = e->type_id; + return emit_global_alloc(a, fc, e->type_id, (usize)gi); + } + } + break; + } + } + return 0; + } spl_type_id_t cur_tid = 0; spl_ir_node_ref_t addr = lower_lvalue(a, fc, root_ref, &cur_tid); spl_type_node_t *curt = tn(a->sema, underlying(a->sema, cur_tid)); if (curt && curt->kind == SPL_TYPE_PTR) { cur_tid = underlying(a->sema, curt->ptr_pointee); - addr = emit_load(a, fc, cur_tid, addr); + spl_type_id_t pty = spl_type_ptr((spl_type_t *)&a->sema->type, cur_tid); + addr = emit_load(a, fc, pty, addr); } if (!addr || !cur_tid) return 0; @@ -1148,16 +1070,15 @@ static spl_ir_node_ref_t lower_field_address(spl_ast2ir_t *a, fnctx_t *fc, spl_a isize idx = agg_index_or_builtin(a, cur_tid, names[i]); if (idx < 0) return 0; - usize off = type_field_offset(a->sema, cur_tid, idx); spl_type_id_t ft = agg_field_tid_or_builtin(a, cur_tid, idx); - if (off) - addr = ptr_add_bytes(a, fc, addr, off); + addr = emit_field(a, fc, cur_tid, addr, idx); cur_tid = ft; if (i > 0) { spl_type_node_t *ftt = tn(a->sema, underlying(a->sema, cur_tid)); if (ftt && ftt->kind == SPL_TYPE_PTR) { cur_tid = underlying(a->sema, ftt->ptr_pointee); - addr = emit_load(a, fc, cur_tid, addr); + spl_type_id_t pty = spl_type_ptr((spl_type_t *)&a->sema->type, cur_tid); + addr = emit_load(a, fc, pty, addr); } } } @@ -1244,8 +1165,42 @@ static spl_ir_node_ref_t lower_lvalue(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node *out_tid = it->tid; return it->slot; } - if (it) + if (it) { diag(a, fc, ref, "not an addressable variable"); + return 0; + } + /* 顶层 / 命名空间全局 var:lvalue = 全局分配地址 */ + spl_def_id_t def = pn->resolved_def_id; + if (!def) + def = root_lookup(a, pn->primary_expr.ident); + if (def) { + spl_def_node_t *d = def_at(a->sema, def); + if (d && d->kind == SPL_DEF_VAR) { + isize gi = gdata_index_by_def(a, def); + if (gi >= 0) { + *out_tid = d->type_id; + return emit_global_alloc(a, fc, *out_tid, (usize)gi); + } + } + if (fc->ns_tid) { + spl_def_id_t gdef = def_for_type(a, fc->ns_tid); + spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL; + for (usize i = 0; gd && i < gd->agg_def.size; i++) { + spl_var_def_t *e = &gd->agg_def.data[i]; + if (e->name && strcmp(e->name, pn->primary_expr.ident) == 0 && e->def_id) { + spl_def_node_t *ed = def_at(a->sema, e->def_id); + if (ed && ed->kind == SPL_DEF_VAR) { + isize gi = gdata_index_by_def(a, e->def_id); + if (gi >= 0) { + *out_tid = e->type_id; + return emit_global_alloc(a, fc, e->type_id, (usize)gi); + } + } + break; + } + } + } + } return 0; } if (pn && pn->primary_expr.kind == SPL_AST_EXPR_EXPR) @@ -1307,11 +1262,36 @@ static spl_ir_node_ref_t lower_ident(spl_ast2ir_t *a, fnctx_t *fc, const char *n if (def) { spl_def_node_t *d = def_at(a->sema, def); if (d && - (d->kind == SPL_DEF_AGG || d->kind == SPL_DEF_ALIAS || d->kind == SPL_DEF_DISTINCT)) - diag(a, fc, ref, "type name used as value (aggregate member not supported)"); - else - diag(a, fc, ref, "undefined identifier"); + (d->kind == SPL_DEF_AGG || d->kind == SPL_DEF_ALIAS || d->kind == SPL_DEF_DISTINCT)) { + diag(a, fc, ref, "type name used as value"); + return 0; + } + if (d && d->kind == SPL_DEF_VAR) { + isize gi = gdata_index_by_def(a, def); + if (gi >= 0) + return emit_load(a, fc, d->type_id, + emit_global_alloc(a, fc, d->type_id, (usize)gi)); + } + diag(a, fc, ref, "undefined identifier"); } else { + /* 命名空间内裸名:fc->ns_tid 聚合成员 static var/const */ + if (fc->ns_tid) { + spl_def_id_t gdef = def_for_type(a, fc->ns_tid); + spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL; + for (usize i = 0; gd && i < gd->agg_def.size; i++) { + spl_var_def_t *e = &gd->agg_def.data[i]; + if (e->name && strcmp(e->name, name) == 0 && e->def_id) { + spl_def_node_t *ed = def_at(a->sema, e->def_id); + if (ed && ed->kind == SPL_DEF_VAR) { + isize gi = gdata_index_by_def(a, e->def_id); + if (gi >= 0) + return emit_load(a, fc, e->type_id, + emit_global_alloc(a, fc, e->type_id, (usize)gi)); + } + break; + } + } + } diag(a, fc, ref, "undefined identifier"); } return 0; @@ -1413,15 +1393,20 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod elem = kw_type(a, "i32"); spl_type_id_t arr = spl_type_array((spl_type_t *)&a->sema->type, elem, (usize)pn->primary_expr.array_lit_expr.integer); - spl_ir_node_ref_t agg = emit_agg_construct(a, fc, arr); + VEC(spl_ir_node_ref_t) vals; + vec_init(vals); for (usize i = 0; i < pn->primary_expr.array_lit_expr.expr_list.size; i++) { fc->hint = elem; spl_ir_node_ref_t v = lower_expr(a, fc, pn->primary_expr.array_lit_expr.expr_list.data[i]); fc->hint = 0; v = coerce_to(a, fc, v, node_type(fc, v), elem); - agg_construct_add(a, fc, agg, v); + vec_push(vals, v); } + spl_ir_node_ref_t agg = emit_agg_construct(a, fc, arr); + for (usize i = 0; i < vals.size; i++) + agg_construct_add(a, fc, agg, vals.data[i]); + vec_free(vals); return agg; } case SPL_AST_ARGGREGATE_INIT: { @@ -1443,7 +1428,8 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod diag(a, fc, 0, "anonymous aggregate literal without context type"); return 0; } - spl_ir_node_ref_t agg = emit_agg_construct(a, fc, hint_t); + VEC(spl_ir_node_ref_t) vals; + vec_init(vals); for (usize j = 0; j < pn->primary_expr.aggregate_init.expr.size; j++) { spl_ast_node_t *item = node_at(a->sema, pn->primary_expr.aggregate_init.expr.data[j]); @@ -1456,17 +1442,34 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod } spl_type_id_t ft = agg_field_tid_or_builtin(a, hint_t, fidx); spl_ir_node_ref_t v = lower_expr(a, fc, item->aggregate_init_item.expr); + /* 字段是指针、值是聚合 lvalue:自动取地址�?left = expr 语义�?*/ + spl_type_node_t *fld_t = ft ? tn(a->sema, ft) : NULL; + spl_type_node_t *v_t = tn(a->sema, underlying(a->sema, node_type(fc, v))); + if (fld_t && fld_t->kind == SPL_TYPE_PTR && v_t && + (v_t->kind == SPL_TYPE_STRUCT || v_t->kind == SPL_TYPE_UNION || + v_t->kind == SPL_TYPE_ENUM)) { + spl_type_id_t lt = 0; + spl_ir_node_ref_t addr = + lower_lvalue(a, fc, item->aggregate_init_item.expr, <); + if (addr) + v = addr; + } if (ft) v = coerce_to(a, fc, v, node_type(fc, v), ft); - agg_construct_add(a, fc, agg, v); + vec_push(vals, v); } + spl_ir_node_ref_t agg = emit_agg_construct(a, fc, hint_t); + for (usize i = 0; i < vals.size; i++) + agg_construct_add(a, fc, agg, vals.data[i]); + vec_free(vals); return agg; } spl_type_node_t *tt = tn(a->sema, tid); if (!tt) return 0; if (tt->kind == SPL_TYPE_ENUM) { - spl_ir_node_ref_t agg = emit_agg_construct(a, fc, tid); + VEC(spl_ir_node_ref_t) vals; + vec_init(vals); for (usize j = 0; j < pn->primary_expr.aggregate_init.expr.size; j++) { spl_ast_node_t *item = node_at(a->sema, pn->primary_expr.aggregate_init.expr.data[j]); @@ -1477,7 +1480,7 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod diag(a, fc, 0, "unknown enum variant"); continue; } - agg_construct_add(a, fc, agg, const_int(a, fc, enum_tag_tid(a), (usize)vidx)); + vec_push(vals, const_int(a, fc, enum_tag_tid(a), (usize)vidx)); if (item->aggregate_init_item.expr) { spl_type_id_t pt = enum_payload_tid(a, tid, vidx); fc->hint = pt; @@ -1485,17 +1488,23 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod fc->hint = 0; if (pt) pv = coerce_to(a, fc, pv, node_type(fc, pv), pt); - agg_construct_add(a, fc, agg, pv); + vec_push(vals, pv); } } + spl_ir_node_ref_t agg = emit_agg_construct(a, fc, tid); + for (usize i = 0; i < vals.size; i++) + agg_construct_add(a, fc, agg, vals.data[i]); + vec_free(vals); return agg; } if (tt->kind != SPL_TYPE_STRUCT) { diag(a, fc, 0, "aggregate literal target is not a struct"); return 0; } - spl_ir_node_ref_t agg = emit_agg_construct(a, fc, tid); + spl_ir_node_ref_t agg = 0; usize nfields = tt->agg_field_types.size; + VEC(spl_ir_node_ref_t) vals; + vec_init(vals); for (usize i = 0; i < nfields; i++) { const char *fname = agg_field_name_at(a, tid, (isize)i); spl_ast_node_ref_t found = 0; @@ -1509,16 +1518,31 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod } } if (!found) { - agg_construct_add(a, fc, agg, const_int(a, fc, tt->agg_field_types.data[i], 0)); + vec_push(vals, const_int(a, fc, tt->agg_field_types.data[i], 0)); continue; } spl_ast_node_t *item = node_at(a->sema, found); fc->hint = tt->agg_field_types.data[i]; spl_ir_node_ref_t v = lower_expr(a, fc, item->aggregate_init_item.expr); fc->hint = 0; + /* 字段是指针、值是聚合 lvalue:自动取地址�?left = expr 语义�?*/ + spl_type_node_t *fld_t = tn(a->sema, tt->agg_field_types.data[i]); + spl_type_node_t *v_t = tn(a->sema, underlying(a->sema, node_type(fc, v))); + if (fld_t && fld_t->kind == SPL_TYPE_PTR && v_t && + (v_t->kind == SPL_TYPE_STRUCT || v_t->kind == SPL_TYPE_UNION || + v_t->kind == SPL_TYPE_ENUM)) { + spl_type_id_t lt = 0; + spl_ir_node_ref_t addr = lower_lvalue(a, fc, item->aggregate_init_item.expr, <); + if (addr) + v = addr; + } v = coerce_to(a, fc, v, node_type(fc, v), tt->agg_field_types.data[i]); - agg_construct_add(a, fc, agg, v); + vec_push(vals, v); } + agg = emit_agg_construct(a, fc, tid); + for (usize i = 0; i < vals.size; i++) + agg_construct_add(a, fc, agg, vals.data[i]); + vec_free(vals); return agg; } case SPL_AST_BUILTIN_EXPR: { @@ -1695,7 +1719,12 @@ static int resolve_callee(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t base, vt = underlying(a->sema, vtt->ptr_pointee); vtt = tn(a->sema, vt); } - spl_type_id_t mt = vtt ? agg_member_type(a, vt, fname) : 0; + /* enum 方法:在原 enum def 上查找 */ + spl_type_id_t lookup = vt; + spl_type_id_t e0 = 0; + if (vtt && is_enum_expand(a, vt, &e0)) + lookup = e0; + spl_type_id_t mt = vtt ? agg_member_type(a, lookup, fname) : 0; spl_type_node_t *mtn = mt ? tn(a->sema, mt) : NULL; if (mt && mtn && mtn->kind == SPL_TYPE_FN) { out->fn_tid = mt; @@ -1730,6 +1759,22 @@ static spl_ir_node_ref_t lower_field(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ if (vidx >= 0) return enum_variant_value(a, fc, ttr, vidx); } + /* 聚合命名空间成员:static var/const �?全局数据 */ + spl_def_id_t gdef = def_for_type(a, ttr); + spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL; + for (usize i = 0; gd && i < gd->agg_def.size; i++) { + spl_var_def_t *e = &gd->agg_def.data[i]; + if (e->name && strcmp(e->name, fname) == 0 && e->def_id) { + spl_def_node_t *ed = def_at(a->sema, e->def_id); + if (ed && ed->kind == SPL_DEF_VAR) { + isize gi = gdata_index_by_def(a, e->def_id); + if (gi >= 0) + return emit_load(a, fc, e->type_id, + emit_global_alloc(a, fc, e->type_id, (usize)gi)); + } + break; + } + } diag(a, fc, 0, "aggregate member is not a value"); return 0; } @@ -1962,12 +2007,13 @@ static spl_ir_node_ref_t lower_binary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node spl_ir_node_ref_t r = lower_expr(a, fc, rr); spl_type_id_t lt = underlying(a->sema, node_type(fc, l)); spl_type_id_t rt = underlying(a->sema, node_type(fc, r)); - spl_type_node_t *ltt = tn(a->sema, lt); - spl_type_node_t *rtt = tn(a->sema, rt); - if (ltt && ltt->kind == SPL_TYPE_ENUM && rtt && rtt->kind == SPL_TYPE_ENUM) { + spl_type_id_t le = 0, re = 0; + int is_l_enum = is_enum_expand(a, lt, &le); + int is_r_enum = is_enum_expand(a, rt, &re); + if (is_l_enum && is_r_enum) { spl_type_id_t tag_t = enum_tag_tid(a); - l = enum_tag_of(a, fc, lt, l); - r = enum_tag_of(a, fc, rt, r); + l = enum_tag_of(a, fc, le, l); + r = enum_tag_of(a, fc, re, r); lt = tag_t; rt = tag_t; } @@ -2038,12 +2084,11 @@ static spl_ir_node_ref_t lower_range_value(spl_ast2ir_t *a, fnctx_t *fc, spl_ast spl_ir_node_ref_t b = lower_expr(a, fc, n->expr.op_expr.left); spl_type_id_t et = underlying(a->sema, node_type(fc, b)); spl_type_id_t range_t = spl_type_range((spl_type_t *)&a->sema->type, et); + spl_ir_node_ref_t e = + n->expr.op_expr.right ? lower_expr(a, fc, n->expr.op_expr.right) : const_int(a, fc, et, 0); spl_ir_node_ref_t r = emit_agg_construct(a, fc, range_t); agg_construct_add(a, fc, r, b); - if (n->expr.op_expr.right) - agg_construct_add(a, fc, r, lower_expr(a, fc, n->expr.op_expr.right)); - else - agg_construct_add(a, fc, r, const_int(a, fc, et, 0)); + agg_construct_add(a, fc, r, e); return r; } @@ -2116,16 +2161,53 @@ static spl_ir_node_ref_t lower_assign(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node spl_ast_node_t *pn = node_at(a->sema, ln->expr.op_expr.left); if (pn && pn->primary_expr.kind == SPL_AST_IDENT) { ir_env_t *it = env_find_def(fc, pn->resolved_def_id, pn->primary_expr.ident); - if (!it || !it->slot) { + spl_type_id_t lt = 0; + spl_ir_node_ref_t target = 0; + if (it && it->slot) { + lt = it->tid; + target = it->slot; + } else { + /* 全局 var(顶�?/ 命名空间裸名�?*/ + spl_def_id_t def = pn->resolved_def_id; + if (!def) + def = root_lookup(a, pn->primary_expr.ident); + if (def) { + spl_def_node_t *d = def_at(a->sema, def); + isize gi0 = (d && d->kind == SPL_DEF_VAR) ? gdata_index_by_def(a, def) : -1; + if (gi0 >= 0) { + lt = d->type_id; + target = emit_global_alloc(a, fc, lt, (usize)gi0); + } else if (fc->ns_tid) { + spl_def_id_t gdef = def_for_type(a, fc->ns_tid); + spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL; + for (usize i = 0; gd && i < gd->agg_def.size; i++) { + spl_var_def_t *e = &gd->agg_def.data[i]; + if (e->name && strcmp(e->name, pn->primary_expr.ident) == 0 && + e->def_id) { + spl_def_node_t *ed = def_at(a->sema, e->def_id); + if (ed && ed->kind == SPL_DEF_VAR) { + isize gi = gdata_index_by_def(a, e->def_id); + if (gi >= 0) { + lt = e->type_id; + target = emit_global_alloc(a, fc, e->type_id, (usize)gi); + } + } + break; + } + } + } + } + } + if (!target || !lt) { diag(a, fc, lr, "assignment target not writable"); return 0; } - spl_ir_node_ref_t cur = compound ? emit_load(a, fc, it->tid, it->slot) : 0; + spl_ir_node_ref_t cur = compound ? emit_load(a, fc, lt, target) : 0; spl_ir_node_ref_t v = lower_expr(a, fc, rr); if (compound) - v = lower_compound_op(a, fc, n->expr.op, it->tid, cur, v); - v = coerce_to(a, fc, v, node_type(fc, v), it->tid); - emit_store(a, fc, it->tid, it->slot, v); + v = lower_compound_op(a, fc, n->expr.op, lt, cur, v); + v = coerce_to(a, fc, v, node_type(fc, v), lt); + emit_store(a, fc, lt, target, v); return v; } } @@ -2434,7 +2516,10 @@ static void lower_for(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { for (usize i = 0; i < nseq; i++) { if (!seqs[i].len) continue; - spl_ir_node_ref_t l = coerce_to(a, fc, seqs[i].len, node_type(fc, seqs[i].len), iszt); + spl_ir_node_ref_t lenv = seqs[i].len; + if (seqs[i].kind == FOR_SLICE) + lenv = emit_load(a, fc, kw_type(a, "usize"), seqs[i].len); + spl_ir_node_ref_t l = coerce_to(a, fc, lenv, node_type(fc, lenv), iszt); if (!m) { m = l; } else { @@ -2472,7 +2557,12 @@ static void lower_for(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { v = emit_arith(a, fc, SPL_IR_ARITH_ADD, s->elem_tid, bg, coerce_to(a, fc, cur, iszt, s->elem_tid)); } else { - spl_ir_node_ref_t addr = emit_offset(a, fc, s->elem_tid, s->base_slot, cur); + spl_ir_node_ref_t base = s->base_slot; + if (s->kind == FOR_SLICE) { + spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, s->elem_tid); + base = emit_load(a, fc, ep, s->base_slot); + } + spl_ir_node_ref_t addr = emit_offset(a, fc, s->elem_tid, base, cur); v = emit_load(a, fc, s->elem_tid, addr); } ir_env_t *it = env_find(fc, id_data[i]); @@ -2575,6 +2665,7 @@ static void lower_match(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { spl_type_id_t pt = enum_payload_tid(a, st, vidx); if (pt) { spl_ir_node_ref_t sv = emit_load(a, fc, st, subj_slot); + /* enum 布局 = tag(0) + payload(8):直接提�?payload,field_tid = 变体具体类型 */ spl_ir_node_ref_t pv = emit_agg_extract(a, fc, st, pt, 1, sv); spl_ir_node_ref_t bslot = emit_alloca(a, fc, pt); emit_store(a, fc, pt, bslot, pv); @@ -2693,7 +2784,7 @@ static void lower_stmt(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { * ================================================================ */ static spl_ir_func_ref_t a2ir_fn_of(spl_ast2ir_t *a, spl_type_id_t fn_tid) { - /* 懒扫描:IR func 已记录 fn_tid(spl_type_fn 不去重,fn_tid 唯一) */ + /* 懒扫描:IR func 已记�?fn_tid(spl_type_fn 不去重,fn_tid 唯一�?*/ for (usize i = 1; i < a->ir.funcs.size; i++) { if (a->ir.funcs.data[i].fn_tid == fn_tid) return i; @@ -2709,7 +2800,7 @@ static void lower_func_body(spl_ast2ir_t *a, spl_ir_func_ref_t fid, spl_type_id_ spl_type_node_t *ft = tn(a->sema, fn_tid); spl_type_id_t ret = (ft && ft->kind == SPL_TYPE_FN) ? ft->fn_type.ret : 0; fnctx_t fc; - fc_init_ns(&fc, fid, ret, ns_tid); + fc_init_ns(&fc, a, fid, ret, ns_tid); spl_ast_node_ref_vec_t *pl = &fn->fn_decl.param_list; usize nparams = (ft && ft->kind == SPL_TYPE_FN) ? ft->fn_type.params.size : 0; env_push(&fc); @@ -2774,9 +2865,136 @@ void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) { for (usize i = 0; i < ast2ir->owned_names.size; i++) free(ast2ir->owned_names.data[i]); vec_free(ast2ir->owned_names); + vec_free(ast2ir->gdata_ref); spl_ir_drop(&ast2ir->ir); } +/* ================================================================ + * 全局数据(聚合类型下 / 顶层�?var、const�? + * ================================================================ */ + +/* 常量折叠:仅支持字面量(int/char/float/string/null)与一元负�?*/ +typedef struct { + int const_init; + isize int_v; + double float_v; + const char *cstr_v; +} gfold_t; + +static void fold_const_init(spl_ast2ir_t *a, spl_ast_node_ref_t ref, gfold_t *g) { + spl_ast_node_t *n = node_at(a->sema, ref); + if (!n || n->kind != SPL_AST_EXPR) + return; + if (n->expr.op == SPL_AST_PRIMARY_EXPR) { + spl_ast_node_t *pn = node_at(a->sema, n->expr.op_expr.left); + if (!pn) + return; + switch (pn->primary_expr.kind) { + case SPL_AST_INTEGER: + g->const_init = 1; + g->int_v = pn->primary_expr.integer_expr; + return; + case SPL_AST_CHAR_LIT: + g->const_init = 1; + g->int_v = (isize)(unsigned char)pn->primary_expr.char_lit_expr; + return; + case SPL_AST_FLOAT: + g->const_init = 1; + g->float_v = pn->primary_expr.float_expr; + return; + case SPL_AST_NULL: + g->const_init = 1; + g->int_v = 0; + return; + case SPL_AST_STRING_LIT: + g->const_init = 1; + g->cstr_v = pn->primary_expr.string_lit_expr; + return; + default: + return; + } + } + if (n->expr.op == SPL_AST_PREFIX_EXPR) { + spl_ast_node_t *pp = node_at(a->sema, n->expr.op_expr.left); + if (pp && pp->prefix_expr.kind == SPL_AST_MINUS_EXPR) { + fold_const_init(a, pp->prefix_expr.postfix_expr, g); + if (g->const_init) + g->int_v = -g->int_v; + } + } +} + +static void collect_gdata_list(spl_ast2ir_t *a, spl_ast_node_ref_vec_t *members) { + for (usize i = 0; i < members->size; i++) { + spl_ast_node_t *m = node_at(a->sema, members->data[i]); + if (!m) + continue; + const char *mname = NULL; + spl_ast_node_ref_t iexpr = 0; + if (m->kind == SPL_AST_VAR_DECL) { + mname = m->var_decl.name; + iexpr = m->var_decl.expr; + } else if (m->kind == SPL_AST_CONST_DECL) { + mname = m->const_decl.name; + iexpr = m->const_decl.expr; + } else { + continue; + } + if (!mname || !m->resolved_def_id) + continue; + spl_def_node_t *d = def_at(a->sema, m->resolved_def_id); + if (!d) + continue; + gfold_t g; + memset(&g, 0, sizeof g); + spl_type_id_t g_tid = d->type_id; + if (iexpr) + fold_const_init(a, iexpr, &g); + /* 全局 value = type.const 节点(标量折叠值;聚合/无 init 零) */ + spl_ir_node_t v; + memset(&v, 0, sizeof v); + v.kind = SPL_IR_TYPE_CONST; + v.type_const.tid = g_tid; + spl_type_node_t *gt = tn(a->sema, underlying(a->sema, g_tid)); + if (g.const_init && gt && gt->kind == SPL_TYPE_INT) + v.type_const.int_lit = (usize)g.int_v; + else if (g.const_init && gt && gt->kind == SPL_TYPE_FLOAT) + v.type_const.float_lit = g.float_v; + else + v.type_const.int_lit = 0; + vec_push(a->ir.gdata, v); + spl_ast2ir_gref_t gr = {m->resolved_def_id, a->ir.gdata.size - 1}; + vec_push(a->gdata_ref, gr); + } +} + +static void collect_gdata(spl_ast2ir_t *a) { + spl_ast_node_t *root = node_at(a->sema, a->sema->ast->root); + if (!root || root->kind != SPL_AST_CONTAINER_ITEM) + return; + collect_gdata_list(a, &root->container_item.members); + for (usize i = 0; i < root->container_item.members.size; i++) { + spl_ast_node_ref_t mref = root->container_item.members.data[i]; + spl_ast_node_t *m = node_at(a->sema, mref); + if (!m || m->kind != SPL_AST_TYPE_DECL) + continue; + spl_ast_node_t *te = node_at(a->sema, m->type_decl.type_expr); + if (!te || + (te->type_expr.kind != SPL_AST_TYPE_STRUCT && + te->type_expr.kind != SPL_AST_TYPE_UNION && te->type_expr.kind != SPL_AST_TYPE_ENUM)) + continue; + collect_gdata_list(a, &te->type_expr.aggregate_list); + } +} + +/* def_id �?gdata value 节点索引;未命中返回 -1 */ +static isize gdata_index_by_def(spl_ast2ir_t *a, spl_def_id_t def_id) { + for (usize i = 0; i < a->gdata_ref.size; i++) + if (a->gdata_ref.data[i].def_id == def_id) + return (isize)a->gdata_ref.data[i].gdata_idx; + return -1; +} + /* ================================================================ * 预登记:为所有函数(顶层 + 聚合方法)建 IR func * ================================================================ */ @@ -2838,6 +3056,8 @@ void spl_ast2ir_run(spl_ast2ir_t *a) { spl_ast_node_t *root = node_at(a->sema, a->sema->ast->root); if (!root || root->kind != SPL_AST_CONTAINER_ITEM) return; + vec_init(a->gdata_ref); + collect_gdata(a); register_funcs(a); for (usize i = 0; i < root->container_item.members.size; i++) { spl_ast_node_ref_t mref = root->container_item.members.data[i]; diff --git a/stage1/spl_ast2ir.h b/stage1/spl_ast2ir.h index f7c5446..d3dbd2c 100644 --- a/stage1/spl_ast2ir.h +++ b/stage1/spl_ast2ir.h @@ -4,10 +4,17 @@ #include "spl_ir.h" #include "spl_sema.h" +/* 全局 var/const 的 def → gdata 向量中的 value 节点索引 */ +typedef struct { + spl_def_id_t def_id; + usize gdata_idx; +} spl_ast2ir_gref_t; + typedef struct { const spl_sema_t *sema; spl_ir_t ir; - VEC(char *) owned_names; /* 本模块 malloc 的函数名,drop 时释放 */ + VEC(char *) owned_names; /* 本模块 malloc 的函数名,drop 时释放 */ + VEC(spl_ast2ir_gref_t) gdata_ref; /* def_id → gdata value 节点索引 */ int err_count; } spl_ast2ir_t; diff --git a/stage1/spl_ir.c b/stage1/spl_ir.c index 978b658..4eb2d4e 100644 --- a/stage1/spl_ir.c +++ b/stage1/spl_ir.c @@ -15,6 +15,7 @@ static const char *const ir_kind_names[] = { void spl_ir_init(spl_ir_t *ir) { memset(ir, 0, sizeof *ir); vec_init(ir->funcs); + vec_init(ir->gdata); /* func ref 0 保留为 error,占位 */ spl_ir_func_t f0; memset(&f0, 0, sizeof f0); @@ -45,6 +46,9 @@ void spl_ir_drop(spl_ir_t *ir) { vec_free(f->labels); } vec_free(ir->funcs); + for (usize i = 0; i < ir->gdata.size; i++) + node_drop_vecs(&ir->gdata.data[i]); + vec_free(ir->gdata); } spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir) { @@ -300,6 +304,16 @@ static void dump_node(const spl_type_t *ty, const spl_ir_node_t *n) { dump_ref(n->mem_offset.offset); printf(")"); break; + case SPL_IR_MEM_FIELD_PTR: + printf("@mem.field_ptr("); + ir_type_dump(ty, n->mem_field_ptr.tid); + printf(", %zu)(", (size_t)n->mem_field_ptr.field_idx); + dump_ref(n->mem_field_ptr.agg); + printf(")"); + break; + case SPL_IR_MEM_GLOBAL_ALLOC: + printf("@mem.global_alloc(gdata[%zu])()", (size_t)n->mem_global_alloc.const_node); + break; case SPL_IR_MEM_COPY: printf("@mem.copy()("); dump_ref(n->mem_copy.dst); @@ -481,4 +495,12 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) { printf("; SPL IR module (%zu funcs)\n", ir->funcs.size - 1); for (usize i = 1; i < ir->funcs.size; i++) dump_func(ty, &ir->funcs.data[i]); + if (ir->gdata.size) { + printf("; global data (%zu)\n", ir->gdata.size); + for (usize i = 0; i < ir->gdata.size; i++) { + printf("; gdata[%zu] = ", i); + dump_node(ty, &ir->gdata.data[i]); + printf("\n"); + } + } } diff --git a/stage1/spl_ir.h b/stage1/spl_ir.h index ce1ccc9..5040caf 100644 --- a/stage1/spl_ir.h +++ b/stage1/spl_ir.h @@ -37,9 +37,11 @@ X(case.int2float, V0, SPL_IR_CASE_INT2FLOAT) \ X(case.float2int, V0, SPL_IR_CASE_FLOAT2INT) \ X(mem.alloca, V0, SPL_IR_MEM_ALLOCA) \ + X(mem.global_alloc, V0, SPL_IR_MEM_GLOBAL_ALLOC) \ X(mem.load, V0, SPL_IR_MEM_LOAD) \ X(mem.store, V0, SPL_IR_MEM_STORE) \ X(mem.offset, V0, SPL_IR_MEM_OFFSET) \ + X(mem.field, V0, SPL_IR_MEM_FIELD_PTR) \ X(mem.copy, V0, SPL_IR_MEM_COPY) \ X(mem.set, V0, SPL_IR_MEM_SET) \ X(mem.fence, V0, SPL_IR_MEM_FENCE) \ @@ -109,6 +111,10 @@ typedef struct { spl_type_id_t tid; spl_ir_node_ref_t count; } mem_alloc; + struct { + spl_type_id_t tid; + spl_ir_node_ref_t const_node; + } mem_global_alloc; struct { spl_type_id_t tid; spl_ir_node_ref_t ptr; @@ -123,6 +129,11 @@ typedef struct { spl_ir_node_ref_t ptr; spl_ir_node_ref_t offset; } mem_offset; + struct { + spl_type_id_t tid; + spl_ir_node_ref_t agg; + usize field_idx; + } mem_field_ptr; struct { spl_type_id_t tid; spl_ir_node_ref_t dst; @@ -171,12 +182,13 @@ typedef struct { } agg_construct; struct { spl_type_id_t tid; - isize field_idx; + spl_type_id_t field_tid; + usize field_idx; spl_ir_node_ref_t val; } agg_extract; struct { spl_type_id_t tid; - isize field_idx; + usize field_idx; spl_ir_node_ref_t agg; spl_ir_node_ref_t field; } agg_insert; @@ -233,8 +245,10 @@ typedef struct { } spl_ir_func_t; typedef VEC(spl_ir_func_t) spl_ir_func_vec_t; + typedef struct { spl_ir_func_vec_t funcs; + spl_ir_node_vec_t gdata; } spl_ir_t; void spl_ir_init(spl_ir_t *ir); diff --git a/stage1/spl_ir2vm.c b/stage1/spl_ir2vm.c new file mode 100644 index 0000000..a4b9bc7 --- /dev/null +++ b/stage1/spl_ir2vm.c @@ -0,0 +1,1393 @@ +/* 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); + emit_arith(fc, arith_op(n->kind, is_signed_type(ty, tid)), 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; + 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) ? SPL_SLT : SPL_ULT; + break; + case SPL_IR_CMP_LE: + op = is_signed_type(ty, tid) ? SPL_SLE : SPL_ULE; + break; + case SPL_IR_CMP_GT: + op = is_signed_type(ty, tid) ? SPL_SGT : SPL_UGT; + break; + default: + op = is_signed_type(ty, tid) ? 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); + 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); + } + } else { + /* 间接调用:栈 [args, func_addr, nargs] CALLI */ + emit_value(fc, n->control_call.func); + emit_push(fc, nargs); + add_insn(fc, SPL_CALLI, SPL_VOID, 0); + } + 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: + case SPL_IR_CONTROL_TRAP: + diag(fc->c, fc->fid, ref, "control.unreachable/trap not implemented"); + add_insn(fc, SPL_HALT, SPL_VOID, 0); + 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]; + if (!produces_value(rn->kind)) + continue; + 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) + 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); + locals = fc.temp_off + 8; /* mem.set 计数器槽 */ + 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; } diff --git a/stage1/spl_ir2vm.h b/stage1/spl_ir2vm.h new file mode 100644 index 0000000..0c417f0 --- /dev/null +++ b/stage1/spl_ir2vm.h @@ -0,0 +1,93 @@ +#ifndef __SPL_IR2VM_H__ +#define __SPL_IR2VM_H__ + +#include "spl_ir.h" +#include "spl_type.h" + +/* + * ================================================================ + * SPL VM ABI (ir2vm 的正式约定;布局知识唯一来源) + * ================================================================ + * + * 栈值槽 spl_val_t = sizeof(usize) = 8 字节。 + * SIR 指令 type 只表达标量 tag(SPL_I8..SPL_PTR),聚合无 tag—— + * 聚合值在 vreg 中是字节块,整体搬运用 NCALL vm_memcpy。 + * + * ── 函数栈帧(字节坐标系,基址 = (char*)&stacks[fp])───────────── + * + * [canary] fp-8 .. 0 (VM CALL 自动插入,ir2vm 不触碰) + * [params 区] fp+0 .. fp+Na (Na = C ABI 参数区字节数) + * [locals / vreg] fp+Na .. fp+Na+L + * + * ALLOC ceil((Na+L)/8) 一条 prologue;epilogue 走 RET。 + * LADDR(imm) 的 imm 是字节偏移;canary 在 fp-1 槽,编译码不可见。 + * + * ── 参数区 = C ABI(聚合值按值) ───────────────────────────────── + * 标量参数:align_up(off,8) 后占 8 字节(一槽)。 + * 聚合参数:按聚合 size 排布跨多槽(align8 + size)。 + * 调用方:标量 ld/PUSH 一槽;聚合逐 8 字节块压栈(聚合 vreg 强制 8 对齐)。 + * 被调方:标量参数映射参数槽;聚合参数在 prologue memcpy 参数区 → param vreg, + * emit_value(param) 取 vreg 地址。参数槽数 = ceil(param_bytes/8) = CALL nargs。 + * + * ── locals = 虚拟寄存器区 ──────────────────────────────────────── + * 每个产生值的 IR 节点 = 一个 vreg(locals 区按类型对齐的字节块)。 + * 纯值节点(type.const / mem.global_alloc / mem.alloca / 折叠 sizeof 等)不落 vreg, + * 引用处重算(PUSH / GADDR / LADDR);其余产生值节点落 vreg,引用处 LOAD。 + * 聚合 vreg 引用处返回其地址(LADDR),搬运经 vm_memcpy。 + * mem.alloca(tid)(cnt) 的 vreg 槽即缓冲区本体,节点值 = LADDR(vreg_off)。 + * 所有运算走 load/store:ld A; ld B; op; st Dst;立即数直接 PUSH。 + * + * ── 调用 ────────────────────────────────────────────────────────── + * 调用方:逐参数压栈(标量一槽;聚合按 C ABI 逐 8 字节块)→ push fn_addr(或 + * native_idx) → CALL n / NCALL n。返回值落 call 节点 vreg。 + * 原生函数:IR 中 nodes 为空的函数(@extern 声明)→ 注册进 prog.natives, + * 加载时由 spl_syscall_register 填 impl;调用改 PUSH nat_idx + NCALL。 + * 变参 nargs = 实际参数槽数。 + * + * ── enum(不展开,直接保留)───────────────────────────────────── + * IR 层保留 enum 类型(不再展开为 struct)。enum 布局 = tag(usize, offset 0) + * + payload(offset 8,最大变体)。构造:agg.construct(enum)(tag, payload); + * match:先取 tag 判定变体,再 extract(enum, 1) 一跳取 payload, + * field_tid = 变体具体类型(由 ast2ir 传入)。 + * + * ── 返回 ────────────────────────────────────────────────────────── + * 标量:ld vreg(val); RET(tag)(RET 的 type 决定 VM 是否弹出返回值)。 + * 聚合返回 = sret(自展开,不改 VM): + * 被调函数签名尾部追加隐藏 *T 参数(最后一个);返回时把聚合 vreg + * memcpy 到 sret 地址,RET(void)。 + * 调用方在 locals 预留聚合槽(= call 节点 vreg),压其地址为最后实参; + * call 完成后聚合值已在该槽。 + * 返回 void:RET(SPL_VOID)。 + * + * ── 全局数据 ────────────────────────────────────────────────────── + * 任何聚合类型下(含 $root 顶层)的 var/const 属全局数据区。gdata 是 + * spl_ir_node_vec_t,每条 = 一个 value 节点(type.const:标量折叠值, + * 聚合/无 init 零)。ir2vm 遍历求值 → SIR gdata 条目(字节 blob)。 + * mem.global_alloc(tid, const_node) 的 const_node = gdata 向量索引, + * 降级为 GADDR(idx)。符号(def) → gdata 索引的解析在 ast2ir 收集期 + * (gdata_ref 表),ir2vm 按索引直接用。 + * + * ── 类型布局(C ABI,唯一实现处)──────────────────────────────── + * type_align / type_size / field_offset:标量按 bits/8 对齐; + * struct 顺序对齐 + 尾填充;union 取最大字段;enum = tag(8) + 最大 payload; + * slice/range = [ptr, len] 各 8 字节;array = len * elem。 + * + * ── 分支 ────────────────────────────────────────────────────────── + * control.br/jmp/select 的 label 是 IR node ref(基本块首指令)。两遍发射: + * 第一遍逐节点发指令并记录 label 节点 → 指令地址;第二遍回填 + * JMP/BZ/BNZ 相对偏移 imm = target_addr - (jmp_addr + 1)。 + * ================================================================ + */ + +typedef struct { + const spl_ir_t *ir; + const spl_type_t *type; +} spl_ir2vm_t; + +void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type); +void spl_ir2vm_drop(spl_ir2vm_t *ctx); + +int spl_ir2vm_run(spl_ir2vm_t *ctx, const char *outpath); /* 返回错误数 */ +void spl_ir2vm_dump(spl_ir2vm_t *ctx); + +#endif /* __SPL_IR2VM_H__ */ diff --git a/stage1/splc0.c b/stage1/splc0.c index 21ceea2..0e3d5ae 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -12,6 +12,7 @@ #include "spl_ast.h" #include "spl_ast2ir.h" +#include "spl_ir2vm.h" #include "spl_lexer.h" #include "spl_sema.h" #include "spl_tok.h" @@ -62,6 +63,11 @@ static void dump_ast(const char *src, const char *fname) { spl_ast_t ast; spl_ast_init(&ast, &toks); spl_ast_prase(&ast); + if (ast.parsed < 0) { + printf("parse failed, skip AST dump\n"); + spl_ast_drop(&ast); + return; + } spl_ast_valid(&ast); spl_ast_dump(&ast, ast.root); spl_ast_drop(&ast); @@ -72,6 +78,11 @@ static void dump_sema(const char *src, const char *fname) { spl_ast_t ast; spl_ast_init(&ast, &toks); spl_ast_prase(&ast); + if (ast.parsed < 0) { + printf("parse failed, skip sema dump\n"); + spl_ast_drop(&ast); + return; + } spl_ast_valid(&ast); spl_sema_t sema; spl_sema_init(&sema); @@ -108,6 +119,11 @@ static void dump_ir(const char *src, const char *fname) { spl_ast_t ast; spl_ast_init(&ast, &toks); spl_ast_prase(&ast); + if (ast.parsed < 0) { + printf("parse failed, skip IR\n"); + spl_ast_drop(&ast); + return; + } spl_ast_valid(&ast); spl_sema_t sema; spl_sema_init(&sema); @@ -152,6 +168,48 @@ static int cmd_dump(const char *flags, const char *path) { return 0; } +static int compile_spl(const char *src, const char *fname, const char *outpath) { + spl_tok_vec_t toks = spl_lex(src, fname); + spl_ast_t ast; + spl_ast_init(&ast, &toks); + spl_ast_prase(&ast); + if (ast.parsed < 0) { + printf("parse failed, no output\n"); + spl_ast_drop(&ast); + return 1; + } + spl_ast_valid(&ast); + spl_sema_t sema; + spl_sema_init(&sema); + sema.ast = * + spl_sema_run(&sema); + spl_sema_check(&sema); + if (sema.error_count) { + printf("sema errors=%d, no output\n", sema.error_count); + spl_sema_drop(&sema); + spl_ast_drop(&ast); + return 1; + } + spl_ast2ir_t a2ir; + spl_ast2ir_init(&a2ir, &sema); + spl_ast2ir_run(&a2ir); + if (a2ir.err_count) { + printf("ast2ir errors=%d, no output\n", a2ir.err_count); + spl_ast2ir_drop(&a2ir); + spl_sema_drop(&sema); + spl_ast_drop(&ast); + return 1; + } + spl_ir2vm_t ir2vm; + spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type); + int rc = spl_ir2vm_run(&ir2vm, outpath); + spl_ir2vm_drop(&ir2vm); + spl_ast2ir_drop(&a2ir); + spl_sema_drop(&sema); + spl_ast_drop(&ast); + return rc ? 1 : 0; +} + int main(int argc, char **argv) { if (argc < 2) { LOG_FATAL("Usage: splc0 [--dump ] [out]\n"); @@ -174,6 +232,16 @@ int main(int argc, char **argv) { } return cmd_dump(argv[argi + 1], argv[argi + 2]); } - LOG_FATAL("splc0: compile todo\n"); - return 1; + /* splc0 */ + if (argc < argi + 2) { + LOG_FATAL("Usage: splc0 or splc0 --dump \n"); + return 1; + } + long len; + char *src = read_file(argv[argi], &len); + if (!src) + return 1; + int rc = compile_spl(src, argv[argi], argv[argi + 1]); + free(src); + return rc; }