/* spl_ast2ir.c AST IR lowering * * 设计要点 * - 名称解析自包含:局部变类型用自身环境栈;顶层类函数sema root scope 与聚合成员表 * - * 变量落在内存槽(@mem.alloca),写走 @mem.load/store;表达式临时值为 SSA * - 控制流用"块表 + * fixup 补丁":分跳转目标在函数末尾回填为块首指令node ref * - * 聚合字段访问:读@agg.extract,写字节地址直写"(@mem.offset + @mem.store�?* - 枚举= * agg.construct(enum)([tag, payload?]);match tag 分发 * - defer 按作用域逆序执行(正常退/ ret / * break / continue 全覆盖) */ #include "spl_ast2ir.h" #include #include #include /* ================================================================ * 基础访问 * ================================================================ */ static spl_ast_node_t *node_at(const spl_sema_t *sema, spl_ast_node_ref_t ref) { if (!ref || ref >= sema->ast->buckets.size) return NULL; return &sema->ast->buckets.data[ref]; } static spl_type_node_t *tn(const spl_sema_t *sema, spl_type_id_t tid) { return spl_type_node((spl_type_t *)&sema->type, tid); } static spl_def_node_t *def_at(const spl_sema_t *sema, spl_def_id_t id) { return spl_type_def((spl_type_t *)&sema->type, id); } static spl_type_id_t underlying(const spl_sema_t *sema, spl_type_id_t tid) { spl_type_node_t *t = tn(sema, tid); return (t && t->kind == SPL_TYPE_ID) ? t->type_id : tid; } static int type_same(const spl_sema_t *sema, spl_type_id_t a, spl_type_id_t b) { if (a == b) return 1; a = underlying(sema, a); b = underlying(sema, b); if (a == b) return 1; spl_type_node_t *na = tn(sema, a); spl_type_node_t *nb = tn(sema, b); if (!na || !nb || na->kind != nb->kind) return 0; switch (na->kind) { case SPL_TYPE_INT: return na->int_type.bits == nb->int_type.bits && na->int_type.is_signed == nb->int_type.is_signed; case SPL_TYPE_FLOAT: return na->float_type.bits == nb->float_type.bits; case SPL_TYPE_PTR: return type_same(sema, na->ptr_pointee, nb->ptr_pointee); case SPL_TYPE_SLICE: return type_same(sema, na->slice_element, nb->slice_element); case SPL_TYPE_RANGE: return type_same(sema, na->range_element, nb->range_element); case SPL_TYPE_ARRAY: return na->array_type.len == nb->array_type.len && type_same(sema, na->array_type.element, nb->array_type.element); case SPL_TYPE_FN: { if (na->fn_type.params.size != nb->fn_type.params.size) return 0; for (usize i = 0; i < na->fn_type.params.size; i++) if (!type_same(sema, na->fn_type.params.data[i], nb->fn_type.params.data[i])) return 0; return type_same(sema, na->fn_type.ret, nb->fn_type.ret); } default: return 0; } } static int is_int_type(const spl_sema_t *sema, spl_type_id_t tid) { spl_type_node_t *t = tn(sema, underlying(sema, tid)); return t && t->kind == SPL_TYPE_INT; } static int is_float_type(const spl_sema_t *sema, spl_type_id_t tid) { spl_type_node_t *t = tn(sema, underlying(sema, tid)); return t && t->kind == SPL_TYPE_FLOAT; } static int is_num_type(const spl_sema_t *sema, spl_type_id_t tid) { spl_type_node_t *t = tn(sema, underlying(sema, tid)); return t && (t->kind == SPL_TYPE_INT || t->kind == SPL_TYPE_FLOAT); } static int is_ptr_type(const spl_sema_t *sema, spl_type_id_t tid) { spl_type_node_t *t = tn(sema, underlying(sema, tid)); return t && t->kind == SPL_TYPE_PTR; } /* ---- 符号解析 ---- */ 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; if (map_get(a->sema->scopes.data[a->sema->root_scope].symbols, name, &def)) { spl_def_node_t *d = def_at(a->sema, def); if (d) return d->type_id; } return 0; } static spl_def_id_t root_lookup(spl_ast2ir_t *a, const char *name) { spl_def_id_t def = 0; if (map_get(a->sema->scopes.data[a->sema->root_scope].symbols, name, &def)) return def; return 0; } /* 匿名类型 id 拥有它的 def(聚合优先,别名/distinct 兜底*/ static spl_def_id_t def_for_type(spl_ast2ir_t *a, spl_type_id_t tid) { if (!tid) return 0; tid = underlying(a->sema, tid); spl_def_id_t fallback = 0; for (usize i = 1; i < a->sema->type.def_table.size; i++) { spl_def_node_t *d = &a->sema->type.def_table.data[i]; spl_type_id_t dt = underlying(a->sema, d->type_id); if (dt == tid) { if (d->kind == SPL_DEF_AGG) return i; if (!fallback && (d->kind == SPL_DEF_ALIAS || d->kind == SPL_DEF_DISTINCT)) fallback = i; } } return fallback; } /* 判断 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; spl_def_node_t *ed = def_at(a->sema, e->def_id); return ed && ed->kind == SPL_DEF_MEMBER; } /* 命名空间成员类型(方�?嵌套类型/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); if (!d) return 0; spl_def_node_t *def = def_at(a->sema, d); for (usize i = 0; i < def->agg_def.size; i++) { if (def->agg_def.data[i].name && strcmp(def->agg_def.data[i].name, name) == 0) return def->agg_def.data[i].type_id; } return 0; } /* 结构字段序号 = 相对 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); if (!d) return -1; spl_def_node_t *def = def_at(a->sema, d); isize fidx = 0; for (usize i = 0; i < def->agg_def.size; i++) { spl_var_def_t *e = &def->agg_def.data[i]; int is_field = agg_entry_is_field(a, e); if (is_field && e->name && strcmp(e->name, name) == 0) return fidx; if (is_field) fidx++; } /* 字段访问只认结构字段(MEMBER_DECL);var/fn/type 成员是命名空间实体,不在此列 */ return -1; } static spl_type_id_t agg_field_tid_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, isize idx) { spl_type_node_t *t = tn(a->sema, underlying(a->sema, agg_tid)); if (!t || (t->kind != SPL_TYPE_STRUCT && t->kind != SPL_TYPE_UNION && t->kind != SPL_TYPE_ENUM)) return 0; if (idx >= 0 && (usize)idx < t->agg_field_types.size) return t->agg_field_types.data[idx]; if (t->kind == SPL_TYPE_ENUM && idx >= 0 && (usize)idx < t->enum_type.variants.size) { spl_type_id_t v = underlying(a->sema, t->enum_type.variants.data[idx]); return (v == underlying(a->sema, agg_tid)) ? 0 : v; } return 0; } /* 按字段序号查成员名(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); if (!d) return NULL; spl_def_node_t *def = def_at(a->sema, d); isize fidx = 0; for (usize i = 0; i < def->agg_def.size; i++) { spl_var_def_t *e = &def->agg_def.data[i]; if (agg_entry_is_field(a, e)) { if (fidx == idx) return e->name; fidx++; } } return NULL; } /* 切片/区间内置字段(ptr/len/begin/end)并入成员查*/ static isize agg_index_or_builtin(spl_ast2ir_t *a, spl_type_id_t agg_tid, const char *name) { spl_type_node_t *t = tn(a->sema, underlying(a->sema, agg_tid)); if (t && t->kind == SPL_TYPE_SLICE) { if (strcmp(name, "ptr") == 0) return 0; if (strcmp(name, "len") == 0) return 1; } if (t && t->kind == SPL_TYPE_RANGE) { if (strcmp(name, "begin") == 0) return 0; if (strcmp(name, "end") == 0) return 1; } return agg_member_index(a, agg_tid, name); } static spl_type_id_t agg_field_tid_or_builtin(spl_ast2ir_t *a, spl_type_id_t agg_tid, isize idx) { spl_type_node_t *t = tn(a->sema, underlying(a->sema, agg_tid)); if (t && t->kind == SPL_TYPE_SLICE) { if (idx == 0) return spl_type_ptr((spl_type_t *)&a->sema->type, t->slice_element); if (idx == 1) return kw_type(a, "usize"); } if (t && t->kind == SPL_TYPE_RANGE) return t->range_element; return agg_field_tid_at(a, agg_tid, idx); } /* ================================================================ * IR 发射(per-function 上下文) * ================================================================ */ typedef struct { const char *name; spl_def_id_t def_id; /* 0 = 未知(名字兜底) */ spl_type_id_t tid; spl_ir_node_ref_t slot; /* 0 = 非内存绑*/ spl_ir_node_ref_t value; /* SSA 值绑*/ int is_type; int mut; } ir_env_t; typedef struct { VEC(ir_env_t) syms; VEC(spl_ast_node_ref_t) defers; /* 本作用域defer */ } ir_env_scope_t; typedef VEC(ir_env_scope_t) ir_env_stack_t; typedef struct { spl_ir_node_ref_t first; } ir_block_t; typedef VEC(ir_block_t) ir_block_vec_t; typedef struct { spl_ir_node_ref_t node; int slot; /* 0=true_label 1=false_label 2=jmp.label */ usize block; } ir_fix_t; typedef VEC(ir_fix_t) ir_fix_vec_t; typedef struct { usize brk; usize cont; usize env_mark; /* 循环体作用域起始下标(defer 边界*/ } ir_loop_t; 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; ir_block_vec_t blocks; usize cur_block; ir_fix_vec_t fixups; ir_loop_vec_t loops; VEC(spl_type_id_t) types; /* nodes 平行的结果类型表 */ int terminated; spl_type_id_t hint; int err; } fnctx_t; 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); vec_init(fc->blocks); vec_init(fc->fixups); vec_init(fc->loops); vec_init(fc->types); } 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; } static void fc_drop(fnctx_t *fc) { for (usize i = 0; i < fc->env.size; i++) { vec_free(fc->env.data[i].syms); vec_free(fc->env.data[i].defers); } vec_free(fc->env); vec_free(fc->blocks); vec_free(fc->fixups); vec_free(fc->loops); vec_free(fc->types); } static void diag(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref, const char *msg) { spl_ast_node_t *n = node_at(a->sema, ref); fc->err++; if (n) LOG_WARN("ast2ir: %s (%s:%d:%d)", msg, n->loc.fname ? n->loc.fname : "?", n->loc.line, n->loc.col); else LOG_WARN("ast2ir: %s [fn=%s]", msg, spl_ir_func(&a->ir, fc->fn)->name ? spl_ir_func(&a->ir, fc->fn)->name : "?"); } static spl_ir_node_ref_t emit_node(spl_ast2ir_t *a, fnctx_t *fc) { if (fc->terminated) { ir_block_t b; memset(&b, 0, sizeof b); vec_push(fc->blocks, b); fc->cur_block = fc->blocks.size - 1; fc->terminated = 0; } spl_ir_node_ref_t r = spl_ir_alloc_node(&a->ir, fc->fn); if (fc->cur_block < fc->blocks.size && !fc->blocks.data[fc->cur_block].first) fc->blocks.data[fc->cur_block].first = r; if (fc->types.size == 0) { spl_type_id_t t0 = 0; vec_push(fc->types, t0); } spl_type_id_t t1 = 0; vec_push(fc->types, t1); return r; } static spl_ir_node_t *enode(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_node_ref_t r) { return spl_ir_node(&a->ir, fc->fn, r); } static void set_ntype(fnctx_t *fc, spl_ir_node_ref_t r, spl_type_id_t tid) { if (r && r < fc->types.size) fc->types.data[r] = tid; } static spl_type_id_t node_type(fnctx_t *fc, spl_ir_node_ref_t r) { if (!r || r >= fc->types.size) return 0; return fc->types.data[r]; } static usize new_block(fnctx_t *fc) { ir_block_t b; memset(&b, 0, sizeof b); vec_push(fc->blocks, b); return fc->blocks.size - 1; } static void begin_block(fnctx_t *fc, usize id) { fc->cur_block = id; fc->terminated = 0; } static void emit_jmp(spl_ast2ir_t *a, fnctx_t *fc, usize target) { spl_ir_node_ref_t r = emit_node(a, fc); spl_ir_node_t *n = enode(a, fc, r); n->kind = SPL_IR_CONTROL_JMP; n->control_jmp.label = 0; ir_fix_t f = {r, 2, target}; vec_push(fc->fixups, f); fc->terminated = 1; } static void emit_br(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_node_ref_t cond, usize t, usize f) { spl_ir_node_ref_t r = emit_node(a, fc); spl_ir_node_t *n = enode(a, fc, r); n->kind = SPL_IR_CONTROL_BR; n->control_br.cond = cond; n->control_br.true_label = 0; n->control_br.false_label = 0; ir_fix_t a1 = {r, 0, t}; ir_fix_t a2 = {r, 1, f}; vec_push(fc->fixups, a1); vec_push(fc->fixups, a2); fc->terminated = 1; } static void emit_ret(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, spl_ir_node_ref_t val) { spl_ir_node_ref_t r = emit_node(a, fc); spl_ir_node_t *n = enode(a, fc, r); n->kind = SPL_IR_CONTROL_RET; n->control_ret.tid = tid; n->control_ret.val = val; fc->terminated = 1; } static spl_ir_node_ref_t emit_const(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid) { spl_ir_node_ref_t r = emit_node(a, fc); spl_ir_node_t *n = enode(a, fc, r); n->kind = SPL_IR_TYPE_CONST; n->type_const.tid = tid; set_ntype(fc, r, tid); return r; } static spl_ir_node_ref_t const_int(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, usize v) { spl_ir_node_ref_t r = emit_const(a, fc, tid); enode(a, fc, r)->type_const.int_lit = v; return r; } static spl_ir_node_ref_t const_bool(spl_ast2ir_t *a, fnctx_t *fc, int v) { return const_int(a, fc, kw_type(a, "bool"), (usize)(v ? 1 : 0)); } static spl_ir_node_ref_t const_float(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, double v) { spl_ir_node_ref_t r = emit_const(a, fc, tid); enode(a, fc, r)->type_const.float_lit = v; return r; } static spl_ir_node_ref_t const_str(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, const char *s) { spl_ir_node_ref_t r = emit_const(a, fc, tid); enode(a, fc, r)->type_const.cstr_lit = s; return r; } static spl_ir_node_ref_t const_fnref(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t fn_tid, spl_ir_func_ref_t fid) { spl_ir_node_ref_t r = emit_const(a, fc, fn_tid); enode(a, fc, r)->type_const.fn = fid; return r; } static spl_ir_node_ref_t emit_arith(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_kind_t k, spl_type_id_t tid, spl_ir_node_ref_t l, spl_ir_node_ref_t r) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = k; e->arith.tid = tid; e->arith.left = l; e->arith.right = r; set_ntype(fc, n, tid); return n; } static spl_ir_node_ref_t emit_cmp(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_kind_t k, spl_type_id_t tid, spl_ir_node_ref_t x, spl_ir_node_ref_t y) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = k; e->cmp.tid = tid; e->cmp.a = x; e->cmp.b = y; set_ntype(fc, n, kw_type(a, "bool")); return n; } static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_kind_t k, spl_type_id_t from, spl_type_id_t to, spl_ir_node_ref_t v) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = k; e->cast.from_tid = from; e->cast.to_tid = to; e->cast.val = v; set_ntype(fc, n, to); return n; } static spl_ir_node_ref_t emit_alloca(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid) { spl_ir_node_ref_t cnt = const_int(a, fc, kw_type(a, "usize"), 1); spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_MEM_ALLOCA; e->mem_alloc.tid = tid; e->mem_alloc.count = cnt; spl_type_id_t pt = spl_type_ptr((spl_type_t *)&a->sema->type, tid); set_ntype(fc, n, pt); return n; } static void emit_store(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, spl_ir_node_ref_t ptr, spl_ir_node_ref_t val) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_MEM_STORE; e->mem_store.tid = tid; e->mem_store.ptr = ptr; e->mem_store.val = val; } static spl_ir_node_ref_t emit_load(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, spl_ir_node_ref_t ptr) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_MEM_LOAD; e->mem_load.tid = tid; e->mem_load.ptr = ptr; set_ntype(fc, n, tid); return n; } static spl_ir_node_ref_t emit_offset(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, spl_ir_node_ref_t ptr, spl_ir_node_ref_t off) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_MEM_OFFSET; e->mem_offset.tid = tid; e->mem_offset.ptr = ptr; e->mem_offset.offset = off; spl_type_id_t pt = spl_type_ptr((spl_type_t *)&a->sema->type, tid); set_ntype(fc, n, pt); 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); e->kind = SPL_IR_AGG_CONSTRUCT; e->agg_construct.tid = tid; vec_init(e->agg_construct.fields); set_ntype(fc, n, tid); return n; } static void agg_construct_add(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_node_ref_t agg, spl_ir_node_ref_t field) { spl_ir_node_t *e = enode(a, fc, agg); vec_push(e->agg_construct.fields, field); } static spl_ir_node_ref_t emit_agg_extract(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, spl_type_id_t field_tid, isize fidx, spl_ir_node_ref_t val) { spl_ir_node_ref_t n = emit_node(a, fc); 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); return n; } static spl_ir_node_ref_t emit_agg_insert(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, isize fidx, spl_ir_node_ref_t agg, spl_ir_node_ref_t field) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_AGG_INSERT; e->agg_insert.tid = tid; e->agg_insert.field_idx = fidx; e->agg_insert.agg = agg; e->agg_insert.field = field; set_ntype(fc, n, tid); return n; } static spl_ir_node_ref_t emit_call(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t fn_tid, spl_ir_node_ref_t callee, spl_ir_node_ref_t *args, usize nargs) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_CONTROL_CALL; e->control_call.tid = fn_tid; e->control_call.func = callee; vec_init(e->control_call.params); for (usize i = 0; i < nargs; i++) vec_push(e->control_call.params, args[i]); 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; set_ntype(fc, n, ret); return n; } static spl_ir_node_ref_t emit_select(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, spl_ir_node_ref_t c, spl_ir_node_ref_t t, spl_ir_node_ref_t f) { spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_CONTROL_SELECT; e->control_select.tid = tid; e->control_select.cond = c; e->control_select.true_val = t; e->control_select.false_val = f; set_ntype(fc, n, tid); return n; } /* ================================================================ * 环境(变类型绑定 * ================================================================ */ static void env_push(fnctx_t *fc) { ir_env_scope_t s; memset(&s, 0, sizeof s); vec_init(s.syms); vec_init(s.defers); vec_push(fc->env, s); } static void env_pop(fnctx_t *fc) { if (!fc->env.size) return; vec_free(fc->env.data[fc->env.size - 1].syms); vec_free(fc->env.data[fc->env.size - 1].defers); vec_pop(fc->env); } static ir_env_t *env_find(fnctx_t *fc, const char *name) { for (usize i = fc->env.size; i > 0; i--) { ir_env_scope_t *s = &fc->env.data[i - 1]; for (usize j = 0; j < s->syms.size; j++) { if (s->syms.data[j].name && strcmp(s->syms.data[j].name, name) == 0) return &s->syms.data[j]; } } return NULL; } /* 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--) { ir_env_scope_t *s = &fc->env.data[i - 1]; for (usize j = 0; j < s->syms.size; j++) { if (s->syms.data[j].def_id == def_id) return &s->syms.data[j]; } } } return name ? env_find(fc, name) : NULL; } static void env_add(fnctx_t *fc, const char *name, spl_def_id_t def_id, spl_type_id_t tid, spl_ir_node_ref_t slot, spl_ir_node_ref_t value, int is_type, int mut) { if (!fc->env.size) env_push(fc); ir_env_t it; memset(&it, 0, sizeof it); it.name = name; it.def_id = def_id; it.tid = tid; it.slot = slot; it.value = value; it.is_type = is_type; it.mut = mut; vec_push(fc->env.data[fc->env.size - 1].syms, it); } /* ================================================================ * 枚举 * ================================================================ */ static spl_type_id_t enum_tag_tid(spl_ast2ir_t *a) { return kw_type(a, "usize"); } static isize enum_variant_index(spl_ast2ir_t *a, spl_type_id_t enum_tid, const char *name) { enum_tid = underlying(a->sema, enum_tid); spl_def_id_t d = def_for_type(a, enum_tid); if (!d) return -1; spl_def_node_t *def = def_at(a->sema, d); isize vidx = 0; for (usize i = 0; i < def->agg_def.size; i++) { spl_var_def_t *e = &def->agg_def.data[i]; if (agg_entry_is_field(a, e)) { if (e->name && strcmp(e->name, name) == 0) return vidx; vidx++; } } return -1; } static spl_type_id_t enum_payload_tid(spl_ast2ir_t *a, spl_type_id_t enum_tid, isize idx) { enum_tid = underlying(a->sema, enum_tid); spl_type_node_t *t = tn(a->sema, enum_tid); if (!t || t->kind != SPL_TYPE_ENUM || idx < 0 || (usize)idx >= t->enum_type.variants.size) return 0; spl_type_id_t v = underlying(a->sema, t->enum_type.variants.data[idx]); return (v == enum_tid) ? 0 : v; } static spl_ir_node_ref_t enum_variant_value(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t enum_tid, isize idx) { spl_ir_node_ref_t agg = emit_agg_construct(a, fc, enum_tid); agg_construct_add(a, fc, agg, const_int(a, fc, enum_tag_tid(a), (usize)idx)); return agg; } static spl_ir_node_ref_t enum_tag_of(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t enum_tid, spl_ir_node_ref_t val) { 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); if (!n || n->kind != SPL_AST_EXPR) return 0; if (n->expr.op == SPL_AST_PRIMARY_EXPR) { spl_ast_node_t *pn = node_at(a->sema, n->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->is_type) return underlying(a->sema, it->tid); spl_def_id_t def = root_lookup(a, pn->primary_expr.ident); if (def) { spl_def_node_t *d = def_at(a->sema, def); if (d && d->type_id) return underlying(a->sema, d->type_id); } } return 0; } if (n->expr.op == SPL_AST_POSTFIX_EXPR) { spl_ast_node_t *pf = node_at(a->sema, n->expr.op_expr.left); if (pf && pf->postfix_expr.kind == SPL_AST_FIELD_EXPR) { spl_type_id_t bt = type_of_type_ref(a, fc, pf->postfix_expr.primary_expr); if (bt) { spl_type_id_t mt = agg_member_type(a, bt, pf->postfix_expr.field_expr); return underlying(a->sema, mt); } } return 0; } return 0; } /* ================================================================ * 类型解析(自包含 * ================================================================ */ static spl_type_id_t resolve_type_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref); static spl_type_id_t resolve_type_atom(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { spl_ast_node_t *n = node_at(a->sema, ref); if (!n) return 0; switch (n->type_atom.kind) { case SPL_AST_TYPE_VOID: return kw_type(a, "void"); case SPL_AST_TYPE_BOOL: return kw_type(a, "bool"); case SPL_AST_TYPE_I8: return kw_type(a, "i8"); case SPL_AST_TYPE_U8: return kw_type(a, "u8"); case SPL_AST_TYPE_I16: return kw_type(a, "i16"); case SPL_AST_TYPE_U16: return kw_type(a, "u16"); case SPL_AST_TYPE_I32: return kw_type(a, "i32"); case SPL_AST_TYPE_U32: return kw_type(a, "u32"); case SPL_AST_TYPE_I64: return kw_type(a, "i64"); case SPL_AST_TYPE_U64: return kw_type(a, "u64"); case SPL_AST_TYPE_ISIZE: return kw_type(a, "isize"); case SPL_AST_TYPE_USIZE: return kw_type(a, "usize"); case SPL_AST_TYPE__F32: return kw_type(a, "f32"); case SPL_AST_TYPE__F64: return kw_type(a, "f64"); case SPL_AST_TYPE_PTR: case SPL_AST_TYPE_ANY: return kw_type(a, "void"); case SPL_AST_TYPE_IDENT: { const char *name = n->type_atom.ident; ir_env_t *it = env_find(fc, name); if (it && it->is_type) return it->tid; spl_def_id_t def = root_lookup(a, name); if (def) { spl_def_node_t *d = def_at(a->sema, def); if (d && d->type_id) return d->type_id; } return 0; } } return 0; } static spl_type_id_t resolve_type_path(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_vec_t *path) { if (!path->size) return 0; spl_type_id_t tid = resolve_type_atom(a, fc, path->data[0]); if (!tid) return 0; for (usize i = 1; i < path->size; i++) { spl_ast_node_t *atom = node_at(a->sema, path->data[i]); if (!atom) return 0; spl_type_id_t mt = agg_member_type(a, tid, atom->type_atom.ident); if (!mt) return 0; tid = mt; } return tid; } static spl_type_id_t resolve_type_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { spl_ast_node_t *n = node_at(a->sema, ref); if (!n) return 0; /* 首�?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(...)、关键字、别名到组合�?*/ spl_type_id_t base = 0; switch (n->type_expr.kind) { case SPL_AST_BASE_TYPE_PATH: base = resolve_type_path(a, fc, &n->type_expr.type_path); break; case SPL_AST_BASE_TYPE_FN: { spl_type_id_vec_t params; vec_init(params); for (usize i = 0; i < n->type_expr.fn_type.param_list.size; i++) { spl_ast_node_t *pd = node_at(a->sema, n->type_expr.fn_type.param_list.data[i]); spl_type_id_t pt = 0; if (pd && pd->param_decl.type_expr) pt = resolve_type_expr(a, fc, pd->param_decl.type_expr); vec_push(params, pt); } spl_type_id_t ret = 0; if (n->type_expr.fn_type.type_expr) ret = resolve_type_expr(a, fc, n->type_expr.fn_type.type_expr); else ret = kw_type(a, "void"); base = spl_type_fn((spl_type_t *)&a->sema->type, params, ret); break; } case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: case SPL_AST_TYPE_ENUM: /* 内联聚合不应走到这里(sema 已注解其 def);防御性报�?*/ diag(a, fc, ref, "inline aggregate not annotated by sema"); return 0; default: return 0; } for (usize i = n->type_expr.type_prefixs.size; i > 0; i--) { spl_ast_node_t *pf = node_at(a->sema, n->type_expr.type_prefixs.data[i - 1]); if (!pf) continue; if (pf->prefix_type.pointer == 1) base = spl_type_ptr((spl_type_t *)&a->sema->type, base); else if (pf->prefix_type.pointer == 2) { if (pf->prefix_type.array_size > 0) base = spl_type_array((spl_type_t *)&a->sema->type, base, (usize)pf->prefix_type.array_size); else base = spl_type_slice((spl_type_t *)&a->sema->type, base); } } return base; } /* ================================================================ * 表达 * ================================================================ */ static spl_ir_node_ref_t lower_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref); static void lower_stmt(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref); static void emit_scope_defers(spl_ast2ir_t *a, fnctx_t *fc, usize scope_idx); static void emit_defers_from(spl_ast2ir_t *a, fnctx_t *fc, usize mark); static spl_ir_func_ref_t a2ir_fn_of(spl_ast2ir_t *a, spl_type_id_t fn_tid); static spl_ir_node_ref_t lower_compound_op(spl_ast2ir_t *a, fnctx_t *fc, int op, spl_type_id_t tid, spl_ir_node_ref_t cur, spl_ir_node_ref_t rhs); static int expr_is_int_literal(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { spl_ast_node_t *n = node_at(a->sema, ref); if (!n || n->kind != SPL_AST_EXPR) return 0; switch (n->expr.op) { case SPL_AST_PRIMARY_EXPR: { spl_ast_node_t *pn = node_at(a->sema, n->expr.op_expr.left); return pn && pn->primary_expr.kind == SPL_AST_INTEGER; } case SPL_AST_PREFIX_EXPR: { spl_ast_node_t *pf = node_at(a->sema, n->expr.op_expr.left); if (pf && pf->prefix_expr.kind == SPL_AST_MINUS_EXPR) return expr_is_int_literal(a, pf->prefix_expr.postfix_expr); return 0; } default: return 0; } } static spl_ir_node_ref_t coerce_to(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_node_ref_t v, spl_type_id_t from, spl_type_id_t to) { if (!v || !from || !to) return v; if (type_same(a->sema, from, to)) return v; spl_type_id_t f = underlying(a->sema, from); spl_type_id_t t = underlying(a->sema, to); spl_type_node_t *ft = tn(a->sema, f); spl_type_node_t *tt = tn(a->sema, t); if (!ft || !tt) return v; if (ft->kind == SPL_TYPE_INT && tt->kind == SPL_TYPE_INT) { if (ft->int_type.bits == tt->int_type.bits) return v; if (tt->int_type.bits > ft->int_type.bits) return emit_cast(a, fc, ft->int_type.is_signed ? SPL_IR_CAST_SEXT : SPL_IR_CAST_ZEXT, from, to, v); return emit_cast(a, fc, SPL_IR_CAST_TRUNC, from, to, v); } if (ft->kind == SPL_TYPE_INT && tt->kind == SPL_TYPE_FLOAT) return emit_cast(a, fc, SPL_IR_CASE_INT2FLOAT, from, to, v); if (ft->kind == SPL_TYPE_FLOAT && tt->kind == SPL_TYPE_INT) return emit_cast(a, fc, SPL_IR_CASE_FLOAT2INT, from, to, v); if (ft->kind == SPL_TYPE_FLOAT && tt->kind == SPL_TYPE_FLOAT) return emit_cast(a, fc, tt->float_type.bits > ft->float_type.bits ? SPL_IR_CAST_FEXT : SPL_IR_CAST_FTRUNC, from, to, v); if (ft->kind == SPL_TYPE_PTR && tt->kind == SPL_TYPE_PTR) return emit_cast(a, fc, SPL_IR_CAST_BITCAST, from, to, v); if (ft->kind == SPL_TYPE_PTR && tt->kind == SPL_TYPE_INT) return emit_cast(a, fc, SPL_IR_CAST_PTR2INT, from, to, v); if (ft->kind == SPL_TYPE_INT && tt->kind == SPL_TYPE_PTR) return emit_cast(a, fc, SPL_IR_CAST_INT2PTR, from, to, v); if (ft->kind == SPL_TYPE_BOOL && tt->kind == SPL_TYPE_INT) return emit_cast(a, fc, SPL_IR_CAST_BOOL2INT, from, to, v); return v; } /* ---- 左值地址 ---- */ #define MAX_FIELD_CHAIN 16 static spl_ir_node_ref_t lower_lvalue(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref, spl_type_id_t *out_tid); /* 收集字段链(叶子在前):返回EXPR ref */ static spl_ast_node_ref_t field_chain_base(spl_ast2ir_t *a, spl_ast_node_t *pf, const char **names, int *n) { *n = 0; names[(*n)++] = pf->postfix_expr.field_expr; spl_ast_node_ref_t bref = pf->postfix_expr.primary_expr; spl_ast_node_t *base = node_at(a->sema, bref); while (base && base->kind == SPL_AST_EXPR && base->expr.op == SPL_AST_POSTFIX_EXPR) { spl_ast_node_t *bpf = node_at(a->sema, base->expr.op_expr.left); if (!bpf || bpf->postfix_expr.kind != SPL_AST_FIELD_EXPR) break; if (*n >= MAX_FIELD_CHAIN) break; names[(*n)++] = bpf->postfix_expr.field_expr; bref = bpf->postfix_expr.primary_expr; base = node_at(a->sema, bref); } return bref; } /* 字段链的存储地址(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); if (!n || n->kind != SPL_AST_EXPR || n->expr.op != SPL_AST_POSTFIX_EXPR) return 0; spl_ast_node_t *pf = node_at(a->sema, n->expr.op_expr.left); if (!pf || pf->postfix_expr.kind != SPL_AST_FIELD_EXPR) return 0; 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); 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; for (int i = nf - 1; i >= 0; i--) { spl_type_node_t *ct = tn(a->sema, underlying(a->sema, cur_tid)); if (!ct || (ct->kind != SPL_TYPE_STRUCT && ct->kind != SPL_TYPE_UNION && ct->kind != SPL_TYPE_SLICE && ct->kind != SPL_TYPE_RANGE)) return 0; isize idx = agg_index_or_builtin(a, cur_tid, names[i]); if (idx < 0) return 0; spl_type_id_t ft = agg_field_tid_or_builtin(a, cur_tid, idx); 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); spl_type_id_t pty = spl_type_ptr((spl_type_t *)&a->sema->type, cur_tid); addr = emit_load(a, fc, pty, addr); } } } *out_tid = cur_tid; return addr; } /* a[i] 内联 postfix 节点 元素地址 */ static spl_ir_node_ref_t index_addr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *pf, spl_type_id_t *elem) { spl_ir_node_ref_t idx = lower_expr(a, fc, pf->postfix_expr.index_expr); spl_ast_node_ref_t bref = pf->postfix_expr.primary_expr; spl_type_id_t base_t = 0; spl_ir_node_ref_t base_lv = lower_lvalue(a, fc, bref, &base_t); spl_ir_node_ref_t base_addr = 0; spl_type_id_t elem_t = 0; spl_type_node_t *bt = NULL; if (base_lv) { bt = tn(a->sema, underlying(a->sema, base_t)); } else { spl_ir_node_ref_t v = lower_expr(a, fc, bref); spl_type_id_t vt = underlying(a->sema, node_type(fc, v)); spl_type_node_t *vtt = vt ? tn(a->sema, vt) : NULL; if (vtt && vtt->kind == SPL_TYPE_PTR) { base_addr = v; base_t = vt; bt = vtt; } else if (vtt && vtt->kind == SPL_TYPE_SLICE) { spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, vtt->slice_element); base_addr = emit_agg_extract(a, fc, vt, ep, 0, v); base_t = vt; bt = vtt; } else if (vtt && vtt->kind == SPL_TYPE_ARRAY) { spl_type_id_t fat = 0; spl_ir_node_ref_t faddr = lower_field_address(a, fc, bref, &fat); if (faddr) { base_addr = faddr; base_t = fat; bt = tn(a->sema, underlying(a->sema, fat)); } else { diag(a, fc, 0, "index on non-addressable array value"); return 0; } } else { diag(a, fc, 0, "index requires array/slice/pointer"); return 0; } } if (bt && bt->kind == SPL_TYPE_ARRAY) { base_addr = base_lv ? base_lv : base_addr; elem_t = bt->array_type.element; } else if (bt && bt->kind == SPL_TYPE_PTR) { base_addr = base_lv ? emit_load(a, fc, base_t, base_lv) : base_addr; elem_t = underlying(a->sema, bt->ptr_pointee); } else if (bt && bt->kind == SPL_TYPE_SLICE) { spl_ir_node_ref_t slv = base_lv ? emit_load(a, fc, base_t, base_lv) : base_addr; elem_t = bt->slice_element; spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, elem_t); base_addr = emit_agg_extract(a, fc, base_t, ep, 0, slv); } else { diag(a, fc, 0, "index requires array/slice/pointer"); return 0; } if (!elem_t) { diag(a, fc, 0, "index requires array/slice/pointer"); return 0; } spl_ir_node_ref_t o = coerce_to(a, fc, idx, node_type(fc, idx), kw_type(a, "isize")); spl_ir_node_ref_t addr = emit_offset(a, fc, elem_t, base_addr, o); *elem = elem_t; return addr; } static spl_ir_node_ref_t lower_lvalue(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref, spl_type_id_t *out_tid) { spl_ast_node_t *n = node_at(a->sema, ref); if (!n || n->kind != SPL_AST_EXPR) return 0; if (n->expr.op == SPL_AST_PRIMARY_EXPR) { spl_ast_node_t *pn = node_at(a->sema, n->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) { *out_tid = it->tid; return it->slot; } 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) return lower_lvalue(a, fc, pn->primary_expr.expr, out_tid); return 0; } if (n->expr.op == SPL_AST_POSTFIX_EXPR) { spl_ast_node_t *pf = node_at(a->sema, n->expr.op_expr.left); if (!pf) return 0; if (pf->postfix_expr.kind == SPL_AST_DEREF_EXPR) { spl_ir_node_ref_t p = lower_expr(a, fc, pf->postfix_expr.primary_expr); spl_type_id_t pt = underlying(a->sema, node_type(fc, p)); spl_type_node_t *tt = tn(a->sema, pt); if (!tt || tt->kind != SPL_TYPE_PTR) { diag(a, fc, ref, ".* requires pointer"); return 0; } *out_tid = underlying(a->sema, tt->ptr_pointee); return p; } if (pf->postfix_expr.kind == SPL_AST_INDEX_EXPR) return index_addr(a, fc, pf, out_tid); if (pf->postfix_expr.kind == SPL_AST_FIELD_EXPR) return lower_field_address(a, fc, ref, out_tid); return 0; } 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_ASTERISK_EXPR) { spl_ir_node_ref_t p = lower_expr(a, fc, pp->prefix_expr.postfix_expr); spl_type_id_t pt = underlying(a->sema, node_type(fc, p)); spl_type_node_t *tt = tn(a->sema, pt); if (!tt || tt->kind != SPL_TYPE_PTR) { diag(a, fc, ref, "prefix * requires pointer"); return 0; } *out_tid = underlying(a->sema, tt->ptr_pointee); return p; } return 0; } return 0; } static spl_ir_node_ref_t lower_ident(spl_ast2ir_t *a, fnctx_t *fc, const char *name, spl_def_id_t def_id, spl_ast_node_ref_t ref) { ir_env_t *it = env_find_def(fc, def_id, name); if (it) { if (it->is_type) { diag(a, fc, ref, "type used as value"); return 0; } if (it->slot) return emit_load(a, fc, it->tid, it->slot); return it->value; } spl_def_id_t def = root_lookup(a, name); 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"); 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; } static spl_type_id_t type_from_type_like(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { spl_ast_node_t *n = node_at(a->sema, ref); if (!n || n->kind != SPL_AST_EXPR) return 0; if (n->expr.op != SPL_AST_PRIMARY_EXPR) return 0; spl_ast_node_t *pn = node_at(a->sema, n->expr.op_expr.left); if (!pn || pn->primary_expr.kind != SPL_AST_IDENT) return 0; ir_env_t *it = env_find_def(fc, pn->resolved_def_id, pn->primary_expr.ident); if (it && it->is_type) return it->tid; spl_def_id_t def = root_lookup(a, pn->primary_expr.ident); if (def) { spl_def_node_t *d = def_at(a->sema, def); if (d && d->type_id) return d->type_id; } return 0; } static spl_ir_node_ref_t lower_block_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_vec_t *items) { env_push(fc); spl_ir_node_ref_t result = 0; for (usize i = 0; i < items->size; i++) { spl_ast_node_t *b = node_at(a->sema, items->data[i]); if (i + 1 == items->size && b && b->kind == SPL_AST_EXPR) { spl_ir_node_ref_t v = lower_expr(a, fc, items->data[i]); if (v && !fc->terminated) result = v; break; } lower_stmt(a, fc, items->data[i]); } if (!fc->terminated) emit_scope_defers(a, fc, fc->env.size - 1); env_pop(fc); return result; } static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *pn) { switch (pn->primary_expr.kind) { case SPL_AST_INTEGER: { spl_type_id_t t = kw_type(a, "i32"); if (fc->hint && is_int_type(a->sema, fc->hint)) t = underlying(a->sema, fc->hint); return const_int(a, fc, t, (usize)pn->primary_expr.integer_expr); } case SPL_AST_FLOAT: { spl_type_id_t t = kw_type(a, "f64"); if (fc->hint && is_float_type(a->sema, fc->hint)) t = underlying(a->sema, fc->hint); return const_float(a, fc, t, pn->primary_expr.float_expr); } case SPL_AST_CHAR_LIT: { spl_type_id_t t = kw_type(a, "u8"); if (fc->hint && is_int_type(a->sema, fc->hint)) t = underlying(a->sema, fc->hint); return const_int(a, fc, t, (usize)(unsigned char)pn->primary_expr.char_lit_expr); } case SPL_AST_STRING_LIT: { spl_type_id_t u8 = kw_type(a, "u8"); spl_type_id_t t = spl_type_ptr((spl_type_t *)&a->sema->type, u8); return const_str(a, fc, t, pn->primary_expr.string_lit_expr); } case SPL_AST_TRUE: case SPL_AST_FALSE: return const_bool(a, fc, pn->primary_expr.kind == SPL_AST_TRUE); case SPL_AST_NULL: { spl_type_id_t ht = underlying(a->sema, fc->hint); spl_type_node_t *htt = ht ? tn(a->sema, ht) : NULL; if (htt && htt->kind == SPL_TYPE_SLICE) { spl_ir_node_ref_t sl = emit_agg_construct(a, fc, ht); spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, htt->slice_element); agg_construct_add(a, fc, sl, const_int(a, fc, ep, 0)); agg_construct_add(a, fc, sl, const_int(a, fc, kw_type(a, "usize"), 0)); return sl; } spl_type_id_t t = htt && htt->kind == SPL_TYPE_PTR ? ht : spl_type_ptr((spl_type_t *)&a->sema->type, kw_type(a, "void")); return const_int(a, fc, t, 0); } case SPL_AST_IDENT: return lower_ident(a, fc, pn->primary_expr.ident, pn->resolved_def_id, 0); case SPL_AST_EXPR_EXPR: return lower_expr(a, fc, pn->primary_expr.expr); case SPL_AST_BLOCK_EXPR: return lower_block_expr(a, fc, &pn->primary_expr.block_expr); case SPL_AST_ARRAY_LIT: { spl_type_id_t elem = resolve_type_expr(a, fc, pn->primary_expr.array_lit_expr.type_expr); if (!elem) 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); 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); 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: { spl_type_id_t tid = 0; if (pn->primary_expr.aggregate_init.name) { spl_def_id_t def = root_lookup(a, pn->primary_expr.aggregate_init.name); if (def) tid = underlying(a->sema, def_at(a->sema, def)->type_id); else { ir_env_t *it = env_find(fc, pn->primary_expr.aggregate_init.name); if (it && it->is_type) tid = underlying(a->sema, it->tid); } } else { spl_type_id_t hint_t = underlying(a->sema, fc->hint); spl_type_node_t *htt = hint_t ? tn(a->sema, hint_t) : NULL; if (!htt || (htt->kind != SPL_TYPE_STRUCT && htt->kind != SPL_TYPE_UNION && htt->kind != SPL_TYPE_SLICE && htt->kind != SPL_TYPE_RANGE)) { diag(a, fc, 0, "anonymous aggregate literal without context type"); return 0; } 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]); if (!item || !item->aggregate_init_item.ident) continue; isize fidx = agg_index_or_builtin(a, hint_t, item->aggregate_init_item.ident); if (fidx < 0) { diag(a, fc, 0, "unknown field in aggregate literal"); continue; } 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); 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) { 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]); if (!item || !item->aggregate_init_item.ident) continue; isize vidx = enum_variant_index(a, tid, item->aggregate_init_item.ident); if (vidx < 0) { diag(a, fc, 0, "unknown enum variant"); continue; } 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; spl_ir_node_ref_t pv = lower_expr(a, fc, item->aggregate_init_item.expr); fc->hint = 0; if (pt) pv = coerce_to(a, fc, pv, node_type(fc, pv), pt); 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 = 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; 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]); if (item && fname && item->aggregate_init_item.ident && strcmp(item->aggregate_init_item.ident, fname) == 0) { found = pn->primary_expr.aggregate_init.expr.data[j]; break; } } if (!found) { 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]); 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: { const char *id = pn->primary_expr.builtin_expr.ident; if (strcmp(id, "sizeof") == 0 && pn->primary_expr.builtin_expr.expr_list.size) { spl_type_id_t t = type_from_type_like(a, fc, pn->primary_expr.builtin_expr.expr_list.data[0]); if (!t) { diag(a, fc, 0, "sizeof: cannot resolve type"); return 0; } spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_TYPE_SIZEOF; e->ir_sizeof.tid = t; set_ntype(fc, n, kw_type(a, "usize")); return n; } if (strcmp(id, "dbg") == 0) { for (usize i = 0; i < pn->primary_expr.builtin_expr.expr_list.size; i++) lower_expr(a, fc, pn->primary_expr.builtin_expr.expr_list.data[i]); spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); e->kind = SPL_IR_DBG_BREAKPOINT; set_ntype(fc, n, kw_type(a, "void")); return n; } diag(a, fc, 0, "unsupported builtin call"); return 0; } default: return 0; } } static spl_ir_node_ref_t lower_prefix(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *pf) { switch (pf->prefix_expr.kind) { case SPL_AST_MINUS_EXPR: { spl_ir_node_ref_t v = lower_expr(a, fc, pf->prefix_expr.postfix_expr); spl_type_id_t t = underlying(a->sema, node_type(fc, v)); if (!is_num_type(a->sema, t)) { diag(a, fc, 0, "unary minus requires numeric"); return 0; } return emit_arith(a, fc, SPL_IR_ARITH_NEG, t, v, 0); } case SPL_AST_BANG_EXPR: { spl_ir_node_ref_t v = lower_expr(a, fc, pf->prefix_expr.postfix_expr); spl_ir_node_ref_t z = const_bool(a, fc, 0); return emit_cmp(a, fc, SPL_IR_CMP_EQ, kw_type(a, "bool"), v, z); } case SPL_AST_TILDE_EXPR: { spl_ir_node_ref_t v = lower_expr(a, fc, pf->prefix_expr.postfix_expr); spl_type_id_t t = underlying(a->sema, node_type(fc, v)); if (!is_int_type(a->sema, t)) { diag(a, fc, 0, "~ requires integer"); return 0; } return emit_arith(a, fc, SPL_IR_ARITH_NOT, t, v, 0); } case SPL_AST_AMPERSAND_EXPR: { spl_type_id_t t = 0; spl_ir_node_ref_t addr = lower_lvalue(a, fc, pf->prefix_expr.postfix_expr, &t); if (addr) { spl_type_id_t pt = spl_type_ptr((spl_type_t *)&a->sema->type, t); set_ntype(fc, addr, pt); return addr; } spl_ast_node_t *operand = node_at(a->sema, pf->prefix_expr.postfix_expr); if (operand && operand->kind == SPL_AST_EXPR && operand->expr.op == SPL_AST_PRIMARY_EXPR) { spl_ast_node_t *pn = node_at(a->sema, operand->expr.op_expr.left); if (pn && pn->primary_expr.kind == SPL_AST_IDENT) { spl_def_id_t 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_FN_PARAMS && d->type_id) { spl_ir_func_ref_t fid = a2ir_fn_of(a, d->type_id); if (fid) return const_fnref(a, fc, d->type_id, fid); } } } } diag(a, fc, 0, "& requires addressable operand"); return 0; } case SPL_AST_ASTERISK_EXPR: { spl_ir_node_ref_t v = lower_expr(a, fc, pf->prefix_expr.postfix_expr); spl_type_id_t t = underlying(a->sema, node_type(fc, v)); spl_type_node_t *tt = tn(a->sema, t); if (tt && tt->kind == SPL_TYPE_PTR) { spl_type_id_t pointee = underlying(a->sema, tt->ptr_pointee); return emit_load(a, fc, pointee, v); } return v; } default: return 0; } } /* ---- 调用目标 ---- */ typedef struct { spl_type_id_t fn_tid; spl_ir_node_ref_t callee; } callee_t; static int resolve_callee(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t base, callee_t *out) { memset(out, 0, sizeof *out); spl_ast_node_t *n = node_at(a->sema, base); if (!n || n->kind != SPL_AST_EXPR) return 0; if (n->expr.op == SPL_AST_PRIMARY_EXPR) { spl_ast_node_t *pn = node_at(a->sema, n->expr.op_expr.left); if (pn && pn->primary_expr.kind == SPL_AST_IDENT) { const char *name = pn->primary_expr.ident; ir_env_t *it = env_find_def(fc, pn->resolved_def_id, name); if (it && it->is_type) { diag(a, fc, base, "type is not callable"); return 0; } spl_def_id_t def = root_lookup(a, name); if (def) { spl_def_node_t *d = def_at(a->sema, def); if (d && d->kind == SPL_DEF_FN_PARAMS && d->type_id) { out->fn_tid = d->type_id; spl_ir_func_ref_t fid = a2ir_fn_of(a, d->type_id); if (fid) { out->callee = const_fnref(a, fc, d->type_id, fid); return 1; } diag(a, fc, base, "function has no IR function"); return 0; } } /* 命名空间内裸名互调:Str.from_cstr 中调cstrlen(...) */ if (fc->ns_tid) { spl_type_id_t mt = agg_member_type(a, fc->ns_tid, name); spl_type_node_t *mtn = mt ? tn(a->sema, mt) : NULL; if (mt && mtn && mtn->kind == SPL_TYPE_FN) { out->fn_tid = mt; spl_ir_func_ref_t fid = a2ir_fn_of(a, mt); if (fid) { out->callee = const_fnref(a, fc, mt, fid); return 1; } } } } } if (n->expr.op == SPL_AST_POSTFIX_EXPR) { spl_ast_node_t *pf = node_at(a->sema, n->expr.op_expr.left); if (pf && pf->postfix_expr.kind == SPL_AST_FIELD_EXPR) { const char *fname = pf->postfix_expr.field_expr; spl_ast_node_ref_t bref = pf->postfix_expr.primary_expr; spl_type_id_t ttr = type_of_type_ref(a, fc, bref); if (ttr) { spl_type_id_t mt = agg_member_type(a, ttr, fname); spl_type_node_t *mtn = tn(a->sema, mt); if (mt && mtn && mtn->kind == SPL_TYPE_FN) { out->fn_tid = mt; spl_ir_func_ref_t fid = a2ir_fn_of(a, mt); if (fid) { out->callee = const_fnref(a, fc, mt, fid); return 1; } } } spl_ir_node_ref_t bv = lower_expr(a, fc, bref); spl_type_id_t vt = underlying(a->sema, node_type(fc, bv)); spl_type_node_t *vtt = vt ? tn(a->sema, vt) : NULL; if (vtt && vtt->kind == SPL_TYPE_PTR) { vt = underlying(a->sema, vtt->ptr_pointee); vtt = tn(a->sema, vt); } /* 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; spl_ir_func_ref_t fid = a2ir_fn_of(a, mt); if (fid) { out->callee = const_fnref(a, fc, mt, fid); return 1; } } } } out->callee = lower_expr(a, fc, base); out->fn_tid = node_type(fc, out->callee); if (out->fn_tid) { spl_type_node_t *ft = tn(a->sema, underlying(a->sema, out->fn_tid)); if (ft && ft->kind != SPL_TYPE_FN) { diag(a, fc, base, "call requires function type"); return 0; } return 1; } return 0; } static spl_ir_node_ref_t lower_field(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *pf) { const char *fname = pf->postfix_expr.field_expr; spl_type_id_t ttr = type_of_type_ref(a, fc, pf->postfix_expr.primary_expr); if (ttr) { spl_type_node_t *ttr_t = tn(a->sema, ttr); if (ttr_t && ttr_t->kind == SPL_TYPE_ENUM) { isize vidx = enum_variant_index(a, ttr, fname); 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; } spl_ir_node_ref_t base = lower_expr(a, fc, pf->postfix_expr.primary_expr); if (!base) return 0; spl_type_id_t bt = underlying(a->sema, node_type(fc, base)); spl_type_node_t *tt = tn(a->sema, bt); if (!tt) return 0; spl_type_id_t agg_tid = bt; spl_ir_node_ref_t agg_val = base; if (tt->kind == SPL_TYPE_PTR) { agg_tid = underlying(a->sema, tt->ptr_pointee); tt = tn(a->sema, agg_tid); agg_val = emit_load(a, fc, agg_tid, base); } if (!tt) return 0; if (tt->kind == SPL_TYPE_SLICE) { if (strcmp(fname, "ptr") == 0) { spl_type_id_t ft = spl_type_ptr((spl_type_t *)&a->sema->type, tt->slice_element); return emit_agg_extract(a, fc, agg_tid, ft, 0, agg_val); } if (strcmp(fname, "len") == 0) return emit_agg_extract(a, fc, agg_tid, kw_type(a, "usize"), 1, agg_val); diag(a, fc, 0, "unknown slice field"); return 0; } if (tt->kind == SPL_TYPE_RANGE) { if (strcmp(fname, "begin") == 0) return emit_agg_extract(a, fc, agg_tid, tt->range_element, 0, agg_val); if (strcmp(fname, "end") == 0) return emit_agg_extract(a, fc, agg_tid, tt->range_element, 1, agg_val); diag(a, fc, 0, "unknown range field"); return 0; } isize fidx = agg_member_index(a, agg_tid, fname); if (fidx < 0) { diag(a, fc, 0, "unknown field"); return 0; } spl_type_id_t ft = agg_field_tid_at(a, agg_tid, fidx); return emit_agg_extract(a, fc, agg_tid, ft, fidx, agg_val); } static spl_ir_node_ref_t lower_postfix(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *pf) { switch (pf->postfix_expr.kind) { case SPL_AST_CALL_EXPR: { callee_t cal; if (!resolve_callee(a, fc, pf->postfix_expr.primary_expr, &cal)) return 0; spl_type_node_t *ft = tn(a->sema, underlying(a->sema, cal.fn_tid)); usize nparams = (ft && ft->kind == SPL_TYPE_FN) ? ft->fn_type.params.size : 0; spl_ast_node_ref_vec_t *args = &pf->postfix_expr.call_expr; spl_ir_node_ref_t av[64]; usize na = args->size < 64 ? args->size : 64; for (usize i = 0; i < na; i++) { spl_type_id_t pt = 0; if (i < nparams && ft && ft->kind == SPL_TYPE_FN) pt = ft->fn_type.params.data[i]; fc->hint = pt; spl_ir_node_ref_t v = lower_expr(a, fc, args->data[i]); fc->hint = 0; if (pt) v = coerce_to(a, fc, v, node_type(fc, v), pt); av[i] = v; } return emit_call(a, fc, cal.fn_tid, cal.callee, av, na); } case SPL_AST_FIELD_EXPR: return lower_field(a, fc, pf); case SPL_AST_DEREF_EXPR: { spl_ir_node_ref_t p = lower_expr(a, fc, pf->postfix_expr.primary_expr); spl_type_id_t pt = underlying(a->sema, node_type(fc, p)); spl_type_node_t *tt = tn(a->sema, pt); if (!tt || tt->kind != SPL_TYPE_PTR) { diag(a, fc, 0, ".* requires pointer"); return 0; } spl_type_id_t pointee = underlying(a->sema, tt->ptr_pointee); return emit_load(a, fc, pointee, p); } case SPL_AST_INDEX_EXPR: { spl_type_id_t elem = 0; spl_ir_node_ref_t addr = index_addr(a, fc, pf, &elem); if (!addr) return 0; return emit_load(a, fc, elem, addr); } case SPL_AST_SLICE_EXPR: { spl_type_id_t bt = 0; spl_ir_node_ref_t base_lv = lower_lvalue(a, fc, pf->postfix_expr.primary_expr, &bt); spl_type_node_t *tt = tn(a->sema, underlying(a->sema, bt)); if (!tt || (tt->kind != SPL_TYPE_ARRAY && tt->kind != SPL_TYPE_SLICE)) { diag(a, fc, 0, "slice requires array/slice"); return 0; } spl_type_id_t elem = tt->kind == SPL_TYPE_ARRAY ? tt->array_type.element : tt->slice_element; spl_type_id_t slice_t = spl_type_slice((spl_type_t *)&a->sema->type, elem); spl_ir_node_ref_t base_ptr = 0; spl_ir_node_ref_t total_len = 0; if (tt->kind == SPL_TYPE_ARRAY) { base_ptr = base_lv; total_len = const_int(a, fc, kw_type(a, "usize"), tt->array_type.len); } else { spl_ir_node_ref_t slv = emit_load(a, fc, bt, base_lv); spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, elem); base_ptr = emit_agg_extract(a, fc, bt, ep, 0, slv); total_len = emit_agg_extract(a, fc, bt, kw_type(a, "usize"), 1, slv); } spl_ir_node_ref_t beg = 0, end = 0; if (pf->postfix_expr.slice_expr.begin) beg = lower_expr(a, fc, pf->postfix_expr.slice_expr.begin); else beg = const_int(a, fc, kw_type(a, "usize"), 0); if (pf->postfix_expr.slice_expr.end) end = lower_expr(a, fc, pf->postfix_expr.slice_expr.end); spl_type_id_t iszt = kw_type(a, "isize"); spl_ir_node_ref_t ptr = emit_offset(a, fc, elem, base_ptr, coerce_to(a, fc, beg, node_type(fc, beg), iszt)); spl_ir_node_ref_t len = 0; spl_ir_node_ref_t begu = coerce_to(a, fc, beg, node_type(fc, beg), kw_type(a, "usize")); if (end) { len = emit_arith(a, fc, SPL_IR_ARITH_SUB, kw_type(a, "usize"), coerce_to(a, fc, end, node_type(fc, end), kw_type(a, "usize")), begu); } else { len = emit_arith(a, fc, SPL_IR_ARITH_SUB, kw_type(a, "usize"), total_len, begu); } spl_ir_node_ref_t sl = emit_agg_construct(a, fc, slice_t); agg_construct_add(a, fc, sl, ptr); agg_construct_add(a, fc, sl, len); return sl; } case SPL_AST_AS_EXPR: { spl_ir_node_ref_t v = lower_expr(a, fc, pf->postfix_expr.primary_expr); spl_type_id_t dt = resolve_type_expr(a, fc, pf->postfix_expr.type_expr); if (!dt) return v; return coerce_to(a, fc, v, node_type(fc, v), dt); } default: return 0; } } static spl_ir_node_ref_t lower_binary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *n) { spl_ast_node_ref_t lr = n->expr.op_expr.left; spl_ast_node_ref_t rr = n->expr.op_expr.right; switch (n->expr.op) { case SPL_AST_ADD_EXPR: case SPL_AST_SUB_EXPR: case SPL_AST_MUL_EXPR: case SPL_AST_DIV_EXPR: case SPL_AST_MOD_EXPR: case SPL_AST_BITOR_EXPR: case SPL_AST_BITXOR_EXPR: case SPL_AST_BITAND_EXPR: case SPL_AST_LSHIFT_EXPR: case SPL_AST_RSHIFT_EXPR: { spl_ir_node_ref_t l = lower_expr(a, fc, lr); 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)); if ((n->expr.op == SPL_AST_ADD_EXPR || n->expr.op == SPL_AST_SUB_EXPR) && is_ptr_type(a->sema, lt) && is_int_type(a->sema, rt)) { spl_type_node_t *ltt = tn(a->sema, lt); spl_type_id_t elem = underlying(a->sema, ltt->ptr_pointee); spl_ir_node_ref_t off = coerce_to(a, fc, r, rt, kw_type(a, "isize")); if (n->expr.op == SPL_AST_SUB_EXPR) { spl_ir_node_ref_t zero = const_int(a, fc, kw_type(a, "isize"), 0); off = emit_arith(a, fc, SPL_IR_ARITH_SUB, kw_type(a, "isize"), zero, off); } return emit_offset(a, fc, elem, l, off); } spl_type_id_t res = lt; if (!type_same(a->sema, lt, rt)) { if (expr_is_int_literal(a, lr) && is_int_type(a->sema, rt)) res = rt; else if (expr_is_int_literal(a, rr) && is_int_type(a->sema, lt)) res = lt; else res = lt; } spl_ir_kind_t k; switch (n->expr.op) { case SPL_AST_ADD_EXPR: k = SPL_IR_ARITH_ADD; break; case SPL_AST_SUB_EXPR: k = SPL_IR_ARITH_SUB; break; case SPL_AST_MUL_EXPR: k = SPL_IR_ARITH_MUL; break; case SPL_AST_DIV_EXPR: k = SPL_IR_ARITH_DIV; break; case SPL_AST_MOD_EXPR: k = SPL_IR_ARITH_REM; break; case SPL_AST_BITOR_EXPR: k = SPL_IR_ARITH_OR; break; case SPL_AST_BITXOR_EXPR: k = SPL_IR_ARITH_XOR; break; case SPL_AST_BITAND_EXPR: k = SPL_IR_ARITH_AND; break; case SPL_AST_LSHIFT_EXPR: k = SPL_IR_ARITH_SHL; break; default: k = SPL_IR_ARITH_SHR; break; } spl_ir_node_ref_t l2 = coerce_to(a, fc, l, lt, res); spl_ir_node_ref_t r2 = coerce_to(a, fc, r, rt, res); return emit_arith(a, fc, k, res, l2, r2); } case SPL_AST_CMPEQ_EXPR: case SPL_AST_CMPNE_EXPR: case SPL_AST_CMP_LE_EXPR: case SPL_AST_CMP_GE_EXPR: case SPL_AST_CMP_LT_EXPR: case SPL_AST_CMP_GT_EXPR: { spl_ir_node_ref_t l = lower_expr(a, fc, lr); 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_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, le, l); r = enum_tag_of(a, fc, re, r); lt = tag_t; rt = tag_t; } spl_type_id_t res = lt; if (!type_same(a->sema, lt, rt)) { if (is_int_type(a->sema, lt) && is_int_type(a->sema, rt)) res = expr_is_int_literal(a, lr) ? rt : lt; else res = lt; } l = coerce_to(a, fc, l, node_type(fc, l), res); r = coerce_to(a, fc, r, node_type(fc, r), res); spl_ir_kind_t k; switch (n->expr.op) { case SPL_AST_CMPEQ_EXPR: k = SPL_IR_CMP_EQ; break; case SPL_AST_CMPNE_EXPR: k = SPL_IR_CMP_NE; break; case SPL_AST_CMP_LE_EXPR: k = SPL_IR_CMP_LE; break; case SPL_AST_CMP_GE_EXPR: k = SPL_IR_CMP_GE; break; case SPL_AST_CMP_LT_EXPR: k = SPL_IR_CMP_LT; break; default: k = SPL_IR_CMP_GT; break; } return emit_cmp(a, fc, k, res, l, r); } case SPL_AST_BOOLAND_EXPR: case SPL_AST_BOOLOR_EXPR: { spl_type_id_t bt = kw_type(a, "bool"); spl_ir_node_ref_t l = lower_expr(a, fc, lr); usize t = new_block(fc), f = new_block(fc), join = new_block(fc); spl_ir_node_ref_t slot = emit_alloca(a, fc, bt); emit_br(a, fc, l, t, f); begin_block(fc, t); if (n->expr.op == SPL_AST_BOOLAND_EXPR) { spl_ir_node_ref_t r = lower_expr(a, fc, rr); emit_store(a, fc, bt, slot, r); } else { emit_store(a, fc, bt, slot, const_bool(a, fc, 1)); } emit_jmp(a, fc, join); begin_block(fc, f); if (n->expr.op == SPL_AST_BOOLAND_EXPR) { emit_store(a, fc, bt, slot, const_bool(a, fc, 0)); } else { spl_ir_node_ref_t r = lower_expr(a, fc, rr); emit_store(a, fc, bt, slot, r); } emit_jmp(a, fc, join); begin_block(fc, join); return emit_load(a, fc, bt, slot); } default: return 0; } } static spl_ir_node_ref_t lower_range_value(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *n) { 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); agg_construct_add(a, fc, r, e); return r; } static spl_ir_node_ref_t lower_compound_op(spl_ast2ir_t *a, fnctx_t *fc, int op, spl_type_id_t tid, spl_ir_node_ref_t cur, spl_ir_node_ref_t rhs) { spl_ir_kind_t k; switch (op) { case SPL_AST_ASSIGN_ADD_EXPR: k = SPL_IR_ARITH_ADD; break; case SPL_AST_ASSIGN_sUB_EXPR: k = SPL_IR_ARITH_SUB; break; case SPL_AST_ASSIGN_MUL_EXPR: k = SPL_IR_ARITH_MUL; break; case SPL_AST_ASSIGN_DIV_EXPR: k = SPL_IR_ARITH_DIV; break; case SPL_AST_ASSIGN_MOD_EXPR: k = SPL_IR_ARITH_REM; break; case SPL_AST_ASSIGN_AND_EXPR: k = SPL_IR_ARITH_AND; break; case SPL_AST_ASSIGN_OR_EXPR: k = SPL_IR_ARITH_OR; break; case SPL_AST_ASSIGN_XOR_EXPR: k = SPL_IR_ARITH_XOR; break; case SPL_AST_ASSIGN_LSHIFT_EXPR: k = SPL_IR_ARITH_SHL; break; case SPL_AST_ASSIGN_USHIFT_EXPR: k = SPL_IR_ARITH_SHR; break; default: return rhs; } spl_ir_node_ref_t r = coerce_to(a, fc, rhs, node_type(fc, rhs), tid); return emit_arith(a, fc, k, tid, cur, r); } /* 字段链赋o.a.b = rhs:直接按字节地址写回(含指针中间字段*/ static void field_assign(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t target, spl_ir_node_ref_t rhs) { spl_type_id_t ft = 0; spl_ir_node_ref_t addr = lower_field_address(a, fc, target, &ft); if (!addr || !ft) { diag(a, fc, target, "field assignment: unsupported base"); return; } rhs = coerce_to(a, fc, rhs, node_type(fc, rhs), ft); emit_store(a, fc, ft, addr, rhs); } static spl_ir_node_ref_t lower_assign(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *n) { spl_ast_node_ref_t lr = n->expr.op_expr.left; spl_ast_node_ref_t rr = n->expr.op_expr.right; spl_ast_node_t *ln = node_at(a->sema, lr); if (!ln || ln->kind != SPL_AST_EXPR) return 0; int compound = n->expr.op != SPL_AST_ASSIGN_EXPR; spl_ast_node_t *pf = NULL; if (ln->expr.op == SPL_AST_POSTFIX_EXPR) pf = node_at(a->sema, ln->expr.op_expr.left); if (ln->expr.op == SPL_AST_PRIMARY_EXPR) { 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); 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, 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, lt, cur, v); v = coerce_to(a, fc, v, node_type(fc, v), lt); emit_store(a, fc, lt, target, v); return v; } } if (ln->expr.op == SPL_AST_PREFIX_EXPR) { spl_ast_node_t *pp = node_at(a->sema, ln->expr.op_expr.left); if (pp && pp->prefix_expr.kind == SPL_AST_ASTERISK_EXPR) { spl_ir_node_ref_t p = lower_expr(a, fc, pp->prefix_expr.postfix_expr); spl_type_id_t pt = underlying(a->sema, node_type(fc, p)); spl_type_node_t *tt = tn(a->sema, pt); if (tt && tt->kind == SPL_TYPE_PTR) { spl_type_id_t pointee = underlying(a->sema, tt->ptr_pointee); spl_ir_node_ref_t cur = compound ? emit_load(a, fc, pointee, p) : 0; spl_ir_node_ref_t v = lower_expr(a, fc, rr); if (compound) v = lower_compound_op(a, fc, n->expr.op, pointee, cur, v); v = coerce_to(a, fc, v, node_type(fc, v), pointee); emit_store(a, fc, pointee, p, v); return v; } } } if (pf && pf->postfix_expr.kind == SPL_AST_DEREF_EXPR) { spl_ir_node_ref_t p = lower_expr(a, fc, pf->postfix_expr.primary_expr); spl_type_id_t pt = underlying(a->sema, node_type(fc, p)); spl_type_node_t *tt = tn(a->sema, pt); if (!tt || tt->kind != SPL_TYPE_PTR) { diag(a, fc, lr, ".* requires pointer"); return 0; } spl_type_id_t pointee = underlying(a->sema, tt->ptr_pointee); spl_ir_node_ref_t cur = compound ? emit_load(a, fc, pointee, p) : 0; spl_ir_node_ref_t v = lower_expr(a, fc, rr); if (compound) v = lower_compound_op(a, fc, n->expr.op, pointee, cur, v); v = coerce_to(a, fc, v, node_type(fc, v), pointee); emit_store(a, fc, pointee, p, v); return v; } if (pf && pf->postfix_expr.kind == SPL_AST_INDEX_EXPR) { spl_type_id_t elem = 0; spl_ir_node_ref_t addr = index_addr(a, fc, pf, &elem); if (!addr) return 0; spl_ir_node_ref_t cur = compound ? emit_load(a, fc, elem, addr) : 0; spl_ir_node_ref_t v = lower_expr(a, fc, rr); if (compound) v = lower_compound_op(a, fc, n->expr.op, elem, cur, v); v = coerce_to(a, fc, v, node_type(fc, v), elem); emit_store(a, fc, elem, addr, v); return v; } if (pf && pf->postfix_expr.kind == SPL_AST_FIELD_EXPR) { spl_ir_node_ref_t v = lower_expr(a, fc, rr); if (compound) { spl_ir_node_ref_t cur = lower_expr(a, fc, lr); v = lower_compound_op(a, fc, n->expr.op, node_type(fc, cur), cur, v); } field_assign(a, fc, lr, v); return v; } diag(a, fc, lr, "unsupported assignment target"); return 0; } static spl_ir_node_ref_t lower_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { spl_ast_node_t *n = node_at(a->sema, ref); if (!n || n->kind != SPL_AST_EXPR) return 0; switch (n->expr.op) { case SPL_AST_PRIMARY_EXPR: return lower_primary(a, fc, node_at(a->sema, n->expr.op_expr.left)); case SPL_AST_PREFIX_EXPR: return lower_prefix(a, fc, node_at(a->sema, n->expr.op_expr.left)); case SPL_AST_POSTFIX_EXPR: return lower_postfix(a, fc, node_at(a->sema, n->expr.op_expr.left)); case SPL_AST_RANGE_EXPR: return lower_range_value(a, fc, n); case SPL_AST_ASSIGN_EXPR: case SPL_AST_ASSIGN_ADD_EXPR: case SPL_AST_ASSIGN_sUB_EXPR: case SPL_AST_ASSIGN_MUL_EXPR: case SPL_AST_ASSIGN_DIV_EXPR: case SPL_AST_ASSIGN_MOD_EXPR: case SPL_AST_ASSIGN_AND_EXPR: case SPL_AST_ASSIGN_OR_EXPR: case SPL_AST_ASSIGN_XOR_EXPR: case SPL_AST_ASSIGN_LSHIFT_EXPR: case SPL_AST_ASSIGN_USHIFT_EXPR: return lower_assign(a, fc, n); default: return lower_binary(a, fc, n); } } /* ================================================================ * 语句 * ================================================================ */ static void lower_block(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_vec_t *block) { env_push(fc); for (usize i = 0; i < block->size; i++) lower_stmt(a, fc, block->data[i]); if (!fc->terminated) emit_scope_defers(a, fc, fc->env.size - 1); env_pop(fc); } /* 登记 defer 体到当前作用*/ static void lower_defer(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { if (!fc->env.size) env_push(fc); vec_push(fc->env.data[fc->env.size - 1].defers, ref); } /* 逆序发射 scope_idx 作用域的 defer,并清空 */ static void emit_scope_defers(spl_ast2ir_t *a, fnctx_t *fc, usize scope_idx) { if (scope_idx >= fc->env.size) return; for (usize i = fc->env.data[scope_idx].defers.size; i > 0; i--) { spl_ast_node_t *d = node_at(a->sema, fc->env.data[scope_idx].defers.data[i - 1]); if (d) { lower_block(a, fc, &d->block_item.defer_statement.block_or_statement); } } vec_free(fc->env.data[scope_idx].defers); vec_init(fc->env.data[scope_idx].defers); } /* 从最内层作用域发射到 mark(含),用于 ret / break / continue */ static void emit_defers_from(spl_ast2ir_t *a, fnctx_t *fc, usize mark) { for (usize i = fc->env.size; i > mark; i--) emit_scope_defers(a, fc, i - 1); } static void lower_type_decl(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *td) { spl_type_id_t tid = resolve_type_expr(a, fc, td->type_decl.type_expr); env_add(fc, td->type_decl.name, td->resolved_def_id, tid, 0, 0, 1, 0); } static void lower_var_decl(spl_ast2ir_t *a, fnctx_t *fc, const char *name, spl_def_id_t def_id, spl_ast_node_ref_t texpr, spl_ast_node_ref_t initexpr) { spl_type_id_t tid = texpr ? resolve_type_expr(a, fc, texpr) : 0; spl_ir_node_ref_t v = 0; spl_type_id_t vt = 0; if (initexpr) { fc->hint = tid; v = lower_expr(a, fc, initexpr); fc->hint = 0; vt = node_type(fc, v); if (!tid && vt) tid = vt; } if (!tid) tid = kw_type(a, "void"); spl_ir_node_ref_t slot = emit_alloca(a, fc, tid); if (v && vt && tid) { if (!type_same(a->sema, vt, tid)) v = coerce_to(a, fc, v, vt, tid); emit_store(a, fc, tid, slot, v); } env_add(fc, name, def_id, tid, slot, 0, 0, 1); } static void lower_if(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { spl_ir_node_ref_t c = lower_expr(a, fc, b->block_item.if_statement.expr); int has_else = b->block_item.if_statement.else_block.size > 0; usize then_b = new_block(fc); usize else_b = has_else ? new_block(fc) : 0; usize exit_b = new_block(fc); emit_br(a, fc, c, then_b, has_else ? else_b : exit_b); begin_block(fc, then_b); lower_block(a, fc, &b->block_item.if_statement.if_block); emit_jmp(a, fc, exit_b); if (has_else) { begin_block(fc, else_b); lower_block(a, fc, &b->block_item.if_statement.else_block); emit_jmp(a, fc, exit_b); } begin_block(fc, exit_b); } static void lower_while(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { usize cond_b = new_block(fc); usize body_b = new_block(fc); usize exit_b = new_block(fc); begin_block(fc, cond_b); spl_ir_node_ref_t c = lower_expr(a, fc, b->block_item.while_statement.expr); emit_br(a, fc, c, body_b, exit_b); begin_block(fc, body_b); ir_loop_t lp = {exit_b, cond_b, fc->env.size}; vec_push(fc->loops, lp); lower_block(a, fc, &b->block_item.while_statement.while_block); emit_jmp(a, fc, cond_b); vec_pop(fc->loops); begin_block(fc, exit_b); } static void lower_loop(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { usize body_b = new_block(fc); usize exit_b = new_block(fc); begin_block(fc, body_b); ir_loop_t lp = {exit_b, body_b, fc->env.size}; vec_push(fc->loops, lp); lower_block(a, fc, &b->block_item.loop_statement.loop_block); emit_jmp(a, fc, body_b); vec_pop(fc->loops); begin_block(fc, exit_b); } enum { FOR_RANGE, FOR_ARRAY, FOR_SLICE }; typedef struct { int kind; spl_type_id_t elem_tid; spl_ir_node_ref_t len; /* 长度节点 = 无界 */ spl_ir_node_ref_t begin_slot; /* range: begin */ spl_ir_node_ref_t base_slot; /* array/slice: 元素基址*/ } for_seq_t; static void for_seq_setup(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t eref, for_seq_t *s) { memset(s, 0, sizeof *s); spl_ast_node_t *n = node_at(a->sema, eref); if (n && n->kind == SPL_AST_EXPR && n->expr.op == SPL_AST_RANGE_EXPR) { s->kind = FOR_RANGE; spl_ir_node_ref_t beg = lower_expr(a, fc, n->expr.op_expr.left); s->elem_tid = underlying(a->sema, node_type(fc, beg)); s->begin_slot = emit_alloca(a, fc, s->elem_tid); emit_store(a, fc, s->elem_tid, s->begin_slot, beg); if (n->expr.op_expr.right) { spl_ir_node_ref_t end = lower_expr(a, fc, n->expr.op_expr.right); spl_ir_node_ref_t b = emit_load(a, fc, s->elem_tid, s->begin_slot); s->len = emit_arith(a, fc, SPL_IR_ARITH_SUB, s->elem_tid, coerce_to(a, fc, end, node_type(fc, end), s->elem_tid), b); } return; } spl_type_id_t bt = 0; spl_ir_node_ref_t base_lv = lower_lvalue(a, fc, eref, &bt); spl_type_node_t *tt = bt ? tn(a->sema, underlying(a->sema, bt)) : NULL; if (base_lv && tt && tt->kind == SPL_TYPE_ARRAY) { s->kind = FOR_ARRAY; s->elem_tid = tt->array_type.element; s->base_slot = base_lv; s->len = const_int(a, fc, kw_type(a, "usize"), tt->array_type.len); return; } if (base_lv && tt && tt->kind == SPL_TYPE_SLICE) { s->kind = FOR_SLICE; s->elem_tid = tt->slice_element; spl_ir_node_ref_t slv = emit_load(a, fc, bt, base_lv); spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, s->elem_tid); s->base_slot = emit_alloca(a, fc, ep); s->len = emit_alloca(a, fc, kw_type(a, "usize")); emit_store(a, fc, ep, s->base_slot, emit_agg_extract(a, fc, bt, ep, 0, slv)); emit_store(a, fc, kw_type(a, "usize"), s->len, emit_agg_extract(a, fc, bt, kw_type(a, "usize"), 1, slv)); return; } spl_ir_node_ref_t v = lower_expr(a, fc, eref); spl_type_id_t vt = underlying(a->sema, node_type(fc, v)); spl_type_node_t *vtt = vt ? tn(a->sema, vt) : NULL; if (vtt && vtt->kind == SPL_TYPE_SLICE) { s->kind = FOR_SLICE; s->elem_tid = vtt->slice_element; spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, s->elem_tid); s->base_slot = emit_alloca(a, fc, ep); s->len = emit_alloca(a, fc, kw_type(a, "usize")); emit_store(a, fc, ep, s->base_slot, emit_agg_extract(a, fc, vt, ep, 0, v)); emit_store(a, fc, kw_type(a, "usize"), s->len, emit_agg_extract(a, fc, vt, kw_type(a, "usize"), 1, v)); return; } if (vtt && vtt->kind == SPL_TYPE_ARRAY) { spl_type_id_t fat = 0; spl_ir_node_ref_t faddr = lower_field_address(a, fc, eref, &fat); if (faddr) { s->kind = FOR_ARRAY; s->elem_tid = vtt->array_type.element; s->base_slot = faddr; s->len = const_int(a, fc, kw_type(a, "usize"), vtt->array_type.len); return; } } diag(a, fc, eref, "for: sequence must be Range/[]T/[N]T"); } static void lower_for(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { spl_ast_node_ref_vec_t *expr_vec = &b->block_item.for_statement.expr_vec; char **id_data = b->block_item.for_statement.ident_vec.data; usize id_size = b->block_item.for_statement.ident_vec.size; usize nseq = expr_vec->size; if (nseq != id_size || nseq > 8) { diag(a, fc, 0, "for: sequence/variable count mismatch"); return; } for_seq_t seqs[8]; for (usize i = 0; i < nseq; i++) for_seq_setup(a, fc, expr_vec->data[i], &seqs[i]); spl_type_id_t iszt = kw_type(a, "isize"); spl_ir_node_ref_t min_slot = 0; int has_finite = 0; for (usize i = 0; i < nseq; i++) if (seqs[i].len) has_finite = 1; if (has_finite) { spl_ir_node_ref_t m = 0; for (usize i = 0; i < nseq; i++) { if (!seqs[i].len) continue; 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 { spl_ir_node_ref_t c = emit_cmp(a, fc, SPL_IR_CMP_LT, iszt, l, m); m = emit_select(a, fc, iszt, c, l, m); } } min_slot = emit_alloca(a, fc, iszt); emit_store(a, fc, iszt, min_slot, m); } spl_ir_node_ref_t ctr = emit_alloca(a, fc, iszt); emit_store(a, fc, iszt, ctr, const_int(a, fc, iszt, 0)); env_push(fc); for (usize i = 0; i < nseq; i++) env_add(fc, id_data[i], 0, seqs[i].elem_tid, 0, 0, 0, 0); usize cond_b = new_block(fc); usize body_b = new_block(fc); usize exit_b = new_block(fc); begin_block(fc, cond_b); if (has_finite) { spl_ir_node_ref_t cur = emit_load(a, fc, iszt, ctr); spl_ir_node_ref_t ml = emit_load(a, fc, iszt, min_slot); spl_ir_node_ref_t c = emit_cmp(a, fc, SPL_IR_CMP_LT, iszt, cur, ml); emit_br(a, fc, c, body_b, exit_b); } else { emit_jmp(a, fc, body_b); } begin_block(fc, body_b); for (usize i = 0; i < nseq; i++) { for_seq_t *s = &seqs[i]; spl_ir_node_ref_t cur = emit_load(a, fc, iszt, ctr); spl_ir_node_ref_t v = 0; if (s->kind == FOR_RANGE) { spl_ir_node_ref_t bg = emit_load(a, fc, s->elem_tid, s->begin_slot); 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 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]); if (it) { it->tid = s->elem_tid; it->value = v; } } ir_loop_t lp = {exit_b, cond_b, fc->env.size}; vec_push(fc->loops, lp); lower_block(a, fc, &b->block_item.for_statement.block); spl_ir_node_ref_t cur2 = emit_load(a, fc, iszt, ctr); spl_ir_node_ref_t one = const_int(a, fc, iszt, 1); spl_ir_node_ref_t nxt = emit_arith(a, fc, SPL_IR_ARITH_ADD, iszt, cur2, one); emit_store(a, fc, iszt, ctr, nxt); emit_jmp(a, fc, cond_b); vec_pop(fc->loops); env_pop(fc); begin_block(fc, exit_b); } static void lower_ret(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { emit_defers_from(a, fc, 0); if (b->block_item.ret_statement.expr) { fc->hint = fc->ret_tid; spl_ir_node_ref_t v = lower_expr(a, fc, b->block_item.ret_statement.expr); fc->hint = 0; spl_type_id_t vt = node_type(fc, v); if (fc->ret_tid && vt && !type_same(a->sema, vt, fc->ret_tid)) v = coerce_to(a, fc, v, vt, fc->ret_tid); emit_ret(a, fc, fc->ret_tid, v); } else { emit_ret(a, fc, fc->ret_tid, 0); } } static void lower_match(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { spl_ast_node_ref_vec_t *arms = &b->block_item.match_statement.paced_exprs; spl_ast_node_ref_vec_t *bodies = &b->block_item.match_statement.match_block; if (arms->size != bodies->size) { diag(a, fc, 0, "match: arm pattern/body count mismatch"); return; } spl_ir_node_ref_t subj = lower_expr(a, fc, b->block_item.match_statement.expr); spl_type_id_t st = underlying(a->sema, node_type(fc, subj)); spl_type_node_t *tt = tn(a->sema, st); if (tt && tt->kind == SPL_TYPE_PTR) { st = underlying(a->sema, tt->ptr_pointee); tt = tn(a->sema, st); subj = emit_load(a, fc, st, subj); } int is_enum = tt && tt->kind == SPL_TYPE_ENUM; int is_int = tt && tt->kind == SPL_TYPE_INT; if (!is_enum && !is_int) { diag(a, fc, 0, "match subject must be enum/union/integer"); return; } spl_ir_node_ref_t subj_slot = emit_alloca(a, fc, st); emit_store(a, fc, st, subj_slot, subj); spl_type_id_t tag_t = enum_tag_tid(a); spl_ir_node_ref_t tag_slot = 0; if (is_enum) { spl_ir_node_ref_t tagv = emit_agg_extract(a, fc, st, tag_t, 0, emit_load(a, fc, st, subj_slot)); tag_slot = emit_alloca(a, fc, tag_t); emit_store(a, fc, tag_t, tag_slot, tagv); } usize exit_b = new_block(fc); for (usize i = 0; i < arms->size; i++) { spl_ast_node_t *pk = node_at(a->sema, arms->data[i]); usize body_b = new_block(fc); usize next_b = (i + 1 < arms->size) ? new_block(fc) : 0; int is_default = !pk || (!pk->packed_expr.ident && !pk->packed_expr.expr); if (is_default) { emit_jmp(a, fc, body_b); } else { spl_ir_node_ref_t cond = 0; if (is_enum && pk->packed_expr.ident) { isize vidx = enum_variant_index(a, st, pk->packed_expr.ident); if (vidx < 0) vidx = 0; spl_ir_node_ref_t tv = emit_load(a, fc, tag_t, tag_slot); spl_ir_node_ref_t idxc = const_int(a, fc, tag_t, (usize)vidx); cond = emit_cmp(a, fc, SPL_IR_CMP_EQ, tag_t, tv, idxc); } else if (is_int && pk->packed_expr.expr) { spl_ir_node_ref_t sv = emit_load(a, fc, st, subj_slot); spl_ir_node_ref_t pv = lower_expr(a, fc, pk->packed_expr.expr); pv = coerce_to(a, fc, pv, node_type(fc, pv), st); cond = emit_cmp(a, fc, SPL_IR_CMP_EQ, st, sv, pv); } if (cond) emit_br(a, fc, cond, body_b, next_b ? next_b : exit_b); else emit_jmp(a, fc, body_b); } begin_block(fc, body_b); env_push(fc); if (is_enum && pk && pk->packed_expr.ident && pk->packed_expr.bind_ident) { isize vidx = enum_variant_index(a, st, pk->packed_expr.ident); 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); env_add(fc, pk->packed_expr.bind_ident, 0, pt, bslot, 0, 0, 0); } } spl_ast_node_t *body = node_at(a->sema, bodies->data[i]); if (body && body->kind == SPL_AST_EXPR && body->expr.op == SPL_AST_PRIMARY_EXPR) { spl_ast_node_t *pn = node_at(a->sema, body->expr.op_expr.left); if (pn && pn->primary_expr.kind == SPL_AST_BLOCK_EXPR) lower_block(a, fc, &pn->primary_expr.block_expr); else lower_expr(a, fc, bodies->data[i]); } else { lower_expr(a, fc, bodies->data[i]); } env_pop(fc); emit_jmp(a, fc, exit_b); if (next_b) begin_block(fc, next_b); } begin_block(fc, exit_b); } static void lower_stmt(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { spl_ast_node_t *b = node_at(a->sema, ref); if (!b) return; if (b->kind == SPL_AST_EXPR) { if (b->expr.op == SPL_AST_PRIMARY_EXPR) { spl_ast_node_t *pn = node_at(a->sema, b->expr.op_expr.left); if (pn && pn->primary_expr.kind == SPL_AST_BLOCK_EXPR) { lower_block_expr(a, fc, &pn->primary_expr.block_expr); return; } } lower_expr(a, fc, ref); return; } switch (b->block_item.kind) { case SPL_AST_VARDECL: { spl_ast_node_t *vd = node_at(a->sema, b->block_item.var_decl); if (vd) lower_var_decl(a, fc, vd->var_decl.name, vd->resolved_def_id, vd->var_decl.type_expr, vd->var_decl.expr); break; } case SPL_AST_CONSTDECL: { spl_ast_node_t *cd = node_at(a->sema, b->block_item.const_decl); if (cd) lower_var_decl(a, fc, cd->const_decl.name, cd->resolved_def_id, cd->const_decl.type_expr, cd->const_decl.expr); break; } case SPL_AST_TYPEDECL: { spl_ast_node_t *td = node_at(a->sema, b->block_item.type_decl); if (td) lower_type_decl(a, fc, td); break; } case SPL_AST_IF_STATEMENT: lower_if(a, fc, b); break; case SPL_AST_IFVAR_STATEMENT: diag(a, fc, ref, "if-var not supported"); break; case SPL_AST_WHILE_STATEMENT: lower_while(a, fc, b); break; case SPL_AST_LOOP_STATEMENT: lower_loop(a, fc, b); break; case SPL_AST_FOR_STATEMENT: lower_for(a, fc, b); break; case SPL_AST_MATCH_STATEMENT: lower_match(a, fc, b); break; case SPL_AST_RET_STATEMENT: lower_ret(a, fc, b); break; case SPL_AST_BREAK_STATEMENT: { if (!fc->loops.size) { diag(a, fc, ref, "break outside loop"); break; } ir_loop_t *lp = &fc->loops.data[fc->loops.size - 1]; emit_defers_from(a, fc, lp->env_mark); emit_jmp(a, fc, lp->brk); break; } case SPL_AST_CONTINUE_STATEMENT: { if (!fc->loops.size) { diag(a, fc, ref, "continue outside loop"); break; } ir_loop_t *lp = &fc->loops.data[fc->loops.size - 1]; emit_defers_from(a, fc, lp->env_mark); emit_jmp(a, fc, lp->cont); break; } case SPL_AST_DEFER_STATEMENT: lower_defer(a, fc, ref); break; case SPL_AST_EXPR_STATEMENT: if (b->block_item.expr_statement) lower_expr(a, fc, b->block_item.expr_statement); break; default: break; } } /* ================================================================ * 函数 * ================================================================ */ 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 唯一�?*/ for (usize i = 1; i < a->ir.funcs.size; i++) { if (a->ir.funcs.data[i].fn_tid == fn_tid) return i; } return 0; } static void lower_func_body(spl_ast2ir_t *a, spl_ir_func_ref_t fid, spl_type_id_t fn_tid, spl_ast_node_ref_t def_ref, spl_type_id_t ns_tid) { spl_ast_node_t *fn = node_at(a->sema, def_ref); if (!fn) return; 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, 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); for (usize i = 0; i < pl->size && i < nparams; i++) { spl_ast_node_t *pd = node_at(a->sema, pl->data[i]); if (!pd || !pd->param_decl.name) continue; spl_type_id_t pt = ft->fn_type.params.data[i]; spl_ir_node_ref_t pr = emit_node(a, &fc); spl_ir_node_t *e = enode(a, &fc, pr); e->kind = SPL_IR_CONTROL_PARAM; e->control_param.tid = pt; e->control_param.idx = (usize)i; set_ntype(&fc, pr, pt); spl_ir_node_ref_t slot = emit_alloca(a, &fc, pt); emit_store(a, &fc, pt, slot, pr); env_add(&fc, pd->param_decl.name, pd->resolved_def_id, pt, slot, 0, 0, 0); } begin_block(&fc, new_block(&fc)); lower_block(a, &fc, &fn->fn_decl.block); if (!fc.terminated) emit_ret(a, &fc, ret, 0); spl_ir_func_t *ff = spl_ir_func(&a->ir, fid); for (usize i = 0; i < fc.fixups.size; i++) { ir_fix_t *fx = &fc.fixups.data[i]; spl_ir_node_t *nn = spl_ir_node(&a->ir, fid, fx->node); spl_ir_node_ref_t target = fc.blocks.data[fx->block].first; if (!target) target = ff->nodes.size ? ff->nodes.size - 1 : 0; if (fx->slot == 0) nn->control_br.true_label = target; else if (fx->slot == 1) nn->control_br.false_label = target; else nn->control_jmp.label = target; } for (usize i = 0; i < fc.blocks.size; i++) if (fc.blocks.data[i].first) vec_push(ff->labels, fc.blocks.data[i].first); for (usize i = 1; i < ff->labels.size; i++) { spl_ir_node_ref_t k = ff->labels.data[i]; usize j = i; while (j > 0 && ff->labels.data[j - 1] > k) { ff->labels.data[j] = ff->labels.data[j - 1]; j--; } ff->labels.data[j] = k; } if (fc.err) a->err_count += fc.err; fc_drop(&fc); } void spl_ast2ir_init(spl_ast2ir_t *ast2ir, const spl_sema_t *sema) { memset(ast2ir, 0, sizeof *ast2ir); ast2ir->sema = sema; spl_ir_init(&ast2ir->ir); vec_init(ast2ir->owned_names); } 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 * ================================================================ */ /* 预登记:为所有函数(顶层 + 聚合方法)建 IR func */ static void register_funcs(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; 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_FN_DECL && m->kind != SPL_AST_FN_DEFINE)) continue; spl_def_id_t def = root_lookup(a, m->fn_decl.name); if (!def) continue; spl_type_id_t fn_tid = def_at(a->sema, def)->type_id; spl_ir_func_ref_t fid = spl_ir_alloc_fn(&a->ir); spl_ir_func_t *f = spl_ir_func(&a->ir, fid); f->name = m->fn_decl.name; f->fn_tid = fn_tid; } 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; spl_def_id_t adef = root_lookup(a, m->type_decl.name); if (!adef) continue; spl_type_id_t agg_tid = underlying(a->sema, def_at(a->sema, adef)->type_id); for (usize j = 0; j < te->type_expr.aggregate_list.size; j++) { spl_ast_node_ref_t mm = te->type_expr.aggregate_list.data[j]; spl_ast_node_t *mn = node_at(a->sema, mm); if (!mn || (mn->kind != SPL_AST_FN_DECL && mn->kind != SPL_AST_FN_DEFINE)) continue; spl_type_id_t mt = agg_member_type(a, agg_tid, mn->fn_decl.name); if (!mt) continue; size_t nlen = strlen(m->type_decl.name) + 1 + strlen(mn->fn_decl.name) + 1; char *fname = malloc(nlen); snprintf(fname, nlen, "%s.%s", m->type_decl.name, mn->fn_decl.name); spl_ir_func_ref_t fid = spl_ir_alloc_fn(&a->ir); spl_ir_func_t *f = spl_ir_func(&a->ir, fid); f->name = fname; f->fn_tid = mt; vec_push(a->owned_names, fname); } } } 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]; spl_ast_node_t *m = node_at(a->sema, mref); if (!m || m->kind != SPL_AST_FN_DEFINE) continue; spl_def_id_t def = root_lookup(a, m->fn_decl.name); if (!def) continue; spl_type_id_t fn_tid = def_at(a->sema, def)->type_id; spl_ir_func_ref_t fid = a2ir_fn_of(a, fn_tid); if (fid) lower_func_body(a, fid, fn_tid, mref, 0); } 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; spl_def_id_t adef = root_lookup(a, m->type_decl.name); if (!adef) continue; spl_type_id_t agg_tid = underlying(a->sema, def_at(a->sema, adef)->type_id); for (usize j = 0; j < te->type_expr.aggregate_list.size; j++) { spl_ast_node_ref_t mm = te->type_expr.aggregate_list.data[j]; spl_ast_node_t *mn = node_at(a->sema, mm); if (!mn || mn->kind != SPL_AST_FN_DEFINE) continue; spl_type_id_t mt = agg_member_type(a, agg_tid, mn->fn_decl.name); spl_ir_func_ref_t fid = mt ? a2ir_fn_of(a, mt) : 0; if (fid) lower_func_body(a, fid, mt, mm, agg_tid); } } }