stage1 修复设计问题 实现ir2vm

This commit is contained in:
zzy
2026-08-05 19:13:48 +08:00
parent 2ccee5f1cf
commit ca7cf221c8
11 changed files with 2038 additions and 206 deletions

View File

@@ -12,6 +12,7 @@ splc0_part = [
"stage1/spl_type.c",
"stage1/spl_sema.c",
"stage1/spl_ast2ir.c",
"stage1/spl_ir2vm.c",
]
exe = {

View File

@@ -343,6 +343,14 @@ int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
return 0;
}
int spl_prog_add_instr(spl_prog_t *prog, uint8_t opcode, uint8_t type, spl_val_t imm) {
if (!prog)
return 0;
spl_ins_t ins = (spl_ins_t){.opcode = opcode, .type = type, .imm = imm};
vec_push(prog->insns, ins);
return vec_size(prog->insns);
}
int spl_prog_add_func(spl_prog_t *prog, spl_func_t *func) {
if (!prog || !func)
return 0;

View File

@@ -201,6 +201,7 @@ void spl_prog_drop(spl_prog_t *prog);
int spl_prog_load_from_file(const char *fname, spl_prog_t *prog);
int spl_prog_store_to_file(const char *fname, spl_prog_t *prog);
int spl_prog_add_instr(spl_prog_t *prog, uint8_t opcode, uint8_t type, spl_val_t imm);
int spl_prog_add_data(spl_prog_t *prog, void *ptr, usize size);
int spl_prog_add_func(spl_prog_t *prog, spl_func_t *func);
int spl_prog_add_native(spl_prog_t *prog, spl_native_t *native);

View File

@@ -147,11 +147,11 @@ static spl_tok_t *peek_next(parser_t *p) {
}
static void parse_error(parser_t *p, spl_tok_t *t, const char *msg) {
(void)p;
p->failed = 1; /* 出错即停(上层循环以 !p->failed 提前退出) */
const char *fn = (t && t->fname) ? t->fname : "<unknown>";
usize line = t ? t->line : 0;
usize col = t ? t->col : 0;
LOG_FATAL("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col,
LOG_ERROR("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col,
msg);
}
@@ -223,7 +223,7 @@ static spl_ast_node_ref_t wrap_op_expr(parser_t *p, spl_ast_node_ref_t inner, in
/* ================================================================
* 字面量解 * ================================================================ */
/* 整数字面量去下划线后按0 解析x/0o/0b/十进制,忽略 0b 特判*/
/* 整数字面量:去下划线后按 0x/0o/0b/十进制解析 */
static isize parse_int_literal(const spl_tok_t *t) {
char buf[128];
usize j = 0;
@@ -232,6 +232,11 @@ static isize parse_int_literal(const spl_tok_t *t) {
buf[j++] = t->lexeme[i];
}
buf[j] = 0;
/* strtoll base 0 不认 0b/0o 前缀:单独处理 */
if (j >= 3 && buf[0] == '0' && (buf[1] == 'b' || buf[1] == 'B'))
return (isize)strtoll(buf + 2, NULL, 2);
if (j >= 3 && buf[0] == '0' && (buf[1] == 'o' || buf[1] == 'O'))
return (isize)strtoll(buf + 2, NULL, 8);
return (isize)strtoll(buf, NULL, 0);
}
@@ -637,7 +642,7 @@ static spl_ast_node_ref_vec_t parse_block(parser_t *p) {
vec_init(vec);
if (!expect(p, TOK_L_BRACE, "expected '{'"))
return vec;
while (1) {
while (!p->failed) {
spl_tok_t *t = peek(p);
if (!t || t->type == TOK_EOF) {
parse_error(p, t, "block missing '}'");
@@ -1827,7 +1832,7 @@ void spl_ast_prase(spl_ast_t *ast) {
spl_ast_node_ref_vec_t members;
vec_init(members);
while (1) {
while (!p.failed) {
spl_tok_t *t = peek(&p);
if (!t || t->type == TOK_EOF)
break;

View File

@@ -3,7 +3,7 @@
* 设计要点 * - 名称解析自包含局部变类型用自身环境栈顶层类函数sema root scope 与聚合成员表 * -
* 变量落在内存槽(@mem.alloca写走 @mem.load/store表达式临时值为 SSA * - 控制流用"块表 +
* fixup 补丁"分跳转目标在函数末尾回填为块首指令node ref * -
* 聚合字段访问:读@agg.extract写字节地址直写"@mem.offset + @mem.store * - 枚举=
* 聚合字段访问:读@agg.extract写字节地址直写"@mem.offset + @mem.store<EFBFBD>?* - 枚举=
* agg.construct(enum)([tag, payload?])match tag 分发 * - defer 按作用域逆序执行(正常退/ ret /
* break / continue 全覆盖) */
@@ -95,6 +95,7 @@ static int is_ptr_type(const spl_sema_t *sema, spl_type_id_t tid) {
/* ---- 符号解析 ---- */
static spl_type_id_t agg_field_tid_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, isize idx);
static isize gdata_index_by_def(spl_ast2ir_t *a, spl_def_id_t def_id);
static spl_type_id_t kw_type(spl_ast2ir_t *a, const char *name) {
spl_def_id_t def = 0;
@@ -132,7 +133,7 @@ static spl_def_id_t def_for_type(spl_ast2ir_t *a, spl_type_id_t tid) {
return fallback;
}
/* 判断 agg_def 条目是否为结构字段SPL_DEF_MEMBER */
/* 判断 agg_def 条目是否为结构字段SPL_DEF_MEMBER<EFBFBD>?*/
static int agg_entry_is_field(spl_ast2ir_t *a, const spl_var_def_t *e) {
if (!e->def_id)
return 0;
@@ -140,7 +141,7 @@ static int agg_entry_is_field(spl_ast2ir_t *a, const spl_var_def_t *e) {
return ed && ed->kind == SPL_DEF_MEMBER;
}
/* 命名空间成员类型(方法/嵌套类型/static var按名任意 kind */
/* 命名空间成员类型(方<EFBFBD>?嵌套类型/static var按名任意 kind */
static spl_type_id_t agg_member_type(spl_ast2ir_t *a, spl_type_id_t agg_tid, const char *name) {
agg_tid = underlying(a->sema, agg_tid);
spl_def_id_t d = def_for_type(a, agg_tid);
@@ -154,7 +155,7 @@ static spl_type_id_t agg_member_type(spl_ast2ir_t *a, spl_type_id_t agg_tid, con
return 0;
}
/* 结构字段序号 = 相对 SPL_DEF_MEMBER 的位置(type.agg_field_types 按序对齐 */
/* 结构字段序号 = 相对 SPL_DEF_MEMBER 的位置(<EFBFBD>?type.agg_field_types 按序对齐<EFBFBD>?*/
static isize agg_member_index(spl_ast2ir_t *a, spl_type_id_t agg_tid, const char *name) {
agg_tid = underlying(a->sema, agg_tid);
spl_def_id_t d = def_for_type(a, agg_tid);
@@ -187,7 +188,7 @@ static spl_type_id_t agg_field_tid_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, is
return 0;
}
/* 按字段序号查成员名agg_def 中第 idx SPL_DEF_MEMBER 条目 */
/* 按字段序号查成员名agg_def 中第 idx <EFBFBD>?SPL_DEF_MEMBER 条目<EFBFBD>?*/
static const char *agg_field_name_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, isize idx) {
agg_tid = underlying(a->sema, agg_tid);
spl_def_id_t d = def_for_type(a, agg_tid);
@@ -237,141 +238,6 @@ static spl_type_id_t agg_field_tid_or_builtin(spl_ast2ir_t *a, spl_type_id_t agg
return agg_field_tid_at(a, agg_tid, idx);
}
/* ================================================================
* 类型布局sizeof / alignof / offsetof *
* ================================================================ */
static usize align_up(usize v, usize a) { return (v + a - 1) & ~(a - 1); }
static usize type_align(const spl_sema_t *sema, spl_type_id_t tid) {
spl_type_node_t *t = tn(sema, underlying(sema, tid));
if (!t)
return 1;
switch (t->kind) {
case SPL_TYPE_VOID:
return 1;
case SPL_TYPE_BOOL:
return 1;
case SPL_TYPE_INT:
return t->int_type.bits / 8;
case SPL_TYPE_FLOAT:
return t->float_type.bits / 8;
case SPL_TYPE_PTR:
case SPL_TYPE_FN:
return sizeof(usize);
case SPL_TYPE_SLICE:
case SPL_TYPE_RANGE:
return sizeof(usize);
case SPL_TYPE_ARRAY:
return type_align(sema, t->array_type.element);
case SPL_TYPE_STRUCT: {
usize a = 1;
for (usize i = 0; i < t->agg_field_types.size; i++) {
usize fa = type_align(sema, t->agg_field_types.data[i]);
if (fa > a)
a = fa;
}
return a;
}
case SPL_TYPE_UNION: {
usize a = 1;
for (usize i = 0; i < t->agg_field_types.size; i++) {
usize fa = type_align(sema, t->agg_field_types.data[i]);
if (fa > a)
a = fa;
}
return a;
}
case SPL_TYPE_ENUM:
return sizeof(usize);
default:
return 1;
}
}
static usize type_size(const spl_sema_t *sema, spl_type_id_t tid) {
spl_type_node_t *t = tn(sema, underlying(sema, tid));
if (!t)
return 0;
switch (t->kind) {
case SPL_TYPE_VOID:
return 0;
case SPL_TYPE_BOOL:
return 1;
case SPL_TYPE_INT:
return t->int_type.bits / 8;
case SPL_TYPE_FLOAT:
return t->float_type.bits / 8;
case SPL_TYPE_PTR:
case SPL_TYPE_FN:
return sizeof(usize);
case SPL_TYPE_SLICE:
return sizeof(usize) * 2;
case SPL_TYPE_RANGE:
return sizeof(usize) * 2;
case SPL_TYPE_ARRAY:
return t->array_type.len * type_size(sema, t->array_type.element);
case SPL_TYPE_STRUCT: {
usize sz = 0;
for (usize i = 0; i < t->agg_field_types.size; i++) {
usize fa = type_align(sema, t->agg_field_types.data[i]);
sz = align_up(sz, fa);
sz += type_size(sema, t->agg_field_types.data[i]);
}
return sz;
}
case SPL_TYPE_UNION: {
usize sz = 0;
for (usize i = 0; i < t->agg_field_types.size; i++) {
usize fs = type_size(sema, t->agg_field_types.data[i]);
if (fs > sz)
sz = fs;
}
return sz;
}
case SPL_TYPE_ENUM: {
usize payload = 0;
for (usize i = 0; i < t->enum_type.variants.size; i++) {
spl_type_id_t v = underlying(sema, t->enum_type.variants.data[i]);
if (v == underlying(sema, tid))
continue;
usize vs = type_size(sema, v);
if (vs > payload)
payload = vs;
}
return sizeof(usize) + payload;
}
default:
return 0;
}
}
/* 聚合字段字节偏移struct 顺序对齐union/enum 偏移 0slice/range 内置字段*/
static usize type_field_offset(const spl_sema_t *sema, spl_type_id_t agg_tid, isize idx) {
spl_type_node_t *t = tn(sema, underlying(sema, agg_tid));
if (!t)
return 0;
if (t->kind == SPL_TYPE_SLICE || t->kind == SPL_TYPE_RANGE)
return (usize)idx * sizeof(usize);
if ((usize)idx >= t->agg_field_types.size)
return 0;
switch (t->kind) {
case SPL_TYPE_STRUCT: {
usize off = 0;
for (isize i = 0; i < idx; i++) {
usize fa = type_align(sema, t->agg_field_types.data[i]);
off = align_up(off, fa);
off += type_size(sema, t->agg_field_types.data[i]);
}
return align_up(off, type_align(sema, t->agg_field_types.data[idx]));
}
case SPL_TYPE_UNION:
case SPL_TYPE_ENUM:
default:
return 0;
}
}
/* ================================================================
* IR 发射per-function 上下文)
* ================================================================ */
@@ -412,6 +278,7 @@ typedef VEC(ir_loop_t) ir_loop_vec_t;
typedef struct {
spl_ir_func_ref_t fn;
spl_ast2ir_t *a;
spl_type_id_t ret_tid;
spl_type_id_t ns_tid; /* 所在聚合类型方法命名空间顶层0 */
ir_env_stack_t env;
@@ -425,8 +292,9 @@ typedef struct {
int err;
} fnctx_t;
static void fc_init(fnctx_t *fc, spl_ir_func_ref_t fn, spl_type_id_t ret) {
static void fc_init(fnctx_t *fc, spl_ast2ir_t *a, spl_ir_func_ref_t fn, spl_type_id_t ret) {
memset(fc, 0, sizeof *fc);
fc->a = a;
fc->fn = fn;
fc->ret_tid = ret;
vec_init(fc->env);
@@ -436,8 +304,9 @@ static void fc_init(fnctx_t *fc, spl_ir_func_ref_t fn, spl_type_id_t ret) {
vec_init(fc->types);
}
static void fc_init_ns(fnctx_t *fc, spl_ir_func_ref_t fn, spl_type_id_t ret, spl_type_id_t ns) {
fc_init(fc, fn, ret);
static void fc_init_ns(fnctx_t *fc, spl_ast2ir_t *a, spl_ir_func_ref_t fn, spl_type_id_t ret,
spl_type_id_t ns) {
fc_init(fc, a, fn, ret);
fc->ns_tid = ns;
}
@@ -664,6 +533,34 @@ static spl_ir_node_ref_t emit_offset(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t
return n;
}
/* 字段地址mem.field_ptr(agg_tid, agg, idx) → *field_type。布局偏移由 ir2vm 算ast2ir 不算。 */
static spl_ir_node_ref_t emit_field(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t agg_tid,
spl_ir_node_ref_t ptr, isize fidx) {
spl_type_id_t fty = agg_field_tid_or_builtin(a, agg_tid, fidx);
spl_ir_node_ref_t n = emit_node(a, fc);
spl_ir_node_t *e = enode(a, fc, n);
e->kind = SPL_IR_MEM_FIELD_PTR;
e->mem_field_ptr.tid = underlying(a->sema, agg_tid);
e->mem_field_ptr.agg = ptr;
e->mem_field_ptr.field_idx = (usize)fidx;
spl_type_id_t pt = spl_type_ptr((spl_type_t *)&a->sema->type, fty);
set_ntype(fc, n, pt);
return n;
}
/* 全局静态数据地址mem.global_alloc(tid, gdata_idx) <20>?*tid */
static spl_ir_node_ref_t emit_global_alloc(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid,
usize gdata_idx) {
spl_ir_node_ref_t n = emit_node(a, fc);
spl_ir_node_t *e = enode(a, fc, n);
e->kind = SPL_IR_MEM_GLOBAL_ALLOC;
e->mem_global_alloc.tid = tid;
e->mem_global_alloc.const_node = gdata_idx;
spl_type_id_t pt = spl_type_ptr((spl_type_t *)&a->sema->type, tid);
set_ntype(fc, n, pt);
return n;
}
static spl_ir_node_ref_t emit_agg_construct(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid) {
spl_ir_node_ref_t n = emit_node(a, fc);
spl_ir_node_t *e = enode(a, fc, n);
@@ -687,6 +584,7 @@ static spl_ir_node_ref_t emit_agg_extract(spl_ast2ir_t *a, fnctx_t *fc, spl_type
spl_ir_node_t *e = enode(a, fc, n);
e->kind = SPL_IR_AGG_EXTRACT;
e->agg_extract.tid = tid;
e->agg_extract.field_tid = field_tid;
e->agg_extract.field_idx = fidx;
e->agg_extract.val = val;
set_ntype(fc, n, field_tid);
@@ -767,7 +665,7 @@ static ir_env_t *env_find(fnctx_t *fc, const char *name) {
return NULL;
}
/* def_id 优先定位sema 已作用域解析,绕开同名遮蔽歧义);def_id 时兜底名*/
/* def_id 优先定位sema 已作用域解析,绕开同名遮蔽歧义);<EFBFBD>?def_id 时兜底名<EFBFBD>?*/
static ir_env_t *env_find_def(fnctx_t *fc, spl_def_id_t def_id, const char *name) {
if (def_id) {
for (usize i = fc->env.size; i > 0; i--) {
@@ -842,6 +740,17 @@ static spl_ir_node_ref_t enum_tag_of(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t
return emit_agg_extract(a, fc, enum_tid, enum_tag_tid(a), 0, val);
}
/* tid 是否<E698AF>?enum */
static int is_enum_expand(spl_ast2ir_t *a, spl_type_id_t tid, spl_type_id_t *out_enum) {
spl_type_node_t *t = tn(a->sema, underlying(a->sema, tid));
if (t && t->kind == SPL_TYPE_ENUM) {
if (out_enum)
*out_enum = underlying(a->sema, tid);
return 1;
}
return 0;
}
/* 表达式当作类型引用解析a / a.b.c用于枚举变嵌套类型路径*/
static spl_type_id_t type_of_type_ref(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t bref) {
spl_ast_node_t *n = node_at(a->sema, bref);
@@ -956,13 +865,13 @@ static spl_type_id_t resolve_type_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod
spl_ast_node_t *n = node_at(a->sema, ref);
if (!n)
return 0;
/* 首sema 注解resolved_def_id def 类型(聚合/别名/命名类型 */
/* 首<EFBFBD>?sema 注解resolved_def_id <EFBFBD>?def <EFBFBD>?类型(聚<EFBFBD>?别名/命名类型<EFBFBD>?*/
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(...)、关键字、别名到组合 */
/* 兜底:组<EFBFBD>?内置类型sema 不为其建 def <EFBFBD>?*T、[]T、fn(...)、关键字、别名到组合<EFBFBD>?*/
spl_type_id_t base = 0;
switch (n->type_expr.kind) {
case SPL_AST_BASE_TYPE_PATH:
@@ -989,7 +898,7 @@ static spl_type_id_t resolve_type_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod
case SPL_AST_TYPE_STRUCT:
case SPL_AST_TYPE_UNION:
case SPL_AST_TYPE_ENUM:
/* 内联聚合不应走到这里sema 已注解其 def防御性报*/
/* 内联聚合不应走到这里sema 已注解其 def防御性报<EFBFBD>?*/
diag(a, fc, ref, "inline aggregate not annotated by sema");
return 0;
default:
@@ -1110,16 +1019,7 @@ static spl_ast_node_ref_t field_chain_base(spl_ast2ir_t *a, spl_ast_node_t *pf,
return bref;
}
/* 指针按字节偏移mem.offset u8 为单位即字节*/
static spl_ir_node_ref_t ptr_add_bytes(spl_ast2ir_t *a, fnctx_t *fc, spl_ir_node_ref_t addr,
usize bytes) {
if (!bytes || !addr)
return addr;
spl_ir_node_ref_t c = const_int(a, fc, kw_type(a, "usize"), bytes);
return emit_offset(a, fc, kw_type(a, "u8"), addr, c);
}
/* 字段链的存储地址root.a.b 地址 + 字段类型*/
/* 字段链的存储地址root.a.b 地址 + 字段类型<E7B1BB>?*/
static spl_ir_node_ref_t lower_field_address(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t bref,
spl_type_id_t *out_tid) {
spl_ast_node_t *n = node_at(a->sema, bref);
@@ -1131,12 +1031,34 @@ static spl_ir_node_ref_t lower_field_address(spl_ast2ir_t *a, fnctx_t *fc, spl_a
const char *names[MAX_FIELD_CHAIN];
int nf = 0;
spl_ast_node_ref_t root_ref = field_chain_base(a, pf, names, &nf);
/* 类型命名空间基址Foo.counter全局 var/const <20>?lvalue = <20>?gdata 地址<E59CB0>?*/
spl_type_id_t ns = type_of_type_ref(a, fc, root_ref);
if (ns && nf == 1) {
spl_def_id_t gdef = def_for_type(a, ns);
spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL;
for (usize i = 0; gd && i < gd->agg_def.size; i++) {
spl_var_def_t *e = &gd->agg_def.data[i];
if (e->name && strcmp(e->name, names[0]) == 0 && e->def_id) {
spl_def_node_t *ed = def_at(a->sema, e->def_id);
if (ed && ed->kind == SPL_DEF_VAR) {
isize gi = gdata_index_by_def(a, e->def_id);
if (gi >= 0) {
*out_tid = e->type_id;
return emit_global_alloc(a, fc, e->type_id, (usize)gi);
}
}
break;
}
}
return 0;
}
spl_type_id_t cur_tid = 0;
spl_ir_node_ref_t addr = lower_lvalue(a, fc, root_ref, &cur_tid);
spl_type_node_t *curt = tn(a->sema, underlying(a->sema, cur_tid));
if (curt && curt->kind == SPL_TYPE_PTR) {
cur_tid = underlying(a->sema, curt->ptr_pointee);
addr = emit_load(a, fc, cur_tid, addr);
spl_type_id_t pty = spl_type_ptr((spl_type_t *)&a->sema->type, cur_tid);
addr = emit_load(a, fc, pty, addr);
}
if (!addr || !cur_tid)
return 0;
@@ -1148,16 +1070,15 @@ static spl_ir_node_ref_t lower_field_address(spl_ast2ir_t *a, fnctx_t *fc, spl_a
isize idx = agg_index_or_builtin(a, cur_tid, names[i]);
if (idx < 0)
return 0;
usize off = type_field_offset(a->sema, cur_tid, idx);
spl_type_id_t ft = agg_field_tid_or_builtin(a, cur_tid, idx);
if (off)
addr = ptr_add_bytes(a, fc, addr, off);
addr = emit_field(a, fc, cur_tid, addr, idx);
cur_tid = ft;
if (i > 0) {
spl_type_node_t *ftt = tn(a->sema, underlying(a->sema, cur_tid));
if (ftt && ftt->kind == SPL_TYPE_PTR) {
cur_tid = underlying(a->sema, ftt->ptr_pointee);
addr = emit_load(a, fc, cur_tid, addr);
spl_type_id_t pty = spl_type_ptr((spl_type_t *)&a->sema->type, cur_tid);
addr = emit_load(a, fc, pty, addr);
}
}
}
@@ -1244,8 +1165,42 @@ static spl_ir_node_ref_t lower_lvalue(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node
*out_tid = it->tid;
return it->slot;
}
if (it)
if (it) {
diag(a, fc, ref, "not an addressable variable");
return 0;
}
/* 顶层 / 命名空间全局 varlvalue = 全局分配地址 */
spl_def_id_t def = pn->resolved_def_id;
if (!def)
def = root_lookup(a, pn->primary_expr.ident);
if (def) {
spl_def_node_t *d = def_at(a->sema, def);
if (d && d->kind == SPL_DEF_VAR) {
isize gi = gdata_index_by_def(a, def);
if (gi >= 0) {
*out_tid = d->type_id;
return emit_global_alloc(a, fc, *out_tid, (usize)gi);
}
}
if (fc->ns_tid) {
spl_def_id_t gdef = def_for_type(a, fc->ns_tid);
spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL;
for (usize i = 0; gd && i < gd->agg_def.size; i++) {
spl_var_def_t *e = &gd->agg_def.data[i];
if (e->name && strcmp(e->name, pn->primary_expr.ident) == 0 && e->def_id) {
spl_def_node_t *ed = def_at(a->sema, e->def_id);
if (ed && ed->kind == SPL_DEF_VAR) {
isize gi = gdata_index_by_def(a, e->def_id);
if (gi >= 0) {
*out_tid = e->type_id;
return emit_global_alloc(a, fc, e->type_id, (usize)gi);
}
}
break;
}
}
}
}
return 0;
}
if (pn && pn->primary_expr.kind == SPL_AST_EXPR_EXPR)
@@ -1307,11 +1262,36 @@ static spl_ir_node_ref_t lower_ident(spl_ast2ir_t *a, fnctx_t *fc, const char *n
if (def) {
spl_def_node_t *d = def_at(a->sema, def);
if (d &&
(d->kind == SPL_DEF_AGG || d->kind == SPL_DEF_ALIAS || d->kind == SPL_DEF_DISTINCT))
diag(a, fc, ref, "type name used as value (aggregate member not supported)");
else
diag(a, fc, ref, "undefined identifier");
(d->kind == SPL_DEF_AGG || d->kind == SPL_DEF_ALIAS || d->kind == SPL_DEF_DISTINCT)) {
diag(a, fc, ref, "type name used as value");
return 0;
}
if (d && d->kind == SPL_DEF_VAR) {
isize gi = gdata_index_by_def(a, def);
if (gi >= 0)
return emit_load(a, fc, d->type_id,
emit_global_alloc(a, fc, d->type_id, (usize)gi));
}
diag(a, fc, ref, "undefined identifier");
} else {
/* 命名空间内裸名fc->ns_tid 聚合成员 static var/const */
if (fc->ns_tid) {
spl_def_id_t gdef = def_for_type(a, fc->ns_tid);
spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL;
for (usize i = 0; gd && i < gd->agg_def.size; i++) {
spl_var_def_t *e = &gd->agg_def.data[i];
if (e->name && strcmp(e->name, name) == 0 && e->def_id) {
spl_def_node_t *ed = def_at(a->sema, e->def_id);
if (ed && ed->kind == SPL_DEF_VAR) {
isize gi = gdata_index_by_def(a, e->def_id);
if (gi >= 0)
return emit_load(a, fc, e->type_id,
emit_global_alloc(a, fc, e->type_id, (usize)gi));
}
break;
}
}
}
diag(a, fc, ref, "undefined identifier");
}
return 0;
@@ -1413,15 +1393,20 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod
elem = kw_type(a, "i32");
spl_type_id_t arr = spl_type_array((spl_type_t *)&a->sema->type, elem,
(usize)pn->primary_expr.array_lit_expr.integer);
spl_ir_node_ref_t agg = emit_agg_construct(a, fc, arr);
VEC(spl_ir_node_ref_t) vals;
vec_init(vals);
for (usize i = 0; i < pn->primary_expr.array_lit_expr.expr_list.size; i++) {
fc->hint = elem;
spl_ir_node_ref_t v =
lower_expr(a, fc, pn->primary_expr.array_lit_expr.expr_list.data[i]);
fc->hint = 0;
v = coerce_to(a, fc, v, node_type(fc, v), elem);
agg_construct_add(a, fc, agg, v);
vec_push(vals, v);
}
spl_ir_node_ref_t agg = emit_agg_construct(a, fc, arr);
for (usize i = 0; i < vals.size; i++)
agg_construct_add(a, fc, agg, vals.data[i]);
vec_free(vals);
return agg;
}
case SPL_AST_ARGGREGATE_INIT: {
@@ -1443,7 +1428,8 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod
diag(a, fc, 0, "anonymous aggregate literal without context type");
return 0;
}
spl_ir_node_ref_t agg = emit_agg_construct(a, fc, hint_t);
VEC(spl_ir_node_ref_t) vals;
vec_init(vals);
for (usize j = 0; j < pn->primary_expr.aggregate_init.expr.size; j++) {
spl_ast_node_t *item =
node_at(a->sema, pn->primary_expr.aggregate_init.expr.data[j]);
@@ -1456,17 +1442,34 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod
}
spl_type_id_t ft = agg_field_tid_or_builtin(a, hint_t, fidx);
spl_ir_node_ref_t v = lower_expr(a, fc, item->aggregate_init_item.expr);
/* 字段是指针、值是聚合 lvalue自动取地址<E59CB0>?left = expr 语义<E8AFAD>?*/
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, &lt);
if (addr)
v = addr;
}
if (ft)
v = coerce_to(a, fc, v, node_type(fc, v), ft);
agg_construct_add(a, fc, agg, v);
vec_push(vals, v);
}
spl_ir_node_ref_t agg = emit_agg_construct(a, fc, hint_t);
for (usize i = 0; i < vals.size; i++)
agg_construct_add(a, fc, agg, vals.data[i]);
vec_free(vals);
return agg;
}
spl_type_node_t *tt = tn(a->sema, tid);
if (!tt)
return 0;
if (tt->kind == SPL_TYPE_ENUM) {
spl_ir_node_ref_t agg = emit_agg_construct(a, fc, tid);
VEC(spl_ir_node_ref_t) vals;
vec_init(vals);
for (usize j = 0; j < pn->primary_expr.aggregate_init.expr.size; j++) {
spl_ast_node_t *item =
node_at(a->sema, pn->primary_expr.aggregate_init.expr.data[j]);
@@ -1477,7 +1480,7 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod
diag(a, fc, 0, "unknown enum variant");
continue;
}
agg_construct_add(a, fc, agg, const_int(a, fc, enum_tag_tid(a), (usize)vidx));
vec_push(vals, const_int(a, fc, enum_tag_tid(a), (usize)vidx));
if (item->aggregate_init_item.expr) {
spl_type_id_t pt = enum_payload_tid(a, tid, vidx);
fc->hint = pt;
@@ -1485,17 +1488,23 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod
fc->hint = 0;
if (pt)
pv = coerce_to(a, fc, pv, node_type(fc, pv), pt);
agg_construct_add(a, fc, agg, pv);
vec_push(vals, pv);
}
}
spl_ir_node_ref_t agg = emit_agg_construct(a, fc, tid);
for (usize i = 0; i < vals.size; i++)
agg_construct_add(a, fc, agg, vals.data[i]);
vec_free(vals);
return agg;
}
if (tt->kind != SPL_TYPE_STRUCT) {
diag(a, fc, 0, "aggregate literal target is not a struct");
return 0;
}
spl_ir_node_ref_t agg = emit_agg_construct(a, fc, tid);
spl_ir_node_ref_t agg = 0;
usize nfields = tt->agg_field_types.size;
VEC(spl_ir_node_ref_t) vals;
vec_init(vals);
for (usize i = 0; i < nfields; i++) {
const char *fname = agg_field_name_at(a, tid, (isize)i);
spl_ast_node_ref_t found = 0;
@@ -1509,16 +1518,31 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod
}
}
if (!found) {
agg_construct_add(a, fc, agg, const_int(a, fc, tt->agg_field_types.data[i], 0));
vec_push(vals, const_int(a, fc, tt->agg_field_types.data[i], 0));
continue;
}
spl_ast_node_t *item = node_at(a->sema, found);
fc->hint = tt->agg_field_types.data[i];
spl_ir_node_ref_t v = lower_expr(a, fc, item->aggregate_init_item.expr);
fc->hint = 0;
/* 字段是指针、值是聚合 lvalue自动取地址<E59CB0>?left = expr 语义<E8AFAD>?*/
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, &lt);
if (addr)
v = addr;
}
v = coerce_to(a, fc, v, node_type(fc, v), tt->agg_field_types.data[i]);
agg_construct_add(a, fc, agg, v);
vec_push(vals, v);
}
agg = emit_agg_construct(a, fc, tid);
for (usize i = 0; i < vals.size; i++)
agg_construct_add(a, fc, agg, vals.data[i]);
vec_free(vals);
return agg;
}
case SPL_AST_BUILTIN_EXPR: {
@@ -1695,7 +1719,12 @@ static int resolve_callee(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t base,
vt = underlying(a->sema, vtt->ptr_pointee);
vtt = tn(a->sema, vt);
}
spl_type_id_t mt = vtt ? agg_member_type(a, vt, fname) : 0;
/* enum 方法:在原 enum def 上查找 */
spl_type_id_t lookup = vt;
spl_type_id_t e0 = 0;
if (vtt && is_enum_expand(a, vt, &e0))
lookup = e0;
spl_type_id_t mt = vtt ? agg_member_type(a, lookup, fname) : 0;
spl_type_node_t *mtn = mt ? tn(a->sema, mt) : NULL;
if (mt && mtn && mtn->kind == SPL_TYPE_FN) {
out->fn_tid = mt;
@@ -1730,6 +1759,22 @@ static spl_ir_node_ref_t lower_field(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_
if (vidx >= 0)
return enum_variant_value(a, fc, ttr, vidx);
}
/* 聚合命名空间成员static var/const <20>?全局数据 */
spl_def_id_t gdef = def_for_type(a, ttr);
spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL;
for (usize i = 0; gd && i < gd->agg_def.size; i++) {
spl_var_def_t *e = &gd->agg_def.data[i];
if (e->name && strcmp(e->name, fname) == 0 && e->def_id) {
spl_def_node_t *ed = def_at(a->sema, e->def_id);
if (ed && ed->kind == SPL_DEF_VAR) {
isize gi = gdata_index_by_def(a, e->def_id);
if (gi >= 0)
return emit_load(a, fc, e->type_id,
emit_global_alloc(a, fc, e->type_id, (usize)gi));
}
break;
}
}
diag(a, fc, 0, "aggregate member is not a value");
return 0;
}
@@ -1962,12 +2007,13 @@ static spl_ir_node_ref_t lower_binary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node
spl_ir_node_ref_t r = lower_expr(a, fc, rr);
spl_type_id_t lt = underlying(a->sema, node_type(fc, l));
spl_type_id_t rt = underlying(a->sema, node_type(fc, r));
spl_type_node_t *ltt = tn(a->sema, lt);
spl_type_node_t *rtt = tn(a->sema, rt);
if (ltt && ltt->kind == SPL_TYPE_ENUM && rtt && rtt->kind == SPL_TYPE_ENUM) {
spl_type_id_t le = 0, re = 0;
int is_l_enum = is_enum_expand(a, lt, &le);
int is_r_enum = is_enum_expand(a, rt, &re);
if (is_l_enum && is_r_enum) {
spl_type_id_t tag_t = enum_tag_tid(a);
l = enum_tag_of(a, fc, lt, l);
r = enum_tag_of(a, fc, rt, r);
l = enum_tag_of(a, fc, le, l);
r = enum_tag_of(a, fc, re, r);
lt = tag_t;
rt = tag_t;
}
@@ -2038,12 +2084,11 @@ static spl_ir_node_ref_t lower_range_value(spl_ast2ir_t *a, fnctx_t *fc, spl_ast
spl_ir_node_ref_t b = lower_expr(a, fc, n->expr.op_expr.left);
spl_type_id_t et = underlying(a->sema, node_type(fc, b));
spl_type_id_t range_t = spl_type_range((spl_type_t *)&a->sema->type, et);
spl_ir_node_ref_t e =
n->expr.op_expr.right ? lower_expr(a, fc, n->expr.op_expr.right) : const_int(a, fc, et, 0);
spl_ir_node_ref_t r = emit_agg_construct(a, fc, range_t);
agg_construct_add(a, fc, r, b);
if (n->expr.op_expr.right)
agg_construct_add(a, fc, r, lower_expr(a, fc, n->expr.op_expr.right));
else
agg_construct_add(a, fc, r, const_int(a, fc, et, 0));
agg_construct_add(a, fc, r, e);
return r;
}
@@ -2116,16 +2161,53 @@ static spl_ir_node_ref_t lower_assign(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node
spl_ast_node_t *pn = node_at(a->sema, ln->expr.op_expr.left);
if (pn && pn->primary_expr.kind == SPL_AST_IDENT) {
ir_env_t *it = env_find_def(fc, pn->resolved_def_id, pn->primary_expr.ident);
if (!it || !it->slot) {
spl_type_id_t lt = 0;
spl_ir_node_ref_t target = 0;
if (it && it->slot) {
lt = it->tid;
target = it->slot;
} else {
/* 全局 var<EFBC88>?/ 命名空间裸名<E8A3B8>?*/
spl_def_id_t def = pn->resolved_def_id;
if (!def)
def = root_lookup(a, pn->primary_expr.ident);
if (def) {
spl_def_node_t *d = def_at(a->sema, def);
isize gi0 = (d && d->kind == SPL_DEF_VAR) ? gdata_index_by_def(a, def) : -1;
if (gi0 >= 0) {
lt = d->type_id;
target = emit_global_alloc(a, fc, lt, (usize)gi0);
} else if (fc->ns_tid) {
spl_def_id_t gdef = def_for_type(a, fc->ns_tid);
spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL;
for (usize i = 0; gd && i < gd->agg_def.size; i++) {
spl_var_def_t *e = &gd->agg_def.data[i];
if (e->name && strcmp(e->name, pn->primary_expr.ident) == 0 &&
e->def_id) {
spl_def_node_t *ed = def_at(a->sema, e->def_id);
if (ed && ed->kind == SPL_DEF_VAR) {
isize gi = gdata_index_by_def(a, e->def_id);
if (gi >= 0) {
lt = e->type_id;
target = emit_global_alloc(a, fc, e->type_id, (usize)gi);
}
}
break;
}
}
}
}
}
if (!target || !lt) {
diag(a, fc, lr, "assignment target not writable");
return 0;
}
spl_ir_node_ref_t cur = compound ? emit_load(a, fc, it->tid, it->slot) : 0;
spl_ir_node_ref_t cur = compound ? emit_load(a, fc, lt, target) : 0;
spl_ir_node_ref_t v = lower_expr(a, fc, rr);
if (compound)
v = lower_compound_op(a, fc, n->expr.op, it->tid, cur, v);
v = coerce_to(a, fc, v, node_type(fc, v), it->tid);
emit_store(a, fc, it->tid, it->slot, v);
v = lower_compound_op(a, fc, n->expr.op, lt, cur, v);
v = coerce_to(a, fc, v, node_type(fc, v), lt);
emit_store(a, fc, lt, target, v);
return v;
}
}
@@ -2434,7 +2516,10 @@ static void lower_for(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) {
for (usize i = 0; i < nseq; i++) {
if (!seqs[i].len)
continue;
spl_ir_node_ref_t l = coerce_to(a, fc, seqs[i].len, node_type(fc, seqs[i].len), iszt);
spl_ir_node_ref_t lenv = seqs[i].len;
if (seqs[i].kind == FOR_SLICE)
lenv = emit_load(a, fc, kw_type(a, "usize"), seqs[i].len);
spl_ir_node_ref_t l = coerce_to(a, fc, lenv, node_type(fc, lenv), iszt);
if (!m) {
m = l;
} else {
@@ -2472,7 +2557,12 @@ static void lower_for(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) {
v = emit_arith(a, fc, SPL_IR_ARITH_ADD, s->elem_tid, bg,
coerce_to(a, fc, cur, iszt, s->elem_tid));
} else {
spl_ir_node_ref_t addr = emit_offset(a, fc, s->elem_tid, s->base_slot, cur);
spl_ir_node_ref_t base = s->base_slot;
if (s->kind == FOR_SLICE) {
spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, s->elem_tid);
base = emit_load(a, fc, ep, s->base_slot);
}
spl_ir_node_ref_t addr = emit_offset(a, fc, s->elem_tid, base, cur);
v = emit_load(a, fc, s->elem_tid, addr);
}
ir_env_t *it = env_find(fc, id_data[i]);
@@ -2575,6 +2665,7 @@ static void lower_match(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) {
spl_type_id_t pt = enum_payload_tid(a, st, vidx);
if (pt) {
spl_ir_node_ref_t sv = emit_load(a, fc, st, subj_slot);
/* enum 布局 = tag(0) + payload(8)直接提<E68EA5>?payloadfield_tid = 变体具体类型 */
spl_ir_node_ref_t pv = emit_agg_extract(a, fc, st, pt, 1, sv);
spl_ir_node_ref_t bslot = emit_alloca(a, fc, pt);
emit_store(a, fc, pt, bslot, pv);
@@ -2693,7 +2784,7 @@ static void lower_stmt(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) {
* ================================================================ */
static spl_ir_func_ref_t a2ir_fn_of(spl_ast2ir_t *a, spl_type_id_t fn_tid) {
/* 懒扫描IR func 已记fn_tidspl_type_fn 不去重fn_tid 唯一 */
/* 懒扫描IR func 已记<EFBFBD>?fn_tidspl_type_fn 不去重fn_tid 唯一<EFBFBD>?*/
for (usize i = 1; i < a->ir.funcs.size; i++) {
if (a->ir.funcs.data[i].fn_tid == fn_tid)
return i;
@@ -2709,7 +2800,7 @@ static void lower_func_body(spl_ast2ir_t *a, spl_ir_func_ref_t fid, spl_type_id_
spl_type_node_t *ft = tn(a->sema, fn_tid);
spl_type_id_t ret = (ft && ft->kind == SPL_TYPE_FN) ? ft->fn_type.ret : 0;
fnctx_t fc;
fc_init_ns(&fc, fid, ret, ns_tid);
fc_init_ns(&fc, a, fid, ret, ns_tid);
spl_ast_node_ref_vec_t *pl = &fn->fn_decl.param_list;
usize nparams = (ft && ft->kind == SPL_TYPE_FN) ? ft->fn_type.params.size : 0;
env_push(&fc);
@@ -2774,9 +2865,136 @@ void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {
for (usize i = 0; i < ast2ir->owned_names.size; i++)
free(ast2ir->owned_names.data[i]);
vec_free(ast2ir->owned_names);
vec_free(ast2ir->gdata_ref);
spl_ir_drop(&ast2ir->ir);
}
/* ================================================================
* 全局数据(聚合类型下 / 顶层<E9A1B6>?var、const<73>?
* ================================================================ */
/* 常量折叠仅支持字面量int/char/float/string/null与一元负<E58583>?*/
typedef struct {
int const_init;
isize int_v;
double float_v;
const char *cstr_v;
} gfold_t;
static void fold_const_init(spl_ast2ir_t *a, spl_ast_node_ref_t ref, gfold_t *g) {
spl_ast_node_t *n = node_at(a->sema, ref);
if (!n || n->kind != SPL_AST_EXPR)
return;
if (n->expr.op == SPL_AST_PRIMARY_EXPR) {
spl_ast_node_t *pn = node_at(a->sema, n->expr.op_expr.left);
if (!pn)
return;
switch (pn->primary_expr.kind) {
case SPL_AST_INTEGER:
g->const_init = 1;
g->int_v = pn->primary_expr.integer_expr;
return;
case SPL_AST_CHAR_LIT:
g->const_init = 1;
g->int_v = (isize)(unsigned char)pn->primary_expr.char_lit_expr;
return;
case SPL_AST_FLOAT:
g->const_init = 1;
g->float_v = pn->primary_expr.float_expr;
return;
case SPL_AST_NULL:
g->const_init = 1;
g->int_v = 0;
return;
case SPL_AST_STRING_LIT:
g->const_init = 1;
g->cstr_v = pn->primary_expr.string_lit_expr;
return;
default:
return;
}
}
if (n->expr.op == SPL_AST_PREFIX_EXPR) {
spl_ast_node_t *pp = node_at(a->sema, n->expr.op_expr.left);
if (pp && pp->prefix_expr.kind == SPL_AST_MINUS_EXPR) {
fold_const_init(a, pp->prefix_expr.postfix_expr, g);
if (g->const_init)
g->int_v = -g->int_v;
}
}
}
static void collect_gdata_list(spl_ast2ir_t *a, spl_ast_node_ref_vec_t *members) {
for (usize i = 0; i < members->size; i++) {
spl_ast_node_t *m = node_at(a->sema, members->data[i]);
if (!m)
continue;
const char *mname = NULL;
spl_ast_node_ref_t iexpr = 0;
if (m->kind == SPL_AST_VAR_DECL) {
mname = m->var_decl.name;
iexpr = m->var_decl.expr;
} else if (m->kind == SPL_AST_CONST_DECL) {
mname = m->const_decl.name;
iexpr = m->const_decl.expr;
} else {
continue;
}
if (!mname || !m->resolved_def_id)
continue;
spl_def_node_t *d = def_at(a->sema, m->resolved_def_id);
if (!d)
continue;
gfold_t g;
memset(&g, 0, sizeof g);
spl_type_id_t g_tid = d->type_id;
if (iexpr)
fold_const_init(a, iexpr, &g);
/* 全局 value = type.const 节点(标量折叠值;聚合/无 init 零) */
spl_ir_node_t v;
memset(&v, 0, sizeof v);
v.kind = SPL_IR_TYPE_CONST;
v.type_const.tid = g_tid;
spl_type_node_t *gt = tn(a->sema, underlying(a->sema, g_tid));
if (g.const_init && gt && gt->kind == SPL_TYPE_INT)
v.type_const.int_lit = (usize)g.int_v;
else if (g.const_init && gt && gt->kind == SPL_TYPE_FLOAT)
v.type_const.float_lit = g.float_v;
else
v.type_const.int_lit = 0;
vec_push(a->ir.gdata, v);
spl_ast2ir_gref_t gr = {m->resolved_def_id, a->ir.gdata.size - 1};
vec_push(a->gdata_ref, gr);
}
}
static void collect_gdata(spl_ast2ir_t *a) {
spl_ast_node_t *root = node_at(a->sema, a->sema->ast->root);
if (!root || root->kind != SPL_AST_CONTAINER_ITEM)
return;
collect_gdata_list(a, &root->container_item.members);
for (usize i = 0; i < root->container_item.members.size; i++) {
spl_ast_node_ref_t mref = root->container_item.members.data[i];
spl_ast_node_t *m = node_at(a->sema, mref);
if (!m || m->kind != SPL_AST_TYPE_DECL)
continue;
spl_ast_node_t *te = node_at(a->sema, m->type_decl.type_expr);
if (!te ||
(te->type_expr.kind != SPL_AST_TYPE_STRUCT &&
te->type_expr.kind != SPL_AST_TYPE_UNION && te->type_expr.kind != SPL_AST_TYPE_ENUM))
continue;
collect_gdata_list(a, &te->type_expr.aggregate_list);
}
}
/* def_id <20>?gdata value 节点索引;未命中返回 -1 */
static isize gdata_index_by_def(spl_ast2ir_t *a, spl_def_id_t def_id) {
for (usize i = 0; i < a->gdata_ref.size; i++)
if (a->gdata_ref.data[i].def_id == def_id)
return (isize)a->gdata_ref.data[i].gdata_idx;
return -1;
}
/* ================================================================
* 预登记:为所有函数(顶层 + 聚合方法)建 IR func
* ================================================================ */
@@ -2838,6 +3056,8 @@ void spl_ast2ir_run(spl_ast2ir_t *a) {
spl_ast_node_t *root = node_at(a->sema, a->sema->ast->root);
if (!root || root->kind != SPL_AST_CONTAINER_ITEM)
return;
vec_init(a->gdata_ref);
collect_gdata(a);
register_funcs(a);
for (usize i = 0; i < root->container_item.members.size; i++) {
spl_ast_node_ref_t mref = root->container_item.members.data[i];

View File

@@ -4,10 +4,17 @@
#include "spl_ir.h"
#include "spl_sema.h"
/* 全局 var/const 的 def → gdata 向量中的 value 节点索引 */
typedef struct {
spl_def_id_t def_id;
usize gdata_idx;
} spl_ast2ir_gref_t;
typedef struct {
const spl_sema_t *sema;
spl_ir_t ir;
VEC(char *) owned_names; /* 本模块 malloc 的函数名drop 时释放 */
VEC(char *) owned_names; /* 本模块 malloc 的函数名drop 时释放 */
VEC(spl_ast2ir_gref_t) gdata_ref; /* def_id → gdata value 节点索引 */
int err_count;
} spl_ast2ir_t;

View File

@@ -15,6 +15,7 @@ static const char *const ir_kind_names[] = {
void spl_ir_init(spl_ir_t *ir) {
memset(ir, 0, sizeof *ir);
vec_init(ir->funcs);
vec_init(ir->gdata);
/* func ref 0 保留为 error占位 */
spl_ir_func_t f0;
memset(&f0, 0, sizeof f0);
@@ -45,6 +46,9 @@ void spl_ir_drop(spl_ir_t *ir) {
vec_free(f->labels);
}
vec_free(ir->funcs);
for (usize i = 0; i < ir->gdata.size; i++)
node_drop_vecs(&ir->gdata.data[i]);
vec_free(ir->gdata);
}
spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir) {
@@ -300,6 +304,16 @@ static void dump_node(const spl_type_t *ty, const spl_ir_node_t *n) {
dump_ref(n->mem_offset.offset);
printf(")");
break;
case SPL_IR_MEM_FIELD_PTR:
printf("@mem.field_ptr(");
ir_type_dump(ty, n->mem_field_ptr.tid);
printf(", %zu)(", (size_t)n->mem_field_ptr.field_idx);
dump_ref(n->mem_field_ptr.agg);
printf(")");
break;
case SPL_IR_MEM_GLOBAL_ALLOC:
printf("@mem.global_alloc(gdata[%zu])()", (size_t)n->mem_global_alloc.const_node);
break;
case SPL_IR_MEM_COPY:
printf("@mem.copy()(");
dump_ref(n->mem_copy.dst);
@@ -481,4 +495,12 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) {
printf("; SPL IR module (%zu funcs)\n", ir->funcs.size - 1);
for (usize i = 1; i < ir->funcs.size; i++)
dump_func(ty, &ir->funcs.data[i]);
if (ir->gdata.size) {
printf("; global data (%zu)\n", ir->gdata.size);
for (usize i = 0; i < ir->gdata.size; i++) {
printf("; gdata[%zu] = ", i);
dump_node(ty, &ir->gdata.data[i]);
printf("\n");
}
}
}

View File

@@ -37,9 +37,11 @@
X(case.int2float, V0, SPL_IR_CASE_INT2FLOAT) \
X(case.float2int, V0, SPL_IR_CASE_FLOAT2INT) \
X(mem.alloca, V0, SPL_IR_MEM_ALLOCA) \
X(mem.global_alloc, V0, SPL_IR_MEM_GLOBAL_ALLOC) \
X(mem.load, V0, SPL_IR_MEM_LOAD) \
X(mem.store, V0, SPL_IR_MEM_STORE) \
X(mem.offset, V0, SPL_IR_MEM_OFFSET) \
X(mem.field, V0, SPL_IR_MEM_FIELD_PTR) \
X(mem.copy, V0, SPL_IR_MEM_COPY) \
X(mem.set, V0, SPL_IR_MEM_SET) \
X(mem.fence, V0, SPL_IR_MEM_FENCE) \
@@ -109,6 +111,10 @@ typedef struct {
spl_type_id_t tid;
spl_ir_node_ref_t count;
} mem_alloc;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t const_node;
} mem_global_alloc;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t ptr;
@@ -123,6 +129,11 @@ typedef struct {
spl_ir_node_ref_t ptr;
spl_ir_node_ref_t offset;
} mem_offset;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t agg;
usize field_idx;
} mem_field_ptr;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t dst;
@@ -171,12 +182,13 @@ typedef struct {
} agg_construct;
struct {
spl_type_id_t tid;
isize field_idx;
spl_type_id_t field_tid;
usize field_idx;
spl_ir_node_ref_t val;
} agg_extract;
struct {
spl_type_id_t tid;
isize field_idx;
usize field_idx;
spl_ir_node_ref_t agg;
spl_ir_node_ref_t field;
} agg_insert;
@@ -233,8 +245,10 @@ typedef struct {
} spl_ir_func_t;
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;
typedef struct {
spl_ir_func_vec_t funcs;
spl_ir_node_vec_t gdata;
} spl_ir_t;
void spl_ir_init(spl_ir_t *ir);

1393
stage1/spl_ir2vm.c Normal file

File diff suppressed because it is too large Load Diff

93
stage1/spl_ir2vm.h Normal file
View File

@@ -0,0 +1,93 @@
#ifndef __SPL_IR2VM_H__
#define __SPL_IR2VM_H__
#include "spl_ir.h"
#include "spl_type.h"
/*
* ================================================================
* SPL VM ABI (ir2vm 的正式约定;布局知识唯一来源)
* ================================================================
*
* 栈值槽 spl_val_t = sizeof(usize) = 8 字节。
* SIR 指令 type 只表达标量 tagSPL_I8..SPL_PTR聚合无 tag——
* 聚合值在 vreg 中是字节块,整体搬运用 NCALL vm_memcpy。
*
* ── 函数栈帧(字节坐标系,基址 = (char*)&stacks[fp])─────────────
*
* [canary] fp-8 .. 0 VM CALL 自动插入ir2vm 不触碰)
* [params 区] fp+0 .. fp+Na Na = C ABI 参数区字节数)
* [locals / vreg] fp+Na .. fp+Na+L
*
* ALLOC ceil((Na+L)/8) 一条 prologueepilogue 走 RET。
* LADDR(imm) 的 imm 是字节偏移canary 在 fp-1 槽,编译码不可见。
*
* ── 参数区 = C ABI聚合值按值 ─────────────────────────────────
* 标量参数align_up(off,8) 后占 8 字节(一槽)。
* 聚合参数:按聚合 size 排布跨多槽align8 + size
* 调用方:标量 ld/PUSH 一槽;聚合逐 8 字节块压栈(聚合 vreg 强制 8 对齐)。
* 被调方:标量参数映射参数槽;聚合参数在 prologue memcpy 参数区 → param vreg
* emit_value(param) 取 vreg 地址。参数槽数 = ceil(param_bytes/8) = CALL nargs。
*
* ── locals = 虚拟寄存器区 ────────────────────────────────────────
* 每个产生值的 IR 节点 = 一个 vreglocals 区按类型对齐的字节块)。
* 纯值节点type.const / mem.global_alloc / mem.alloca / 折叠 sizeof 等)不落 vreg
* 引用处重算PUSH / GADDR / LADDR其余产生值节点落 vreg引用处 LOAD。
* 聚合 vreg 引用处返回其地址LADDR搬运经 vm_memcpy。
* mem.alloca(tid)(cnt) 的 vreg 槽即缓冲区本体,节点值 = LADDR(vreg_off)。
* 所有运算走 load/storeld A; ld B; op; st Dst立即数直接 PUSH。
*
* ── 调用 ──────────────────────────────────────────────────────────
* 调用方:逐参数压栈(标量一槽;聚合按 C ABI 逐 8 字节块)→ push fn_addr(或
* native_idx) → CALL n / NCALL n。返回值落 call 节点 vreg。
* 原生函数IR 中 nodes 为空的函数(@extern 声明)→ 注册进 prog.natives
* 加载时由 spl_syscall_register 填 impl调用改 PUSH nat_idx + NCALL。
* 变参 nargs = 实际参数槽数。
*
* ── enum不展开直接保留─────────────────────────────────────
* IR 层保留 enum 类型(不再展开为 struct。enum 布局 = tag(usize, offset 0)
* + payload(offset 8最大变体。构造agg.construct(enum)(tag, payload)
* match先取 tag 判定变体,再 extract(enum, 1) 一跳取 payload
* field_tid = 变体具体类型(由 ast2ir 传入)。
*
* ── 返回 ──────────────────────────────────────────────────────────
* 标量ld vreg(val); RET(tag)RET 的 type 决定 VM 是否弹出返回值)。
* 聚合返回 = sret自展开不改 VM
* 被调函数签名尾部追加隐藏 *T 参数(最后一个);返回时把聚合 vreg
* memcpy 到 sret 地址RET(void)。
* 调用方在 locals 预留聚合槽(= call 节点 vreg压其地址为最后实参
* call 完成后聚合值已在该槽。
* 返回 voidRET(SPL_VOID)。
*
* ── 全局数据 ──────────────────────────────────────────────────────
* 任何聚合类型下(含 $root 顶层)的 var/const 属全局数据区。gdata 是
* spl_ir_node_vec_t每条 = 一个 value 节点type.const标量折叠值
* 聚合/无 init 零。ir2vm 遍历求值 → SIR gdata 条目(字节 blob
* mem.global_alloc(tid, const_node) 的 const_node = gdata 向量索引,
* 降级为 GADDR(idx)。符号(def) → gdata 索引的解析在 ast2ir 收集期
* gdata_ref 表ir2vm 按索引直接用。
*
* ── 类型布局C ABI唯一实现处────────────────────────────────
* type_align / type_size / field_offset标量按 bits/8 对齐;
* struct 顺序对齐 + 尾填充union 取最大字段enum = tag(8) + 最大 payload
* slice/range = [ptr, len] 各 8 字节array = len * elem。
*
* ── 分支 ──────────────────────────────────────────────────────────
* control.br/jmp/select 的 label 是 IR node ref基本块首指令。两遍发射
* 第一遍逐节点发指令并记录 label 节点 → 指令地址;第二遍回填
* JMP/BZ/BNZ 相对偏移 imm = target_addr - (jmp_addr + 1)。
* ================================================================
*/
typedef struct {
const spl_ir_t *ir;
const spl_type_t *type;
} spl_ir2vm_t;
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type);
void spl_ir2vm_drop(spl_ir2vm_t *ctx);
int spl_ir2vm_run(spl_ir2vm_t *ctx, const char *outpath); /* 返回错误数 */
void spl_ir2vm_dump(spl_ir2vm_t *ctx);
#endif /* __SPL_IR2VM_H__ */

View File

@@ -12,6 +12,7 @@
#include "spl_ast.h"
#include "spl_ast2ir.h"
#include "spl_ir2vm.h"
#include "spl_lexer.h"
#include "spl_sema.h"
#include "spl_tok.h"
@@ -62,6 +63,11 @@ static void dump_ast(const char *src, const char *fname) {
spl_ast_t ast;
spl_ast_init(&ast, &toks);
spl_ast_prase(&ast);
if (ast.parsed < 0) {
printf("parse failed, skip AST dump\n");
spl_ast_drop(&ast);
return;
}
spl_ast_valid(&ast);
spl_ast_dump(&ast, ast.root);
spl_ast_drop(&ast);
@@ -72,6 +78,11 @@ static void dump_sema(const char *src, const char *fname) {
spl_ast_t ast;
spl_ast_init(&ast, &toks);
spl_ast_prase(&ast);
if (ast.parsed < 0) {
printf("parse failed, skip sema dump\n");
spl_ast_drop(&ast);
return;
}
spl_ast_valid(&ast);
spl_sema_t sema;
spl_sema_init(&sema);
@@ -108,6 +119,11 @@ static void dump_ir(const char *src, const char *fname) {
spl_ast_t ast;
spl_ast_init(&ast, &toks);
spl_ast_prase(&ast);
if (ast.parsed < 0) {
printf("parse failed, skip IR\n");
spl_ast_drop(&ast);
return;
}
spl_ast_valid(&ast);
spl_sema_t sema;
spl_sema_init(&sema);
@@ -152,6 +168,48 @@ static int cmd_dump(const char *flags, const char *path) {
return 0;
}
static int compile_spl(const char *src, const char *fname, const char *outpath) {
spl_tok_vec_t toks = spl_lex(src, fname);
spl_ast_t ast;
spl_ast_init(&ast, &toks);
spl_ast_prase(&ast);
if (ast.parsed < 0) {
printf("parse failed, no output\n");
spl_ast_drop(&ast);
return 1;
}
spl_ast_valid(&ast);
spl_sema_t sema;
spl_sema_init(&sema);
sema.ast = &ast;
spl_sema_run(&sema);
spl_sema_check(&sema);
if (sema.error_count) {
printf("sema errors=%d, no output\n", sema.error_count);
spl_sema_drop(&sema);
spl_ast_drop(&ast);
return 1;
}
spl_ast2ir_t a2ir;
spl_ast2ir_init(&a2ir, &sema);
spl_ast2ir_run(&a2ir);
if (a2ir.err_count) {
printf("ast2ir errors=%d, no output\n", a2ir.err_count);
spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema);
spl_ast_drop(&ast);
return 1;
}
spl_ir2vm_t ir2vm;
spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type);
int rc = spl_ir2vm_run(&ir2vm, outpath);
spl_ir2vm_drop(&ir2vm);
spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema);
spl_ast_drop(&ast);
return rc ? 1 : 0;
}
int main(int argc, char **argv) {
if (argc < 2) {
LOG_FATAL("Usage: splc0 [--dump <flags>] <in> [out]\n");
@@ -174,6 +232,16 @@ int main(int argc, char **argv) {
}
return cmd_dump(argv[argi + 1], argv[argi + 2]);
}
LOG_FATAL("splc0: compile todo\n");
return 1;
/* splc0 <in> <out> */
if (argc < argi + 2) {
LOG_FATAL("Usage: splc0 <in> <out> or splc0 --dump <flags> <file>\n");
return 1;
}
long len;
char *src = read_file(argv[argi], &len);
if (!src)
return 1;
int rc = compile_spl(src, argv[argi], argv[argi + 1]);
free(src);
return rc;
}