From 994a35a942f82153763bb187f5e331d6e1045a25 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Tue, 18 Aug 2026 11:22:15 +0800 Subject: [PATCH] =?UTF-8?q?stage1=20=E9=87=8D=E6=9E=84=E8=AF=AD=E4=B9=89?= =?UTF-8?q?=E5=88=86=E6=9E=90=20ast2ir=20ir=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project_desc.py | 9 +- stage1/spl_ast2ir.c | 3384 ++----------------------------------------- stage1/spl_ast2ir.h | 12 +- stage1/spl_ir.c | 948 +++++++----- stage1/spl_ir.h | 159 +- stage1/spl_sema.c | 86 +- stage1/splc0.c | 31 +- 7 files changed, 970 insertions(+), 3659 deletions(-) diff --git a/project_desc.py b/project_desc.py index e66f92f..ba24765 100644 --- a/project_desc.py +++ b/project_desc.py @@ -5,14 +5,13 @@ vm = [ ] splc0_part = [ - # "stage1/spl_ir.c", "stage1/spl_ast.c", "stage1/spl_lexer.c", "stage1/spl_dumptree.c", - # "stage1/spl_type.c", - # "stage1/spl_sema.c", - # "stage1/spl_builtin.c", - # "stage1/spl_ast2ir.c", + "stage1/spl_type.c", + "stage1/spl_sema.c", + "stage1/spl_ir.c", + "stage1/spl_ast2ir.c", # "stage1/spl_ir2vm.c", ] diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index 98bbd30..441f1ca 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -1,3248 +1,178 @@ -/* 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 "spl_builtin.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_id_t tid_from_def(const spl_sema_t *sema, spl_def_id_t def) { + spl_def_node_t *d = spl_type_def(sema->type, def); + return d ? d->type_id : 0; } -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) +static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, + spl_ast_node_ref_t ref) { + if (ref == 0) 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; - usize cur_src; /* 当前语句AST 节点 ref(调试行号) */ - 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); - spl_ir_node(&a->ir, fc->fn, r)->src_ref = fc->cur_src; /* 调试行号 */ - 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); + Assert(sema != NULL); + spl_ast_node_t *n = spl_ast_node(sema->ast, ref); + spl_ir_node_ref_t ret = 0; + Assert(n != NULL); + + switch (n->kind) { + case SPL_AST_NONE: + UNREACHABLE(); 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); + case SPL_AST_CONTAINER_MEMBERS: { + vec_for(n->container_members, i) { transit(ir, sema, vec_at(n->container_members, i)); } + } break; + case SPL_AST_FN_DECL: + TODO(); 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); + case SPL_AST_FN_DEFINE: { + spl_def_node_t *def = spl_type_def(sema->type, n->resolved_def_id); + Assert(def != NULL); + spl_ir_builder_fn_new(ir, n->fn_decl.name, def->type_id); + vec_for(n->fn_decl.block, i) { transit(ir, sema, vec_at(n->fn_decl.block, i)); } + } break; + case SPL_AST_TYPE_DECL: + TODO(); + break; + case SPL_AST_VAR_DECL: { + TODO(); + } break; + case SPL_AST_CONST_DECL: + case SPL_AST_MEMBER_DECL: + TODO(); + break; + case SPL_AST__COMPTIME_STMT: + case SPL_AST__DIRECTIVE_BLOCK: + case SPL_AST_PARAM_DECL: + break; + case SPL_AST_ATTR_ITEM: + case SPL_AST_ARGG_INIT_ITEM: + case SPL_AST_IF_STATEMENT: + case SPL_AST_IFVAR_STATEMENT: + case SPL_AST_WHILE_STATEMENT: + case SPL_AST_LOOP_STATEMENT: + case SPL_AST_FOR_STATEMENT: + case SPL_AST_MATCH_STATEMENT: + TODO(); + break; + case SPL_AST_RET_STATEMENT: { + if (n->ret_statement.expr) { + ret = transit(ir, sema, n->ret_statement.expr); } - } - 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) { - elem_t = bt->slice_element; - if (base_lv) { - spl_ir_node_ref_t slv = emit_load(a, fc, base_t, base_lv); - 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); - } - /* base_lv==0 时 base_addr 已是切片表达式中提取出的 ptr 标量,直接复用 */ - } 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; - const spl_builtin_t *bi = spl_builtin_lookup(id); - if (!bi) { - diag(a, fc, 0, "unsupported builtin call"); - return 0; - } - usize nargs = pn->primary_expr.builtin_expr.expr_list.size; - if (nargs < (usize)bi->min_args || (bi->max_args >= 0 && nargs > (usize)bi->max_args)) { - diag(a, fc, 0, "builtin @arg count mismatch"); - return 0; - } - /* @sizeof / @bitsizeof / @alignof / @field_count: 单类型参数 → 对应 IR 类型查询节点 */ - if (bi->kind == SPL_BUILTIN_SIZE_OF || bi->kind == SPL_BUILTIN_BITSIZE_OF || - bi->kind == SPL_BUILTIN_ALIGN_OF || bi->kind == SPL_BUILTIN_FIELD_COUNT) { - 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, "builtin @type query: cannot resolve type"); - return 0; - } - spl_ir_node_ref_t n = emit_node(a, fc); - spl_ir_node_t *e = enode(a, fc, n); - switch (bi->kind) { - case SPL_BUILTIN_SIZE_OF: - e->kind = SPL_IR_TYPE_SIZEOF; - e->ir_sizeof.tid = t; - break; - case SPL_BUILTIN_BITSIZE_OF: - e->kind = SPL_IR_TYPE_BITSIZEOF; - e->bitsizeof.tid = t; - break; - case SPL_BUILTIN_ALIGN_OF: - e->kind = SPL_IR_TYPE_ALIGNOF; - e->ir_alignof.tid = t; - break; - default: - e->kind = SPL_IR_TYPE_FIELD_COUNT; - e->field_count.tid = t; - break; - } - set_ntype(fc, n, kw_type(a, "usize")); - return n; - } - /* @offsetof(T, field): 字段名 → 索引常量节点 */ - if (bi->kind == SPL_BUILTIN_OFFSET_OF) { - spl_type_id_t t = - type_from_type_like(a, fc, pn->primary_expr.builtin_expr.expr_list.data[0]); - spl_ast_node_t *farg = - node_at(a->sema, pn->primary_expr.builtin_expr.expr_list.data[1]); - if (!t || !farg || farg->kind != SPL_AST_EXPR) { - diag(a, fc, 0, "@offsetof: invalid arguments"); - return 0; - } - spl_ast_node_t *fn_ = farg->expr.op == SPL_AST_PRIMARY_EXPR - ? node_at(a->sema, farg->expr.op_expr.left) - : NULL; - const char *fname = - (fn_ && fn_->primary_expr.kind == SPL_AST_IDENT) ? fn_->primary_expr.ident : NULL; - isize fidx = fname ? agg_index_or_builtin(a, t, fname) : -1; - if (fidx < 0) { - diag(a, fc, 0, "@offsetof: unknown field"); - return 0; - } - spl_ir_node_ref_t idx = const_int(a, fc, kw_type(a, "usize"), (usize)fidx); - spl_ir_node_ref_t n = emit_node(a, fc); - spl_ir_node_t *e = enode(a, fc, n); - e->kind = SPL_IR_TYPE_OFFSETOF; - e->ir_offsetof.tid = t; - e->ir_offsetof.field_idx = idx; - set_ntype(fc, n, kw_type(a, "usize")); - return n; - } - /* @dbg(args...): 逐参数求值(副作用),发射断点 */ - if (bi->kind == SPL_BUILTIN_DBG) { - for (usize i = 0; i < nargs; 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; - } - /* @assert(cond): 若 cond 为假 → trap(HALT) */ - if (bi->kind == SPL_BUILTIN_ASSERT) { - spl_ir_node_ref_t c = - lower_expr(a, fc, pn->primary_expr.builtin_expr.expr_list.data[0]); - usize trap_b = new_block(fc); - usize exit_b = new_block(fc); - emit_br(a, fc, c, exit_b, trap_b); - begin_block(fc, trap_b); - { - spl_ir_node_ref_t n = emit_node(a, fc); - spl_ir_node_t *e = enode(a, fc, n); - e->kind = SPL_IR_CONTROL_TRAP; - set_ntype(fc, n, kw_type(a, "void")); - fc->terminated = 1; - } - begin_block(fc, exit_b); - spl_ir_node_ref_t r = emit_node(a, fc); - spl_ir_node_t *e = enode(a, fc, r); - e->kind = SPL_IR_TYPE_CONST; - e->type_const.tid = kw_type(a, "void"); - set_ntype(fc, r, kw_type(a, "void")); - return r; - } - /* @import: 预留未实现 */ - diag(a, fc, 0, "builtin @import not implemented"); - 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_ir_node_ref_t base_val = 0; - if (!base_lv) { - /* base 是切片/数组表达式(如 arr[1..4][1..2]):取值后提取字段 */ - base_val = lower_expr(a, fc, pf->postfix_expr.primary_expr); - bt = node_type(fc, base_val); - } - 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 = base_lv ? emit_load(a, fc, bt, base_lv) : base_val; - 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) { + ret = spl_ir_builder_control_ret(ir, tid_from_def(sema, n->resolved_def_id), ret); + } break; + case SPL_AST_BREAK_STATEMENT: + case SPL_AST_CONTINUE_STATEMENT: + case SPL_AST_DEFER_STATEMENT: + case SPL_AST_TRY_STATEMENT: + case SPL_AST_CATCH_STATEMENT: + case SPL_AST_ERRDEFER_STATEMEMT: + case SPL_AST_EXPR_STATEMENT: + case SPL_AST_PACKED_EXPR: + 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: + case SPL_AST_BOOL_OR_EXPR: + case SPL_AST_BOOL_AND_EXPR: + case SPL_AST_BIT_OR_EXPR: + case SPL_AST_BIT_XOR_EXPR: + case SPL_AST_BIT_AND_EXPR: + case SPL_AST_CMP_EQ_EXPR: + case SPL_AST_CMP_NE_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: + case SPL_AST_RANGE_EXPR: + case SPL_AST_LSHIFT_EXPR: + case SPL_AST_RSHIFT_EXPR: 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_MINUS_EXPR: + case SPL_AST_NOT_EXPR: + case SPL_AST_BIT_NOT_EXPR: + case SPL_AST_ADDRESS_EXPR: + case SPL_AST_CALL_EXPR: + case SPL_AST_FIELD_EXPR: + case SPL_AST_DEREF_EXPR: + case SPL_AST_INDEX_EXPR: + case SPL_AST_SLICE_EXPR: + case SPL_AST_AS_EXPR: + TODO(); + break; + case SPL_AST_EXPR_INTEGER_LIT: { + ret = spl_ir_builder_type_const_int(ir, tid_from_def(sema, n->resolved_def_id), + n->primary_expr.integer_expr); + break; } - 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; + case SPL_AST_EXPR_FLOAT_LIT: + case SPL_AST_EXPR_CHAR_LIT: + case SPL_AST_EXPR_STRING_LIT: + case SPL_AST_EXPR_TRUE: + case SPL_AST_EXPR_FALSE: + case SPL_AST_EXPR_NULL: + case SPL_AST_EXPR_UNDEFINED: + break; + case SPL_AST_EXPR_IDENT: { + } break; + case SPL_AST_ARGGREGATE_INIT: + case SPL_AST_EXPR_EXPR: + case SPL_AST_ARRAY_LIT: + case SPL_AST_BUILTIN_EXPR: + case SPL_AST_BLOCK_EXPR: + case SPL_AST_BASE_TYPE_FN: + case SPL_AST_BASE_TYPE_PATH: + TODO(); + break; + case SPL_AST_TYPE_POINTER: + case SPL_AST_TYPE_ARRAY: + case SPL_AST_TYPE_SLICE: + case SPL_AST_TYPE_STRUCT: + case SPL_AST_TYPE_UNION: + case SPL_AST_TYPE_SHAPE: + case SPL_AST_TYPE_ENUM: + case SPL_AST_TYPE_VOID: + case SPL_AST_TYPE_BOOL: + case SPL_AST_TYPE_OPAQUE: + case SPL_AST_TYPE_I8: + case SPL_AST_TYPE_U8: + case SPL_AST_TYPE_I16: + case SPL_AST_TYPE_U16: + case SPL_AST_TYPE_I32: + case SPL_AST_TYPE_U32: + case SPL_AST_TYPE_I64: + case SPL_AST_TYPE_U64: + case SPL_AST_TYPE_ISIZE: + case SPL_AST_TYPE_USIZE: + case SPL_AST_TYPE__F32: + case SPL_AST_TYPE__F64: + case SPL_AST_TYPE_ANY: + case SPL_AST_TYPE_IDENT: + TODO(); + break; + case SPL_AST_COUNT: + UNREACHABLE(); + break; } + return ret; } -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; - if (ref) - fc->cur_src = ref; /* 调试行号:当前语*/ - 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); - /* 调试:登记变量名 alloca 节点 */ - spl_ir_dbg_var_t dv = {name, slot, tid, 0, 0}; - vec_push(a->ir.funcs.data[fc->fn].dbg_vars, dv); -} - -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_RANGE) { - /* Range 值:内部 { begin, end },迭代 begin..end-1 */ - s->kind = FOR_RANGE; - s->elem_tid = vtt->range_element; - s->begin_slot = emit_alloca(a, fc, s->elem_tid); - emit_store(a, fc, s->elem_tid, s->begin_slot, - emit_agg_extract(a, fc, vt, s->elem_tid, 0, v)); - spl_ir_node_ref_t end = emit_agg_extract(a, fc, vt, s->elem_tid, 1, v); - 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, end, b); - return; - } - 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; - const char *vname = NULL; - if (is_enum) { - /* 变体名:`.Red`(ident)或 `Tag.ident`(expr 字段路径)两种形式 */ - vname = pk->packed_expr.ident; - if (!vname && pk->packed_expr.expr) { - spl_ast_node_t *en = node_at(a->sema, pk->packed_expr.expr); - if (en && en->kind == SPL_AST_EXPR && en->expr.op == SPL_AST_POSTFIX_EXPR) { - spl_ast_node_t *epf = node_at(a->sema, en->expr.op_expr.left); - if (epf && epf->postfix_expr.kind == SPL_AST_FIELD_EXPR) - vname = epf->postfix_expr.field_expr; - } - } - if (vname) { - isize vidx = enum_variant_index(a, st, vname); - 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: { - /* if var .x[y] = e { }:绑定新变量 y = e,进入 if 块(sema 语义) - * 若 bind_ident 为空(if var .x = e),则不绑定,仅进入 if 块 */ - spl_ast_node_t *pk = node_at(a->sema, b->block_item.ifvar_statement.packed_expr); - if (pk && pk->packed_expr.bind_ident && pk->packed_expr.expr) { - spl_ir_node_ref_t ev = lower_expr(a, fc, pk->packed_expr.expr); - spl_type_id_t vt = underlying(a->sema, node_type(fc, ev)); - spl_ir_node_ref_t bslot = emit_alloca(a, fc, vt); - emit_store(a, fc, vt, bslot, ev); - env_add(fc, pk->packed_expr.bind_ident, 0, vt, bslot, 0, 0, 0); - } - env_push(fc); - lower_block(a, fc, &b->block_item.ifvar_statement.if_block); - env_pop(fc); - /* else 分支:无失败语义,不发射 */ - 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); - /* 调试:参数登记(值在参数区,fp 偏移ir2vm param_off 填) */ - spl_ir_dbg_var_t dv = {pd->param_decl.name, slot, pt, 1, (usize)i}; - vec_push(a->ir.funcs.data[fid].dbg_vars, dv); - } - 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); +void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema) { ast2ir->sema = sema; - spl_ir_init(&ast2ir->ir); - vec_init(ast2ir->owned_names); + ast2ir->ir = ir; + ast2ir->err_count = 0; } -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); -} +void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {} -/* ================================================================ - * 全局数据(聚合类型下 / 顶层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 if (m->kind == SPL_AST_MEMBER_DECL) { - /* 顶层裸成员(文件级 IDENT: T)视为全局 var;聚合体内 MEMBER_DECL 是字段不收集 */ - spl_def_node_t *md = m->resolved_def_id ? def_at(a->sema, m->resolved_def_id) : NULL; - if (!md || md->kind != SPL_DEF_VAR) - continue; - mname = m->member_decl.name; - iexpr = 0; - } 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); - } - } -} +void spl_ast2ir_run(spl_ast2ir_t *ctx) { transit(ctx->ir, ctx->sema, ctx->sema->ast->root); } diff --git a/stage1/spl_ast2ir.h b/stage1/spl_ast2ir.h index d3dbd2c..dafcfd0 100644 --- a/stage1/spl_ast2ir.h +++ b/stage1/spl_ast2ir.h @@ -4,21 +4,13 @@ #include "spl_ir.h" #include "spl_sema.h" -/* 全局 var/const 的 def → gdata 向量中的 value 节点索引 */ -typedef struct { - spl_def_id_t def_id; - usize gdata_idx; -} spl_ast2ir_gref_t; - typedef struct { const spl_sema_t *sema; - spl_ir_t ir; - VEC(char *) owned_names; /* 本模块 malloc 的函数名,drop 时释放 */ - VEC(spl_ast2ir_gref_t) gdata_ref; /* def_id → gdata value 节点索引 */ + spl_ir_builder_t *ir; int err_count; } spl_ast2ir_t; -void spl_ast2ir_init(spl_ast2ir_t *ast2ir, const spl_sema_t *sema); +void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema); void spl_ast2ir_drop(spl_ast2ir_t *ast2ir); void spl_ast2ir_run(spl_ast2ir_t *ast2ir); diff --git a/stage1/spl_ir.c b/stage1/spl_ir.c index d458a55..79d7705 100644 --- a/stage1/spl_ir.c +++ b/stage1/spl_ir.c @@ -1,25 +1,21 @@ -/* spl_ir.c — function-based SIR IR (arena 容器 + 文本 dump) */ - #include "spl_ir.h" -#include -#include - -/* ---- 内置函数名字表(与 spl_ir_kind_t 枚举一一对应) ---- */ -static const char *const ir_kind_names[] = { +const char *spl_ir_kind_name(spl_ir_kind_t kind) { + static const char *const names[] = { #define X(a, b, c) #a, - SPL_IR_FN_TABLE + SPL_IR_FN_TABLE #undef X -}; + }; + if ((usize)kind < sizeof(names) / sizeof(names[0])) + return names[kind]; + return "?"; +} void spl_ir_init(spl_ir_t *ir) { - memset(ir, 0, sizeof *ir); vec_init(ir->funcs); + vec_push(ir->funcs, (spl_ir_func_t){0}); vec_init(ir->gdata); - /* func ref 0 保留为 error,占位 */ - spl_ir_func_t f0; - memset(&f0, 0, sizeof f0); - vec_push(ir->funcs, f0); + vec_push(ir->gdata, (spl_ir_node_t){0}); } static void node_drop_vecs(spl_ir_node_t *n) { @@ -38,180 +34,66 @@ static void node_drop_vecs(spl_ir_node_t *n) { } void spl_ir_drop(spl_ir_t *ir) { - for (usize i = 0; i < ir->funcs.size; i++) { - spl_ir_func_t *f = &ir->funcs.data[i]; - for (usize j = 0; j < f->nodes.size; j++) - node_drop_vecs(&f->nodes.data[j]); + vec_for(ir->funcs, i) { + spl_ir_func_t *f = &vec_at(ir->funcs, i); + vec_for(f->nodes, j) { node_drop_vecs(&vec_at(f->nodes, j)); } vec_free(f->nodes); vec_free(f->labels); - vec_free(f->dbg_vars); } vec_free(ir->funcs); - for (usize i = 0; i < ir->gdata.size; i++) - node_drop_vecs(&ir->gdata.data[i]); + vec_for(ir->gdata, i) { node_drop_vecs(&vec_at(ir->gdata, i)); } vec_free(ir->gdata); } spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir) { - spl_ir_func_t f; - memset(&f, 0, sizeof f); + spl_ir_func_t f = {0}; vec_init(f.nodes); vec_init(f.labels); - vec_init(f.dbg_vars); + vec_push(f.nodes, (spl_ir_node_t){0}); /* 0 = error 哨兵 */ vec_push(ir->funcs, f); - return ir->funcs.size - 1; + return vec_size(ir->funcs) - 1; } spl_ir_node_ref_t spl_ir_alloc_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id) { - if (!fn_id || fn_id >= ir->funcs.size) + if (!fn_id || fn_id >= vec_size(ir->funcs)) return 0; - spl_ir_func_t *f = &ir->funcs.data[fn_id]; - spl_ir_node_t n; - memset(&n, 0, sizeof n); - if (f->nodes.size == 0) { - vec_push(f->nodes, n); /* 占位:node ref 0 保留为 error */ - } + spl_ir_func_t *f = &vec_at(ir->funcs, fn_id); + spl_ir_node_t n = {0}; vec_push(f->nodes, n); - return f->nodes.size - 1; + return vec_size(f->nodes) - 1; } spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id) { - if (!fn_id || fn_id >= ir->funcs.size) + if (!fn_id || fn_id >= vec_size(ir->funcs)) return NULL; - spl_ir_func_t *f = &ir->funcs.data[fn_id]; - if (!node_id || node_id >= f->nodes.size) + spl_ir_func_t *f = &vec_at(ir->funcs, fn_id); + if (!node_id || node_id >= vec_size(f->nodes)) return NULL; - return &f->nodes.data[node_id]; + return &vec_at(f->nodes, node_id); } spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id) { - if (!fn_id || fn_id >= ir->funcs.size) + if (!fn_id || fn_id >= vec_size(ir->funcs)) return NULL; - return &ir->funcs.data[fn_id]; + return &vec_at(ir->funcs, fn_id); } -/* ================================================================ - * dump - * ================================================================ */ +static inline void ir_dump_type(const spl_type_t *ty, spl_type_id_t tid) { + printf("("); + spl_type_pure_dump((spl_type_t *)ty, tid); + printf(")"); +} -static void ir_type_dump(const spl_type_t *ty, spl_type_id_t tid) { - spl_type_node_t *n = spl_type_node((spl_type_t *)ty, tid); - if (!n) { - printf("?"); - return; +static inline void ir_dump_ref(spl_ir_node_ref_t ref) { + if (ref == 0) { + printf(" _"); + } else { + printf(" %%%zu", ref); } +} + +static void ir_dump_node(const spl_type_t *ty, spl_ir_node_t *n) { switch (n->kind) { - case SPL_TYPE_VOID: - printf("void"); - break; - case SPL_TYPE_BOOL: - printf("bool"); - break; - case SPL_TYPE_INT: - printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits); - break; - case SPL_TYPE_FLOAT: - printf("f%zu", n->float_type.bits); - break; - case SPL_TYPE_PTR: - printf("*"); - ir_type_dump(ty, n->ptr_pointee); - break; - case SPL_TYPE_SLICE: - printf("[]"); - ir_type_dump(ty, n->slice_element); - break; - case SPL_TYPE_RANGE: - printf("range["); - ir_type_dump(ty, n->range_element); - printf("]"); - break; - case SPL_TYPE_ARRAY: - printf("[%zu]", n->array_type.len); - ir_type_dump(ty, n->array_type.element); - break; - case SPL_TYPE_STRUCT: - printf("struct#%zu", tid); - break; - case SPL_TYPE_UNION: - printf("union#%zu", tid); - break; - case SPL_TYPE_ENUM: - printf("enum#%zu", tid); - break; - case SPL_TYPE_FN: - printf("fn<"); - for (usize i = 0; i < n->fn_type.params.size; i++) { - if (i) - printf(","); - ir_type_dump(ty, n->fn_type.params.data[i]); - } - printf("->"); - ir_type_dump(ty, n->fn_type.ret); - printf(">"); - break; - case SPL_TYPE_ID: - ir_type_dump(ty, n->type_id); - break; - default: - printf("?%zu", tid); - break; - } -} - -static const char *node_name(spl_ir_kind_t k) { - if ((usize)k < sizeof(ir_kind_names) / sizeof(ir_kind_names[0])) - return ir_kind_names[k]; - return "?"; -} - -static int node_produces_value(spl_ir_kind_t k) { - switch (k) { - case SPL_IR_MEM_STORE: - case SPL_IR_MEM_COPY: - case SPL_IR_MEM_SET: - case SPL_IR_MEM_FENCE: - case SPL_IR_CONTROL_BR: - case SPL_IR_CONTROL_JMP: - case SPL_IR_CONTROL_RET: - case SPL_IR_CONTROL_UNREACHABLE: - case SPL_IR_CONTROL_TRAP: - case SPL_IR_DBG_BREAKPOINT: - case SPL_IR_DBG_DECLARE: - return 0; - default: - return 1; - } -} - -static void dump_ref(spl_ir_node_ref_t r) { printf("%%%zu", r); } - -static void dump_node(const spl_type_t *ty, const spl_ir_node_t *n) { - switch (n->kind) { - case SPL_IR_TYPE_CONST: - printf("@type.const("); - ir_type_dump(ty, n->type_const.tid); - printf(")("); - { - spl_type_node_t *t = spl_type_node((spl_type_t *)ty, n->type_const.tid); - if (t && t->kind == SPL_TYPE_INT) - printf("%lld", (long long)n->type_const.int_lit); - else if (t && t->kind == SPL_TYPE_FLOAT) - printf("%g", n->type_const.float_lit); - else if (t && t->kind == SPL_TYPE_FN) - printf("@fn#%zu", n->type_const.fn); - else if (t && (t->kind == SPL_TYPE_PTR || t->kind == SPL_TYPE_SLICE)) { - if (n->type_const.cstr_lit) - printf("\"%s\"", n->type_const.cstr_lit); - else - printf("0"); - } else if (t && t->kind == SPL_TYPE_BOOL) - printf("%lld", (long long)n->type_const.int_lit); - else - printf("?"); - } - printf(")"); - break; case SPL_IR_ARITH_ADD: case SPL_IR_ARITH_SUB: case SPL_IR_ARITH_MUL: @@ -222,24 +104,12 @@ static void dump_node(const spl_type_t *ty, const spl_ir_node_t *n) { case SPL_IR_ARITH_XOR: case SPL_IR_ARITH_SHL: case SPL_IR_ARITH_SHR: - printf("@%s(", node_name(n->kind)); - ir_type_dump(ty, n->arith.tid); - printf(")("); - dump_ref(n->arith.left); - if (n->arith.right) { - printf(", "); - dump_ref(n->arith.right); - } - printf(")"); - break; case SPL_IR_ARITH_NEG: case SPL_IR_ARITH_ABS: case SPL_IR_ARITH_NOT: - printf("@%s(", node_name(n->kind)); - ir_type_dump(ty, n->arith.tid); - printf(")("); - dump_ref(n->arith.left); - printf(")"); + ir_dump_type(ty, n->arith.tid); + ir_dump_ref(n->arith.left); + ir_dump_ref(n->arith.right); break; case SPL_IR_CMP_EQ: case SPL_IR_CMP_NE: @@ -247,13 +117,9 @@ static void dump_node(const spl_type_t *ty, const spl_ir_node_t *n) { case SPL_IR_CMP_LE: case SPL_IR_CMP_GT: case SPL_IR_CMP_GE: - printf("@%s(", node_name(n->kind)); - ir_type_dump(ty, n->cmp.tid); - printf(")("); - dump_ref(n->cmp.a); - printf(", "); - dump_ref(n->cmp.b); - printf(")"); + ir_dump_type(ty, n->cmp.tid); + ir_dump_ref(n->cmp.a); + ir_dump_ref(n->cmp.b); break; case SPL_IR_CAST_TRUNC: case SPL_IR_CAST_ZEXT: @@ -266,254 +132,578 @@ static void dump_node(const spl_type_t *ty, const spl_ir_node_t *n) { case SPL_IR_CAST_BOOL2INT: case SPL_IR_CASE_INT2FLOAT: case SPL_IR_CASE_FLOAT2INT: - printf("@%s(", node_name(n->kind)); - ir_type_dump(ty, n->cast.from_tid); - printf(", "); - ir_type_dump(ty, n->cast.to_tid); - printf(")("); - dump_ref(n->cast.val); - printf(")"); + printf(" "); + spl_type_pure_dump((spl_type_t *)ty, n->cast.from_tid); + printf(" -> "); + spl_type_pure_dump((spl_type_t *)ty, n->cast.to_tid); + ir_dump_ref(n->cast.val); break; case SPL_IR_MEM_ALLOCA: - printf("@mem.alloca("); - ir_type_dump(ty, n->mem_alloc.tid); - printf(")("); - dump_ref(n->mem_alloc.count); - printf(")"); - break; - case SPL_IR_MEM_LOAD: - printf("@mem.load("); - ir_type_dump(ty, n->mem_load.tid); - printf(")("); - dump_ref(n->mem_load.ptr); - printf(")"); - break; - case SPL_IR_MEM_STORE: - printf("@mem.store("); - ir_type_dump(ty, n->mem_store.tid); - printf(")("); - dump_ref(n->mem_store.ptr); - printf(", "); - dump_ref(n->mem_store.val); - printf(")"); - break; - case SPL_IR_MEM_OFFSET: - printf("@mem.offset("); - ir_type_dump(ty, n->mem_offset.tid); - printf(")("); - dump_ref(n->mem_offset.ptr); - printf(", "); - dump_ref(n->mem_offset.offset); - printf(")"); - break; - case SPL_IR_MEM_FIELD_PTR: - printf("@mem.field_ptr("); - ir_type_dump(ty, n->mem_field_ptr.tid); - printf(", %zu)(", (size_t)n->mem_field_ptr.field_idx); - dump_ref(n->mem_field_ptr.agg); - printf(")"); + ir_dump_type(ty, n->mem_alloc.tid); + ir_dump_ref(n->mem_alloc.count); break; case SPL_IR_MEM_GLOBAL_ALLOC: - printf("@mem.global_alloc(gdata[%zu])()", (size_t)n->mem_global_alloc.const_node); + ir_dump_type(ty, n->mem_global_alloc.tid); + printf(" g#%zu", n->mem_global_alloc.const_node); + break; + case SPL_IR_MEM_LOAD: + ir_dump_type(ty, n->mem_load.tid); + ir_dump_ref(n->mem_load.ptr); + break; + case SPL_IR_MEM_STORE: + ir_dump_type(ty, n->mem_store.tid); + ir_dump_ref(n->mem_store.ptr); + ir_dump_ref(n->mem_store.val); + break; + case SPL_IR_MEM_OFFSET: + ir_dump_type(ty, n->mem_offset.tid); + ir_dump_ref(n->mem_offset.ptr); + ir_dump_ref(n->mem_offset.offset); + break; + case SPL_IR_MEM_FIELD_PTR: + ir_dump_type(ty, n->mem_field_ptr.tid); + ir_dump_ref(n->mem_field_ptr.agg); + printf(" #%zu", n->mem_field_ptr.field_idx); break; case SPL_IR_MEM_COPY: - printf("@mem.copy()("); - dump_ref(n->mem_copy.dst); - printf(", "); - dump_ref(n->mem_copy.src); - printf(", "); - dump_ref(n->mem_copy.size); - printf(")"); + ir_dump_type(ty, n->mem_copy.tid); + ir_dump_ref(n->mem_copy.dst); + ir_dump_ref(n->mem_copy.src); + ir_dump_ref(n->mem_copy.size); break; case SPL_IR_MEM_SET: - printf("@mem.set()("); - dump_ref(n->mem_set.dst); - printf(", "); - dump_ref(n->mem_set.val); - printf(", "); - dump_ref(n->mem_set.size); - printf(")"); + ir_dump_type(ty, n->mem_set.tid); + ir_dump_ref(n->mem_set.dst); + ir_dump_ref(n->mem_set.val); + ir_dump_ref(n->mem_set.size); break; - case SPL_IR_MEM_FENCE: - printf("@mem.fence()("); - dump_ref(n->mem_fence.ordering); - printf(")"); + case SPL_IR_TYPE_CONST: { + ir_dump_type(ty, n->type_const.tid); + spl_type_node_t *t = spl_type_node((spl_type_t *)ty, n->type_const.tid); + if (t && t->kind == SPL_TYPE_FLOAT) { + printf(" float=%f", n->type_const.float_lit); + } else if (t && t->kind == SPL_TYPE_FN) { + printf(" fn#%zu", n->type_const.fn); + } else if (t && t->kind == SPL_TYPE_SLICE) { + printf(" str=\"%s\"", n->type_const.cstr_lit ? n->type_const.cstr_lit : "?"); + } else if (t && t->kind == SPL_TYPE_INT && t->int_type.bits == 8) { + printf(" char='%c'", n->type_const.ch_lit); + } else { + printf(" int=%zu", n->type_const.int_lit); + } break; + } case SPL_IR_TYPE_BITSIZEOF: - printf("@type.bitsizeof("); - ir_type_dump(ty, n->bitsizeof.tid); - printf(")()"); + ir_dump_type(ty, n->bitsizeof.tid); break; case SPL_IR_TYPE_SIZEOF: - printf("@type.sizeof("); - ir_type_dump(ty, n->ir_sizeof.tid); - printf(")()"); + ir_dump_type(ty, n->ir_sizeof.tid); break; case SPL_IR_TYPE_ALIGNOF: - printf("@type.alignof("); - ir_type_dump(ty, n->ir_alignof.tid); - printf(")()"); + ir_dump_type(ty, n->ir_alignof.tid); break; case SPL_IR_TYPE_OFFSETOF: - printf("@type.offsetof("); - ir_type_dump(ty, n->ir_offsetof.tid); - printf(")("); - dump_ref(n->ir_offsetof.field_idx); - printf(")"); + ir_dump_type(ty, n->ir_offsetof.tid); + ir_dump_ref(n->ir_offsetof.field_idx); break; case SPL_IR_TYPE_FIELD_COUNT: - printf("@type.field_count("); - ir_type_dump(ty, n->field_count.tid); - printf(")()"); + ir_dump_type(ty, n->field_count.tid); break; case SPL_IR_AGG_CONSTRUCT: - printf("@agg.construct("); - ir_type_dump(ty, n->agg_construct.tid); - printf(")("); - for (usize i = 0; i < n->agg_construct.fields.size; i++) { - if (i) - printf(", "); - dump_ref(n->agg_construct.fields.data[i]); - } - printf(")"); + ir_dump_type(ty, n->agg_construct.tid); + vec_for(n->agg_construct.fields, i) ir_dump_ref(vec_at(n->agg_construct.fields, i)); break; case SPL_IR_AGG_EXTRACT: - printf("@agg.extract("); - ir_type_dump(ty, n->agg_extract.tid); - printf(", %lld)(", (long long)n->agg_extract.field_idx); - dump_ref(n->agg_extract.val); - printf(")"); + ir_dump_type(ty, n->agg_extract.tid); + printf(" #%zu", n->agg_extract.field_idx); + ir_dump_ref(n->agg_extract.val); break; case SPL_IR_AGG_INSERT: - printf("@agg.insert("); - ir_type_dump(ty, n->agg_insert.tid); - printf(", %lld)(", (long long)n->agg_insert.field_idx); - dump_ref(n->agg_insert.agg); - printf(", "); - dump_ref(n->agg_insert.field); - printf(")"); + ir_dump_type(ty, n->agg_insert.tid); + printf(" #%zu", n->agg_insert.field_idx); + ir_dump_ref(n->agg_insert.agg); + ir_dump_ref(n->agg_insert.field); break; case SPL_IR_CONTROL_SELECT: - printf("@control.select("); - ir_type_dump(ty, n->control_select.tid); - printf(")("); - dump_ref(n->control_select.cond); - printf(", "); - dump_ref(n->control_select.true_val); - printf(", "); - dump_ref(n->control_select.false_val); - printf(")"); + ir_dump_type(ty, n->control_select.tid); + ir_dump_ref(n->control_select.cond); + ir_dump_ref(n->control_select.true_val); + ir_dump_ref(n->control_select.false_val); break; case SPL_IR_CONTROL_BR: - printf("@control.br()("); - dump_ref(n->control_br.cond); - printf(", "); - dump_ref(n->control_br.true_label); - printf(", "); - dump_ref(n->control_br.false_label); - printf(")"); + ir_dump_ref(n->control_br.cond); + ir_dump_ref(n->control_br.true_label); + ir_dump_ref(n->control_br.false_label); break; case SPL_IR_CONTROL_JMP: - printf("@control.jmp()("); - dump_ref(n->control_jmp.label); - printf(")"); + ir_dump_ref(n->control_jmp.label); break; case SPL_IR_CONTROL_CALL: - printf("@control.call("); - ir_type_dump(ty, n->control_call.tid); - printf(")("); - dump_ref(n->control_call.func); - for (usize i = 0; i < n->control_call.params.size; i++) { - printf(", "); - dump_ref(n->control_call.params.data[i]); - } - printf(")"); + ir_dump_type(ty, n->control_call.tid); + ir_dump_ref(n->control_call.func); + vec_for(n->control_call.params, i) ir_dump_ref(vec_at(n->control_call.params, i)); break; case SPL_IR_CONTROL_PARAM: - printf("@control.param("); - ir_type_dump(ty, n->control_param.tid); - printf(")(%lld)", (long long)n->control_param.idx); + ir_dump_type(ty, n->control_param.tid); + ir_dump_ref(n->control_param.idx); break; case SPL_IR_CONTROL_RET: - printf("@control.ret("); - ir_type_dump(ty, n->control_ret.tid); - printf(")("); - if (n->control_ret.val) - dump_ref(n->control_ret.val); - printf(")"); + ir_dump_type(ty, n->control_ret.tid); + ir_dump_ref(n->control_ret.val); break; case SPL_IR_CONTROL_UNREACHABLE: - printf("@control.unreachable()()"); - break; case SPL_IR_CONTROL_TRAP: - printf("@control.trap()()"); - break; case SPL_IR_DBG_BREAKPOINT: - printf("@dbg.breakpoint()()"); - break; - case SPL_IR_DBG_DECLARE: - printf("@dbg.declare()()"); - break; - default: - printf("@%s()()", node_name(n->kind)); break; } } -static void dump_func(const spl_type_t *ty, const spl_ir_func_t *f) { - printf("func @%s", f->name ? f->name : "?"); - if (f->fn_tid) { - spl_type_node_t *t = spl_type_node((spl_type_t *)ty, f->fn_tid); - if (t && t->kind == SPL_TYPE_FN) { - printf("("); - for (usize i = 0; i < t->fn_type.params.size; i++) { - if (i) - printf(", "); - ir_type_dump(ty, t->fn_type.params.data[i]); - } - printf(") -> "); - ir_type_dump(ty, t->fn_type.ret); - } - } - printf(" {\n"); - usize li = 0; - for (usize i = 1; i < f->nodes.size; i++) { - if (li < f->labels.size && f->labels.data[li] == i) { - printf("#bb%zu:\n", li); - li++; - } - printf(" "); - if (node_produces_value(f->nodes.data[i].kind)) - printf("%%%zu = ", i); - dump_node(ty, &f->nodes.data[i]); - printf("\n"); - } - if (li < f->labels.size && f->labels.data[li] == f->nodes.size) - printf("#bb%zu:\n", li); - printf("}\n"); -} - void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) { - printf("; SPL IR module (%zu funcs)\n", ir->funcs.size - 1); - for (usize i = 1; i < ir->funcs.size; i++) - dump_func(ty, &ir->funcs.data[i]); - if (ir->gdata.size) { - printf("; global data (%zu)\n", ir->gdata.size); - for (usize i = 0; i < ir->gdata.size; i++) { - printf("; gdata[%zu] = ", i); - dump_node(ty, &ir->gdata.data[i]); + vec_for(ir->funcs, i) { + if (i == 0) + continue; + spl_ir_func_t *func = &vec_at(ir->funcs, i); + printf("func %s", func->name ? func->name : "?"); + printf(" tid="); + spl_type_pure_dump((spl_type_t *)ty, func->fn_tid); + printf("\n"); + vec_for(func->nodes, j) { + if (j == 0) + continue; + spl_ir_node_t *node = &vec_at(func->nodes, j); + printf(" #%zu ", j); + printf("%s", spl_ir_kind_name(node->kind)); + ir_dump_node(ty, node); + printf("\n"); + } + if (vec_size(func->nodes) == 0) + printf(" (extern)\n"); + } + if (vec_size(ir->gdata) > 1) { + printf("gdata:\n"); + vec_for(ir->gdata, i) { + if (i == 0) + continue; + spl_ir_node_t *node = &vec_at(ir->gdata, i); + printf(" #%zu ", i); + printf("%s", spl_ir_kind_name(node->kind)); + ir_dump_node(ty, node); printf("\n"); } } } -const char *spl_ir_kind_name(spl_ir_kind_t kind) { - static const char *const names[] = { -#define X(a, b, c) #a, - SPL_IR_FN_TABLE -#undef X - }; - if ((usize)kind < sizeof(names) / sizeof(names[0])) - return names[kind]; - return "?"; +// IR Builder + +static spl_ir_node_ref_t builder_alloc_node(spl_ir_builder_t *b, spl_ir_kind_t kind) { + spl_ir_node_ref_t ref = spl_ir_alloc_node(&b->ir, b->current_fn); + Assert(ref != 0); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->kind = kind; + n->dbg = b->dbg; + b->current_node = ref; + return ref; } + +static spl_ir_func_t *builder_cur_func(spl_ir_builder_t *b) { + return spl_ir_func(&b->ir, b->current_fn); +} + +static void builder_reloc_add(spl_ir_builder_t *b, spl_ir_node_ref_t label) { + if (label == 0) { + LOG_WARN("reloc null lable"); + return; + } + spl_ir_func_t *f = builder_cur_func(b); + if (f && label < vec_size(f->nodes)) { + // resolved + return; + } + vec_for(b->reloc_label, i) { + if (vec_at(b->reloc_label, i) == label) { + return; + } + } + vec_push(b->reloc_label, label); +} + +static void builder_reloc_check(spl_ir_builder_t *b) { + spl_ir_func_t *f = builder_cur_func(b); + if (!f) + return; + vec_for(b->reloc_label, i) { + spl_ir_node_ref_t label = vec_at(b->reloc_label, i); + if (label >= vec_size(f->nodes)) { + LOG_ERROR("fn `%s`: forward label %%%zu unresolved", f->name ? f->name : "?", label); + } + } + b->reloc_label.size = 0; +} + +void spl_ir_builder_init(spl_ir_builder_t *b) { + spl_ir_init(&b->ir); + b->current_fn = 0; + b->current_node = 0; + b->dbg = (spl_dbg_node_t){0}; + vec_init(b->reloc_label); +} + +void spl_ir_builder_drop(spl_ir_builder_t *b) { + spl_ir_drop(&b->ir); + vec_free(b->reloc_label); +} + +spl_ir_func_ref_t spl_ir_builder_fn_new(spl_ir_builder_t *b, const char *name, + spl_type_id_t fn_tid) { + if (b->current_fn) { + builder_reloc_check(b); + } + spl_ir_func_ref_t fid = spl_ir_alloc_fn(&b->ir); + spl_ir_func_t *f = spl_ir_func(&b->ir, fid); + f->name = name; + f->fn_tid = fn_tid; + b->current_fn = fid; + b->current_node = 0; + return fid; +} + +spl_ir_func_ref_t spl_ir_builder_cur_fn(const spl_ir_builder_t *b) { return b->current_fn; } + +void spl_ir_builder_set_dbg(spl_ir_builder_t *b, spl_dbg_node_t dbg) { b->dbg = dbg; } + +spl_ir_node_ref_t spl_ir_builder_block_new(spl_ir_builder_t *b) { + spl_ir_func_t *f = builder_cur_func(b); + Assert(f != NULL); + return vec_size(f->nodes); +} + +#define X(name, kind) \ + spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *builder, spl_type_id_t x_tid, \ + spl_ir_node_ref_t x_left, spl_ir_node_ref_t x_right) { \ + spl_ir_node_ref_t ref = builder_alloc_node(builder, kind); \ + spl_ir_node_t *n = spl_ir_node(&builder->ir, builder->current_fn, ref); \ + n->arith.tid = x_tid; \ + n->arith.left = x_left; \ + n->arith.right = x_right; \ + return ref; \ + } +SPL_IR_BIN_ARITH_TABLE +#undef X + +#define X(name, kind) \ + spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *builder, spl_type_id_t x_tid, \ + spl_ir_node_ref_t x_val) { \ + spl_ir_node_ref_t ref = builder_alloc_node(builder, kind); \ + spl_ir_node_t *n = spl_ir_node(&builder->ir, builder->current_fn, ref); \ + n->arith.tid = x_tid; \ + n->arith.left = x_val; \ + n->arith.right = 0; \ + return ref; \ + } +SPL_IR_UN_ARITH_TABLE +#undef X + +#define X(name, kind) \ + spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *builder, spl_type_id_t x_tid, \ + spl_ir_node_ref_t x_a, spl_ir_node_ref_t x_b) { \ + spl_ir_node_ref_t ref = builder_alloc_node(builder, kind); \ + spl_ir_node_t *n = spl_ir_node(&builder->ir, builder->current_fn, ref); \ + n->cmp.tid = x_tid; \ + n->cmp.a = x_a; \ + n->cmp.b = x_b; \ + return ref; \ + } +SPL_IR_CMP_TABLE +#undef X + +#define X(name, kind) \ + spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *builder, spl_type_id_t x_from, \ + spl_type_id_t x_to, spl_ir_node_ref_t x_val) { \ + spl_ir_node_ref_t ref = builder_alloc_node(builder, kind); \ + spl_ir_node_t *n = spl_ir_node(&builder->ir, builder->current_fn, ref); \ + n->cast.from_tid = x_from; \ + n->cast.to_tid = x_to; \ + n->cast.val = x_val; \ + return ref; \ + } +SPL_IR_CAST_TABLE +#undef X + +spl_ir_node_ref_t spl_ir_builder_mem_alloca(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t count) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_MEM_ALLOCA); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->mem_alloc.tid = tid; + n->mem_alloc.count = count; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_mem_global_alloc(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t const_node) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_MEM_GLOBAL_ALLOC); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->mem_global_alloc.tid = tid; + n->mem_global_alloc.const_node = const_node; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_mem_load(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t ptr) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_MEM_LOAD); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->mem_load.tid = tid; + n->mem_load.ptr = ptr; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_mem_store(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t ptr, spl_ir_node_ref_t val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_MEM_STORE); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->mem_store.tid = tid; + n->mem_store.ptr = ptr; + n->mem_store.val = val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_mem_offset(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t ptr, spl_ir_node_ref_t offset) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_MEM_OFFSET); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->mem_offset.tid = tid; + n->mem_offset.ptr = ptr; + n->mem_offset.offset = offset; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_mem_field(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t agg, usize field_idx) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_MEM_FIELD_PTR); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->mem_field_ptr.tid = tid; + n->mem_field_ptr.agg = agg; + n->mem_field_ptr.field_idx = field_idx; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_mem_copy(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t dst, spl_ir_node_ref_t src, + spl_ir_node_ref_t size) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_MEM_COPY); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->mem_copy.tid = tid; + n->mem_copy.dst = dst; + n->mem_copy.src = src; + n->mem_copy.size = size; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_mem_set(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t dst, spl_ir_node_ref_t val, + spl_ir_node_ref_t size) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_MEM_SET); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->mem_set.tid = tid; + n->mem_set.dst = dst; + n->mem_set.val = val; + n->mem_set.size = size; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_const_int(spl_ir_builder_t *b, spl_type_id_t tid, usize val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->type_const.tid = tid; + n->type_const.int_lit = val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_const_float(spl_ir_builder_t *b, spl_type_id_t tid, + double val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->type_const.tid = tid; + n->type_const.float_lit = val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_const_cstr(spl_ir_builder_t *b, spl_type_id_t tid, + const char *val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->type_const.tid = tid; + n->type_const.cstr_lit = val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_const_char(spl_ir_builder_t *b, spl_type_id_t tid, char val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->type_const.tid = tid; + n->type_const.ch_lit = val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_const_fn(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_func_ref_t val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->type_const.tid = tid; + n->type_const.fn = val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_bitsizeof(spl_ir_builder_t *b, spl_type_id_t tid) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_BITSIZEOF); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->bitsizeof.tid = tid; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_sizeof(spl_ir_builder_t *b, spl_type_id_t tid) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_SIZEOF); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->ir_sizeof.tid = tid; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_alignof(spl_ir_builder_t *b, spl_type_id_t tid) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_ALIGNOF); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->ir_alignof.tid = tid; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_offsetof(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t field_idx) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_OFFSETOF); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->ir_offsetof.tid = tid; + n->ir_offsetof.field_idx = field_idx; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_type_field_count(spl_ir_builder_t *b, spl_type_id_t tid) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_FIELD_COUNT); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->field_count.tid = tid; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_agg_construct(spl_ir_builder_t *b, spl_type_id_t tid) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_AGG_CONSTRUCT); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->agg_construct.tid = tid; + vec_init(n->agg_construct.fields); + return ref; +} + +void spl_ir_builder_agg_construct_field(spl_ir_builder_t *b, spl_ir_node_ref_t node, + spl_ir_node_ref_t field) { + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, node); + Assert(n != NULL); + vec_push(n->agg_construct.fields, field); +} + +spl_ir_node_ref_t spl_ir_builder_agg_extract(spl_ir_builder_t *b, spl_type_id_t tid, + spl_type_id_t field_tid, usize field_idx, + spl_ir_node_ref_t val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_AGG_EXTRACT); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->agg_extract.tid = tid; + n->agg_extract.field_tid = field_tid; + n->agg_extract.field_idx = field_idx; + n->agg_extract.val = val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_agg_insert(spl_ir_builder_t *b, spl_type_id_t tid, usize field_idx, + spl_ir_node_ref_t agg, spl_ir_node_ref_t field) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_AGG_INSERT); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->agg_insert.tid = tid; + n->agg_insert.field_idx = field_idx; + n->agg_insert.agg = agg; + n->agg_insert.field = field; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_control_select(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t cond, spl_ir_node_ref_t true_val, + spl_ir_node_ref_t false_val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_SELECT); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->control_select.tid = tid; + n->control_select.cond = cond; + n->control_select.true_val = true_val; + n->control_select.false_val = false_val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_control_br(spl_ir_builder_t *b, spl_ir_node_ref_t cond, + spl_ir_node_ref_t true_label, + spl_ir_node_ref_t false_label) { + builder_reloc_add(b, true_label); + builder_reloc_add(b, false_label); + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_BR); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->control_br.cond = cond; + n->control_br.true_label = true_label; + n->control_br.false_label = false_label; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_control_jmp(spl_ir_builder_t *b, spl_ir_node_ref_t label) { + builder_reloc_add(b, label); + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_JMP); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->control_jmp.label = label; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_control_call(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t func) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_CALL); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->control_call.tid = tid; + n->control_call.func = func; + vec_init(n->control_call.params); + return ref; +} + +void spl_ir_builder_control_call_param(spl_ir_builder_t *b, spl_ir_node_ref_t node, + spl_ir_node_ref_t arg) { + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, node); + Assert(n != NULL); + vec_push(n->control_call.params, arg); +} + +spl_ir_node_ref_t spl_ir_builder_control_param(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t idx) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_PARAM); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->control_param.tid = tid; + n->control_param.idx = idx; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_control_ret(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t val) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_RET); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->control_ret.tid = tid; + n->control_ret.val = val; + return ref; +} + +spl_ir_node_ref_t spl_ir_builder_control_unreachable(spl_ir_builder_t *b) { + return builder_alloc_node(b, SPL_IR_CONTROL_UNREACHABLE); +} + +spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b) { + return builder_alloc_node(b, SPL_IR_CONTROL_TRAP); +} + +spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b) { + return builder_alloc_node(b, SPL_IR_DBG_BREAKPOINT); +} \ No newline at end of file diff --git a/stage1/spl_ir.h b/stage1/spl_ir.h index 4447846..8544b9b 100644 --- a/stage1/spl_ir.h +++ b/stage1/spl_ir.h @@ -5,7 +5,6 @@ #include "spl_dbg.h" #include "spl_type.h" - /* clang-format off */ #define SPL_IR_FN_TABLE \ X(arith.add, V0, SPL_IR_ARITH_ADD) \ @@ -46,7 +45,6 @@ X(mem.field, V0, SPL_IR_MEM_FIELD_PTR) \ X(mem.copy, V0, SPL_IR_MEM_COPY) \ X(mem.set, V0, SPL_IR_MEM_SET) \ - X(mem.fence, V0, SPL_IR_MEM_FENCE) \ X(type.const, V0, SPL_IR_TYPE_CONST) \ X(type.bitsizeof, V0, SPL_IR_TYPE_BITSIZEOF) \ X(type.sizeof, V0, SPL_IR_TYPE_SIZEOF) \ @@ -56,15 +54,6 @@ X(agg.construct, V0, SPL_IR_AGG_CONSTRUCT) \ X(agg.extract, V0, SPL_IR_AGG_EXTRACT) \ X(agg.insert, V0, SPL_IR_AGG_INSERT) \ - X(atomic.load, V0, SPL_IR_ATOMIC_LOAD) \ - X(atomic.store, V0, SPL_IR_ATOMIC_STORE) \ - X(atomic.rmw_add, V0, SPL_IR_ATOMIC_RMW_ADD) \ - X(atomic.rmw_sub, V0, SPL_IR_ATOMIC_RMW_SUB) \ - X(atomic.rmw_and, V0, SPL_IR_ATOMIC_RMW_AND) \ - X(atomic.rmw_or, V0, SPL_IR_ATOMIC_RMW_OR) \ - X(atomic.rmw_xor, V0, SPL_IR_ATOMIC_RMW_XOR) \ - X(atomic.rmw_xchg, V0, SPL_IR_ATOMIC_RMW_XCHG) \ - X(atomic.cmpxchg, V0, SPL_IR_ATOMIC_CMPXCHG) \ X(control.select, V0, SPL_IR_CONTROL_SELECT) \ X(control.br, V0, SPL_IR_CONTROL_BR) \ X(control.jmp, V0, SPL_IR_CONTROL_JMP) \ @@ -74,8 +63,7 @@ X(control.unreachable, V0, SPL_IR_CONTROL_UNREACHABLE) \ X(control.trap, V0, SPL_IR_CONTROL_TRAP) \ X(dbg.breakpoint, V0, SPL_IR_DBG_BREAKPOINT) \ - X(dbg.declare, V0, SPL_IR_DBG_DECLARE) - + typedef enum { #ifdef X #undef X @@ -95,6 +83,7 @@ typedef struct { spl_ir_kind_t kind; spl_dbg_node_t dbg; union { + spl_type_id_t tid; struct { spl_type_id_t tid; spl_ir_node_ref_t left; @@ -149,9 +138,6 @@ typedef struct { spl_ir_node_ref_t val; spl_ir_node_ref_t size; } mem_set; - struct { - spl_ir_node_ref_t ordering; - } mem_fence; struct { spl_type_id_t tid; union { @@ -267,4 +253,145 @@ spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id); void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty); const char *spl_ir_kind_name(spl_ir_kind_t kind); +typedef struct { + spl_ir_t ir; + spl_ir_func_ref_t current_fn; + spl_ir_node_ref_t current_node; + spl_ir_node_ref_vec_t reloc_label; + spl_dbg_node_t dbg; +} spl_ir_builder_t; + +/* clang-format off */ +#define SPL_IR_BIN_ARITH_TABLE \ + X(arith_add, SPL_IR_ARITH_ADD) \ + X(arith_sub, SPL_IR_ARITH_SUB) \ + X(arith_mul, SPL_IR_ARITH_MUL) \ + X(arith_div, SPL_IR_ARITH_DIV) \ + X(arith_rem, SPL_IR_ARITH_REM) \ + X(arith_and, SPL_IR_ARITH_AND) \ + X(arith_or, SPL_IR_ARITH_OR) \ + X(arith_xor, SPL_IR_ARITH_XOR) \ + X(arith_shl, SPL_IR_ARITH_SHL) \ + X(arith_shr, SPL_IR_ARITH_SHR) +#define SPL_IR_UN_ARITH_TABLE \ + X(arith_neg, SPL_IR_ARITH_NEG) \ + X(arith_abs, SPL_IR_ARITH_ABS) \ + X(arith_not, SPL_IR_ARITH_NOT) +#define SPL_IR_CMP_TABLE \ + X(cmp_eq, SPL_IR_CMP_EQ) \ + X(cmp_ne, SPL_IR_CMP_NE) \ + X(cmp_lt, SPL_IR_CMP_LT) \ + X(cmp_le, SPL_IR_CMP_LE) \ + X(cmp_gt, SPL_IR_CMP_GT) \ + X(cmp_ge, SPL_IR_CMP_GE) +#define SPL_IR_CAST_TABLE \ + X(cast_trunc, SPL_IR_CAST_TRUNC) \ + X(cast_zext, SPL_IR_CAST_ZEXT) \ + X(cast_sext, SPL_IR_CAST_SEXT) \ + X(cast_fext, SPL_IR_CAST_FEXT) \ + X(cast_ftrunc, SPL_IR_CAST_FTRUNC) \ + X(cast_bitcast, SPL_IR_CAST_BITCAST) \ + X(cast_ptr2int, SPL_IR_CAST_PTR2INT) \ + X(cast_int2ptr, SPL_IR_CAST_INT2PTR) \ + X(cast_bool2int, SPL_IR_CAST_BOOL2INT) \ + X(case_int2float, SPL_IR_CASE_INT2FLOAT) \ + X(case_float2int, SPL_IR_CASE_FLOAT2INT) +/* clang-format on */ +void spl_ir_builder_init(spl_ir_builder_t *b); +void spl_ir_builder_drop(spl_ir_builder_t *b); + +spl_ir_func_ref_t spl_ir_builder_fn_new(spl_ir_builder_t *b, const char *name, + spl_type_id_t fn_tid); +spl_ir_func_ref_t spl_ir_builder_cur_fn(const spl_ir_builder_t *b); +void spl_ir_builder_set_dbg(spl_ir_builder_t *b, spl_dbg_node_t dbg); + +spl_ir_node_ref_t spl_ir_builder_block_new(spl_ir_builder_t *b); + +#define X(name, kind) \ + spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *b, spl_type_id_t tid, \ + spl_ir_node_ref_t left, spl_ir_node_ref_t right); +SPL_IR_BIN_ARITH_TABLE +#undef X + +#define X(name, kind) \ + spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *b, spl_type_id_t tid, \ + spl_ir_node_ref_t val); +SPL_IR_UN_ARITH_TABLE +#undef X + +#define X(name, kind) \ + spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *builder, spl_type_id_t tid, \ + spl_ir_node_ref_t a, spl_ir_node_ref_t b); +SPL_IR_CMP_TABLE +#undef X + +#define X(name, kind) \ + spl_ir_node_ref_t spl_ir_builder_##name(spl_ir_builder_t *b, spl_type_id_t from_tid, \ + spl_type_id_t to_tid, spl_ir_node_ref_t val); +SPL_IR_CAST_TABLE +#undef X + +spl_ir_node_ref_t spl_ir_builder_mem_alloca(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t count); +spl_ir_node_ref_t spl_ir_builder_mem_global_alloc(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t const_node); +spl_ir_node_ref_t spl_ir_builder_mem_load(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t ptr); +spl_ir_node_ref_t spl_ir_builder_mem_store(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t ptr, spl_ir_node_ref_t val); +spl_ir_node_ref_t spl_ir_builder_mem_offset(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t ptr, spl_ir_node_ref_t offset); +spl_ir_node_ref_t spl_ir_builder_mem_field(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t agg, usize field_idx); +spl_ir_node_ref_t spl_ir_builder_mem_copy(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t dst, spl_ir_node_ref_t src, + spl_ir_node_ref_t size); +spl_ir_node_ref_t spl_ir_builder_mem_set(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t dst, spl_ir_node_ref_t val, + spl_ir_node_ref_t size); + +spl_ir_node_ref_t spl_ir_builder_type_const_int(spl_ir_builder_t *b, spl_type_id_t tid, usize val); +spl_ir_node_ref_t spl_ir_builder_type_const_float(spl_ir_builder_t *b, spl_type_id_t tid, + double val); +spl_ir_node_ref_t spl_ir_builder_type_const_cstr(spl_ir_builder_t *b, spl_type_id_t tid, + const char *val); +spl_ir_node_ref_t spl_ir_builder_type_const_char(spl_ir_builder_t *b, spl_type_id_t tid, char val); +spl_ir_node_ref_t spl_ir_builder_type_const_fn(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_func_ref_t val); +spl_ir_node_ref_t spl_ir_builder_type_bitsizeof(spl_ir_builder_t *b, spl_type_id_t tid); +spl_ir_node_ref_t spl_ir_builder_type_sizeof(spl_ir_builder_t *b, spl_type_id_t tid); +spl_ir_node_ref_t spl_ir_builder_type_alignof(spl_ir_builder_t *b, spl_type_id_t tid); +spl_ir_node_ref_t spl_ir_builder_type_offsetof(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t field_idx); +spl_ir_node_ref_t spl_ir_builder_type_field_count(spl_ir_builder_t *b, spl_type_id_t tid); + +spl_ir_node_ref_t spl_ir_builder_agg_construct(spl_ir_builder_t *b, spl_type_id_t tid); +void spl_ir_builder_agg_construct_field(spl_ir_builder_t *b, spl_ir_node_ref_t node, + spl_ir_node_ref_t field); +spl_ir_node_ref_t spl_ir_builder_agg_extract(spl_ir_builder_t *b, spl_type_id_t tid, + spl_type_id_t field_tid, usize field_idx, + spl_ir_node_ref_t val); +spl_ir_node_ref_t spl_ir_builder_agg_insert(spl_ir_builder_t *b, spl_type_id_t tid, usize field_idx, + spl_ir_node_ref_t agg, spl_ir_node_ref_t field); + +spl_ir_node_ref_t spl_ir_builder_control_select(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t cond, spl_ir_node_ref_t true_val, + spl_ir_node_ref_t false_val); +spl_ir_node_ref_t spl_ir_builder_control_br(spl_ir_builder_t *b, spl_ir_node_ref_t cond, + spl_ir_node_ref_t true_label, + spl_ir_node_ref_t false_label); +spl_ir_node_ref_t spl_ir_builder_control_jmp(spl_ir_builder_t *b, spl_ir_node_ref_t label); +spl_ir_node_ref_t spl_ir_builder_control_call(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t func); +void spl_ir_builder_control_call_param(spl_ir_builder_t *b, spl_ir_node_ref_t node, + spl_ir_node_ref_t arg); +spl_ir_node_ref_t spl_ir_builder_control_param(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t idx); +spl_ir_node_ref_t spl_ir_builder_control_ret(spl_ir_builder_t *b, spl_type_id_t tid, + spl_ir_node_ref_t val); +spl_ir_node_ref_t spl_ir_builder_control_unreachable(spl_ir_builder_t *b); +spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b); + +spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b); + #endif /* __SPL_IR_H__ */ diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 724ec1b..22fc35e 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -43,15 +43,14 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { if (scope == NULL || name == NULL || out == NULL) { return false; } - spl_symbol_t symbol = {0}; - for (spl_scope_node_t *s = &vec_at(scope->scopes, scope->current_scope); s->parent != 0; + for (spl_scope_node_t *s = &vec_at(scope->scopes, scope->current_scope); s != 0; s = &vec_at(scope->scopes, s->parent)) { - if (map_get(s->symbols, name, &symbol) == true) { - Assert(symbol.kind != SPL_SYMBOL_KIND_ERROR); + if (map_get(s->symbols, name, out) == true) { + Assert(out->kind != SPL_SYMBOL_KIND_ERROR); break; } } - if (symbol.kind == SPL_SYMBOL_KIND_ERROR) { + if (out->kind == SPL_SYMBOL_KIND_ERROR) { return false; } return true; @@ -153,23 +152,71 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { // Parse twice static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { - Assert(sema != NULL && ref != 0); + if (ref == 0) + return; + Assert(sema != NULL); spl_ast_node_t *n = spl_ast_node(sema->ast, ref); spl_symbol_t symbol = {0}; spl_def_id_t def = 0; Assert(n != NULL); switch (n->kind) { case SPL_AST_NONE: - case SPL_AST_CONTAINER_MEMBERS: + UNREACHABLE(); + break; + case SPL_AST_CONTAINER_MEMBERS: { + vec_for(n->container_members, i) { sema_parse(sema, vec_at(n->container_members, i)); } + } break; case SPL_AST_FN_DECL: - case SPL_AST_FN_DEFINE: + case SPL_AST_FN_DEFINE: { + if (n->resolved_def_id == 0) { + Panic("fn `%s` don't collect", n->fn_decl.name); + } + + spl_def_node_t *def = spl_type_def(sema->type, n->resolved_def_id); + def->kind = SPL_DEF_FN_PARAMS; + vec_init(def->fn_params_def); + + spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); + spl_scope_id_t old_id = sema->scope->current_scope; + sema->scope->current_scope = scope_id; + vec_for(n->fn_decl.param_list, i) { + spl_ast_node_ref_t ref = vec_at(n->fn_decl.param_list, i); + // sema_parse(sema, ref); + spl_ast_node_t *node = spl_ast_node(sema->ast, ref); + Assert(node->kind = SPL_AST_PARAM_DECL); + + spl_var_def_t var_def = {0}; + var_def.name = node->param_decl.name; + var_def.scope_id = sema->scope->current_scope; + vec_push(def->fn_params_def, var_def); + } + vec_for(n->fn_decl.block, i) { sema_parse(sema, vec_at(n->fn_decl.block, i)); } + sema->scope->current_scope = old_id; + } break; case SPL_AST_TYPE_DECL: - case SPL_AST_VAR_DECL: + TODO(); + break; + case SPL_AST_VAR_DECL: { + if (n->resolved_def_id == 0) { + symbol.name = n->var_const_decl.name; + symbol.kind = SPL_SYMBOL_KIND_VAR; + symbol.node = spl_type_def_alloc(sema->type); + n->resolved_def_id = symbol.node; + + spl_def_node_t *def = spl_type_def(sema->type, symbol.node); + def->kind = SPL_DEF_VAR; + spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); + } + spl_def_node_t *def_node = spl_type_def(sema->type, n->resolved_def_id); + } break; case SPL_AST_CONST_DECL: case SPL_AST_MEMBER_DECL: + TODO(); + break; case SPL_AST__COMPTIME_STMT: case SPL_AST__DIRECTIVE_BLOCK: case SPL_AST_PARAM_DECL: + break; case SPL_AST_ATTR_ITEM: case SPL_AST_ARGG_INIT_ITEM: case SPL_AST_IF_STATEMENT: @@ -178,7 +225,11 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_LOOP_STATEMENT: case SPL_AST_FOR_STATEMENT: case SPL_AST_MATCH_STATEMENT: - case SPL_AST_RET_STATEMENT: + TODO(); + break; + case SPL_AST_RET_STATEMENT: { + sema_parse(sema, n->ret_statement.expr); + } break; case SPL_AST_BREAK_STATEMENT: case SPL_AST_CONTINUE_STATEMENT: case SPL_AST_DEFER_STATEMENT: @@ -227,6 +278,8 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_INDEX_EXPR: case SPL_AST_SLICE_EXPR: case SPL_AST_AS_EXPR: + TODO(); + break; case SPL_AST_EXPR_INTEGER_LIT: case SPL_AST_EXPR_FLOAT_LIT: case SPL_AST_EXPR_CHAR_LIT: @@ -235,7 +288,15 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_EXPR_FALSE: case SPL_AST_EXPR_NULL: case SPL_AST_EXPR_UNDEFINED: - case SPL_AST_EXPR_IDENT: + break; + case SPL_AST_EXPR_IDENT: { + if (!spl_scope_find(sema->scope, n->primary_expr.ident, &symbol)) { + LOG_FATAL("can't find ident `%s`", n->primary_expr.ident); + return; + } + Assert(symbol.node != 0); + n->resolved_def_id = symbol.node; + } break; case SPL_AST_ARGGREGATE_INIT: case SPL_AST_EXPR_EXPR: case SPL_AST_ARRAY_LIT: @@ -243,6 +304,8 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_BLOCK_EXPR: case SPL_AST_BASE_TYPE_FN: case SPL_AST_BASE_TYPE_PATH: + TODO(); + break; case SPL_AST_TYPE_POINTER: case SPL_AST_TYPE_ARRAY: case SPL_AST_TYPE_SLICE: @@ -267,6 +330,7 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_TYPE__F64: case SPL_AST_TYPE_ANY: case SPL_AST_TYPE_IDENT: + TODO(); break; case SPL_AST_COUNT: UNREACHABLE(); diff --git a/stage1/splc0.c b/stage1/splc0.c index e6abd2d..2ceec24 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -11,7 +11,7 @@ #include #include "spl_ast.h" -// #include "spl_ast2ir.h" +#include "spl_ast2ir.h" // #include "spl_ir2vm.h" #include "spl_lexer.h" #include "spl_sema.h" @@ -107,16 +107,25 @@ static int compile_spl(const char *src, const char *fname, const char *outpath, // memory leak return 0; } - // spl_ast2ir_t a2ir; - // spl_ast2ir_init(&a2ir, &sema); - // spl_ast2ir_run(&a2ir); - // if (a2ir.err_count) { - // printf("ast2ir errors=%d, no output\n", a2ir.err_count); - // spl_ast2ir_drop(&a2ir); - // spl_sema_drop(&sema); - // spl_ast_drop(&ast); - // return 1; - // } + + spl_ast2ir_t a2ir; + spl_ir_builder_t ir_builder; + spl_ir_builder_init(&ir_builder); + spl_ast2ir_init(&a2ir, &ir_builder, &sema); + spl_ast2ir_run(&a2ir); + if (a2ir.err_count) { + printf("ast2ir errors=%d, no output\n", a2ir.err_count); + spl_ast2ir_drop(&a2ir); + spl_sema_drop(&sema); + spl_ast_drop(&ast); + return 1; + } + if (dump == DUMP_IR) { + spl_ir_dump(&ir_builder.ir, &type); + // memory leak + return 0; + } + // spl_ir2vm_t ir2vm; // spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type); // int rc = spl_ir2vm_run(&ir2vm, outpath);