stage1 实现并修复ast2ir的核心功能的正确性

This commit is contained in:
zzy committed 2026-09-12 09:46:56 +08:00
1 parent 49ccdec3dd
commit 87d9b7ea34
7 files changed
+1408 -110

No files matched your search

+1 -1
View File
@@ -91,7 +91,7 @@ static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const
spl_ast_node_t n = {0};
n.kind = kind;
n.resolved_def_id = 0;
n.resolved_type_id = 0;
n.resolved_lang_tid = 0;
if (tok) {
n.dbg.dbg_name = spl_ast_kind_name(kind);
n.dbg.fname = tok->fname;
+3 -1
View File
@@ -150,8 +150,10 @@ typedef VEC(spl_ast_node_ref_t) spl_ast_node_ref_vec_t;
struct spl_ast_node {
spl_ast_node_kind_t kind;
spl_dbg_node_t dbg;
usize resolved_def_id;
usize resolved_type_id;
usize resolved_lang_tid;
usize expected_lang_tid;
union {
/* SPL_AST_ROOT */
+96 -17
View File
@@ -8,11 +8,8 @@ static spl_type_id_t to_ir_type(spl_ast2ir_t *a, spl_lang_type_id_t lang) {
}
static spl_lang_type_id_t node_lang(spl_ast2ir_t *a, spl_ast_node_t *n) {
if (!n)
return 0;
if (n->kind == SPL_AST_EXPR_IDENT)
return spl_def_get_lang_id(a->sema->type, n->resolved_def_id);
return n->resolved_type_id;
(void)a;
return n ? n->resolved_lang_tid : 0;
}
static spl_type_id_t node_ir(spl_ast2ir_t *a, spl_ast_node_t *n) {
@@ -30,27 +27,48 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n);
static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n);
static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in);
static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n);
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref);
static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_type_id_t ft, spl_type_id_t tt,
spl_ir_node_ref_t v);
static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in,
spl_ast_node_ref_vec_t *args);
static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in);
static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n);
static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in) {
static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in,
spl_ast_node_ref_vec_t *args) {
switch (in) {
case SPL_INTRIN_SIZEOF: {
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(n->call.args, 0));
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(*args, 0));
return spl_ir_builder_type_sizeof(a->ir, node_ir(a, arg));
}
case SPL_INTRIN_ALIGNOF: {
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(n->call.args, 0));
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(*args, 0));
return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg));
}
case SPL_INTRIN_ASSERT: {
/* 目前 SEMA 只做类型检查,emit 阶段留空,
@assert 展开需待 control.trap 语义明确后再实现 */
spl_ir_node_ref_t cond = emit_expr(a, vec_at(*args, 0));
if (!cond)
return 0;
spl_lang_type_id_t b = spl_lang_make_bool(a->sema->type);
spl_ir_node_ref_t notc = spl_ir_builder_arith_not(a->ir, to_ir_type(a, b), cond);
spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, notc);
spl_ir_builder_block_end(a->ir);
usize trap_blk = spl_ir_builder_block_begin(a->ir);
spl_ir_builder_control_trap(a->ir);
spl_ir_builder_block_end(a->ir);
usize cont_blk = spl_ir_builder_block_begin(a->ir);
spl_ir_builder_control_br_fixup(a->ir, br, trap_blk, cont_blk);
return 0;
}
case SPL_INTRIN_BREAKPOINT:
return spl_ir_builder_dbg_breakpoint(a->ir);
default:
UNREACHABLE();
}
@@ -198,7 +216,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
}
static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n) {
spl_ir_node_ref_t v = emit_expr(a, n->cast.expr);
spl_ir_node_ref_t v = emit_expr_raw(a, n->cast.expr);
if (!v)
return 0;
spl_ast_node_t *src = spl_ast_node(a->sema->ast, n->cast.expr);
@@ -238,6 +256,28 @@ static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n) {
}
static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ir_node_ref_t val = emit_expr_raw(a, ref);
if (!val)
return 0;
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
if (!n || n->expected_lang_tid == 0)
return val;
spl_lang_type_id_t from = n->resolved_lang_tid;
spl_lang_type_id_t to = n->expected_lang_tid;
if (!from || from == to)
return val;
spl_type_id_t from_ir = to_ir_type(a, from);
spl_type_id_t to_ir = to_ir_type(a, to);
if (!from_ir || !to_ir || from_ir == to_ir)
return val;
return emit_implicit_cast(a, from_ir, to_ir, val);
}
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
if (!n)
return 0;
@@ -396,7 +436,7 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
if (callee && callee->kind == SPL_AST_EXPR_IDENT) {
spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name);
if (in != SPL_INTRIN_NONE)
return ast2ir_intrin_call(a, n, in);
return ast2ir_intrin_call(a, n, in, &n->call.args);
}
spl_ir_node_ref_t fn = emit_expr(a, n->call.callee);
@@ -573,9 +613,12 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ir_builder_agg_construct_field(a->ir, node, len);
return node;
}
case SPL_AST_EXPR_COMPTIME_CALL:
// TODO
return 0;
case SPL_AST_EXPR_COMPTIME_CALL: {
spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name);
if (in == SPL_INTRIN_NONE)
return 0;
return ast2ir_intrin_call(a, n, in, &n->comptime_call.args);
}
default:
TODO();
return 0;
@@ -959,6 +1002,42 @@ static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
}
}
static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_type_id_t ft, spl_type_id_t tt,
spl_ir_node_ref_t v) {
if (!ft || !tt || ft == tt)
return v;
spl_type_node_t *fs = spl_type_node(a->sema->type, ft);
spl_type_node_t *ts = spl_type_node(a->sema->type, tt);
if (!fs || !ts)
return v;
if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_INT) {
if (fs->int_type.bits == ts->int_type.bits)
return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v);
if (fs->int_type.bits > ts->int_type.bits)
return spl_ir_builder_cast_trunc(a->ir, ft, tt, v);
if (fs->int_type.is_signed)
return spl_ir_builder_cast_sext(a->ir, ft, tt, v);
return spl_ir_builder_cast_zext(a->ir, ft, tt, v);
}
if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_FLOAT)
return spl_ir_builder_case_int2float(a->ir, ft, tt, v);
if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_INT)
return spl_ir_builder_case_float2int(a->ir, ft, tt, v);
if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_FLOAT) {
if (fs->float_type.bits > ts->float_type.bits)
return spl_ir_builder_cast_ftrunc(a->ir, ft, tt, v);
return spl_ir_builder_cast_fext(a->ir, ft, tt, v);
}
if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT)
return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v);
if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_INT)
return spl_ir_builder_cast_ptr2int(a->ir, ft, tt, v);
if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_PTR)
return spl_ir_builder_cast_int2ptr(a->ir, ft, tt, v);
return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v);
}
static usize spl_int_map_hash(usize k) { return MAP_HASH_INT(k); }
static int spl_int_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
+2
View File
@@ -8,6 +8,8 @@ static const spl_intrin_info_t g_intrin_table[] = {
SPL_INTRIN_RESULT_USIZE},
[SPL_INTRIN_ASSERT] = {"@assert", SPL_INTRIN_ASSERT, SPL_INTRIN_FORM_CALL, 1, 2,
SPL_INTRIN_RESULT_UNIT},
[SPL_INTRIN_BREAKPOINT] = {"@breakpoint", SPL_INTRIN_BREAKPOINT, SPL_INTRIN_FORM_CALL, 0, 0,
SPL_INTRIN_RESULT_UNIT},
[SPL_INTRIN_LEN] = {"len", SPL_INTRIN_LEN, SPL_INTRIN_FORM_FIELD, 0, 0,
SPL_INTRIN_RESULT_USIZE},
};
+1
View File
@@ -9,6 +9,7 @@ typedef enum {
SPL_INTRIN_SIZEOF,
SPL_INTRIN_ALIGNOF,
SPL_INTRIN_ASSERT,
SPL_INTRIN_BREAKPOINT,
SPL_INTRIN_LEN,
} spl_intrin_t;
+15 -5
View File
@@ -315,12 +315,16 @@ static spl_ir_node_ref_t builder_alloc_node(spl_ir_builder_t *b, spl_ir_kind_t k
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
n->kind = kind;
n->dbg = b->dbg;
if (b->current_block < vec_size(b->blocks)) {
vec_at(b->blocks, b->current_block) = ref;
} else {
if (b->current_block >= vec_size(b->blocks)) {
Panic("unknown bblock");
return 0;
}
spl_ir_node_ref_t *slot = &vec_at(b->blocks, b->current_block);
if (*slot == 0)
*slot = ref;
return ref;
}
@@ -378,7 +382,7 @@ void spl_ir_builder_fn_end(spl_ir_builder_t *b) {
target = vec_at(b->blocks, fx->block);
}
if (target == 0) {
Panic("unknown reloc target bblock");
Panic("reloc to empty/unknown bblock #%zu", fx->block);
}
switch (fx->slot) {
case SPL_IR_FIX_BR_TRUE:
@@ -411,6 +415,10 @@ void spl_ir_builder_block_end(spl_ir_builder_t *b) {
if (!b->terminated) {
Panic("bblock must be end of terminated");
}
if (b->current_block != 0 && b->current_block < vec_size(b->blocks) &&
vec_at(b->blocks, b->current_block) == 0) {
Panic("bblock #%zu is empty (no entry node emitted)", b->current_block);
}
}
#define X(name, kind) \
@@ -769,7 +777,9 @@ spl_ir_node_ref_t spl_ir_builder_control_ret(spl_ir_builder_t *b, spl_type_id_t
}
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 ref = builder_alloc_node(b, SPL_IR_CONTROL_UNREACHABLE);
b->terminated = true;
return ref;
}
spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b) {
+1290 -86
View File
File diff suppressed because it is too large. Load diff