stage1 实现并修复ast2ir的核心功能的正确性
This commit is contained in:
1 parent
49ccdec3dd
commit
87d9b7ea34
7 files changed
+1406
-108
No files matched your search
+1
-1
@@ -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};
|
spl_ast_node_t n = {0};
|
||||||
n.kind = kind;
|
n.kind = kind;
|
||||||
n.resolved_def_id = 0;
|
n.resolved_def_id = 0;
|
||||||
n.resolved_type_id = 0;
|
n.resolved_lang_tid = 0;
|
||||||
if (tok) {
|
if (tok) {
|
||||||
n.dbg.dbg_name = spl_ast_kind_name(kind);
|
n.dbg.dbg_name = spl_ast_kind_name(kind);
|
||||||
n.dbg.fname = tok->fname;
|
n.dbg.fname = tok->fname;
|
||||||
|
|||||||
+3
-1
@@ -150,8 +150,10 @@ typedef VEC(spl_ast_node_ref_t) spl_ast_node_ref_vec_t;
|
|||||||
struct spl_ast_node {
|
struct spl_ast_node {
|
||||||
spl_ast_node_kind_t kind;
|
spl_ast_node_kind_t kind;
|
||||||
spl_dbg_node_t dbg;
|
spl_dbg_node_t dbg;
|
||||||
|
|
||||||
usize resolved_def_id;
|
usize resolved_def_id;
|
||||||
usize resolved_type_id;
|
usize resolved_lang_tid;
|
||||||
|
usize expected_lang_tid;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
/* SPL_AST_ROOT */
|
/* SPL_AST_ROOT */
|
||||||
|
|||||||
+95
-16
@@ -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) {
|
static spl_lang_type_id_t node_lang(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||||
if (!n)
|
(void)a;
|
||||||
return 0;
|
return n ? n->resolved_lang_tid : 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static spl_type_id_t node_ir(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
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_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_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 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_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_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) {
|
switch (in) {
|
||||||
case SPL_INTRIN_SIZEOF: {
|
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));
|
return spl_ir_builder_type_sizeof(a->ir, node_ir(a, arg));
|
||||||
}
|
}
|
||||||
case SPL_INTRIN_ALIGNOF: {
|
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));
|
return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg));
|
||||||
}
|
}
|
||||||
case SPL_INTRIN_ASSERT: {
|
case SPL_INTRIN_ASSERT: {
|
||||||
/* 目前 SEMA 只做类型检查,emit 阶段留空,
|
spl_ir_node_ref_t cond = emit_expr(a, vec_at(*args, 0));
|
||||||
@assert 展开需待 control.trap 语义明确后再实现 */
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case SPL_INTRIN_BREAKPOINT:
|
||||||
|
return spl_ir_builder_dbg_breakpoint(a->ir);
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
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) {
|
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)
|
if (!v)
|
||||||
return 0;
|
return 0;
|
||||||
spl_ast_node_t *src = spl_ast_node(a->sema->ast, n->cast.expr);
|
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) {
|
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);
|
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
|
||||||
if (!n)
|
if (!n)
|
||||||
return 0;
|
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) {
|
if (callee && callee->kind == SPL_AST_EXPR_IDENT) {
|
||||||
spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name);
|
spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name);
|
||||||
if (in != SPL_INTRIN_NONE)
|
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);
|
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);
|
spl_ir_builder_agg_construct_field(a->ir, node, len);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
case SPL_AST_EXPR_COMPTIME_CALL:
|
case SPL_AST_EXPR_COMPTIME_CALL: {
|
||||||
// TODO
|
spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name);
|
||||||
|
if (in == SPL_INTRIN_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
|
return ast2ir_intrin_call(a, n, in, &n->comptime_call.args);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
TODO();
|
TODO();
|
||||||
return 0;
|
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 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); }
|
static int spl_int_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ static const spl_intrin_info_t g_intrin_table[] = {
|
|||||||
SPL_INTRIN_RESULT_USIZE},
|
SPL_INTRIN_RESULT_USIZE},
|
||||||
[SPL_INTRIN_ASSERT] = {"@assert", SPL_INTRIN_ASSERT, SPL_INTRIN_FORM_CALL, 1, 2,
|
[SPL_INTRIN_ASSERT] = {"@assert", SPL_INTRIN_ASSERT, SPL_INTRIN_FORM_CALL, 1, 2,
|
||||||
SPL_INTRIN_RESULT_UNIT},
|
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_LEN] = {"len", SPL_INTRIN_LEN, SPL_INTRIN_FORM_FIELD, 0, 0,
|
||||||
SPL_INTRIN_RESULT_USIZE},
|
SPL_INTRIN_RESULT_USIZE},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ typedef enum {
|
|||||||
SPL_INTRIN_SIZEOF,
|
SPL_INTRIN_SIZEOF,
|
||||||
SPL_INTRIN_ALIGNOF,
|
SPL_INTRIN_ALIGNOF,
|
||||||
SPL_INTRIN_ASSERT,
|
SPL_INTRIN_ASSERT,
|
||||||
|
SPL_INTRIN_BREAKPOINT,
|
||||||
SPL_INTRIN_LEN,
|
SPL_INTRIN_LEN,
|
||||||
} spl_intrin_t;
|
} spl_intrin_t;
|
||||||
|
|
||||||
|
|||||||
+15
-5
@@ -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);
|
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||||
n->kind = kind;
|
n->kind = kind;
|
||||||
n->dbg = b->dbg;
|
n->dbg = b->dbg;
|
||||||
if (b->current_block < vec_size(b->blocks)) {
|
|
||||||
vec_at(b->blocks, b->current_block) = ref;
|
if (b->current_block >= vec_size(b->blocks)) {
|
||||||
} else {
|
|
||||||
Panic("unknown bblock");
|
Panic("unknown bblock");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spl_ir_node_ref_t *slot = &vec_at(b->blocks, b->current_block);
|
||||||
|
if (*slot == 0)
|
||||||
|
*slot = ref;
|
||||||
|
|
||||||
return 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);
|
target = vec_at(b->blocks, fx->block);
|
||||||
}
|
}
|
||||||
if (target == 0) {
|
if (target == 0) {
|
||||||
Panic("unknown reloc target bblock");
|
Panic("reloc to empty/unknown bblock #%zu", fx->block);
|
||||||
}
|
}
|
||||||
switch (fx->slot) {
|
switch (fx->slot) {
|
||||||
case SPL_IR_FIX_BR_TRUE:
|
case SPL_IR_FIX_BR_TRUE:
|
||||||
@@ -411,6 +415,10 @@ void spl_ir_builder_block_end(spl_ir_builder_t *b) {
|
|||||||
if (!b->terminated) {
|
if (!b->terminated) {
|
||||||
Panic("bblock must be end of 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) \
|
#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) {
|
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) {
|
spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b) {
|
||||||
|
|||||||
+1289
-85
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user