stage1 修复设计问题 实现ast2ir

This commit is contained in:
zzy
2026-08-05 08:14:23 +08:00
parent 8ac59dfaa1
commit 2ccee5f1cf
14 changed files with 3694 additions and 91 deletions

View File

@@ -1 +1,484 @@
/* spl_ir.c — function-based SIR IR (arena 容器 + 文本 dump) */
#include "spl_ir.h"
#include <stdio.h>
#include <string.h>
/* ---- 内置函数名字表(与 spl_ir_kind_t 枚举一一对应) ---- */
static const char *const ir_kind_names[] = {
#define X(a, b, c) #a,
SPL_IR_FN_TABLE
#undef X
};
void spl_ir_init(spl_ir_t *ir) {
memset(ir, 0, sizeof *ir);
vec_init(ir->funcs);
/* func ref 0 保留为 error占位 */
spl_ir_func_t f0;
memset(&f0, 0, sizeof f0);
vec_push(ir->funcs, f0);
}
static void node_drop_vecs(spl_ir_node_t *n) {
if (!n)
return;
switch (n->kind) {
case SPL_IR_AGG_CONSTRUCT:
vec_free(n->agg_construct.fields);
break;
case SPL_IR_CONTROL_CALL:
vec_free(n->control_call.params);
break;
default:
break;
}
}
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_free(f->nodes);
vec_free(f->labels);
}
vec_free(ir->funcs);
}
spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir) {
spl_ir_func_t f;
memset(&f, 0, sizeof f);
vec_init(f.nodes);
vec_init(f.labels);
vec_push(ir->funcs, f);
return ir->funcs.size - 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)
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 */
}
vec_push(f->nodes, n);
return f->nodes.size - 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)
return NULL;
spl_ir_func_t *f = &ir->funcs.data[fn_id];
if (!node_id || node_id >= f->nodes.size)
return NULL;
return &f->nodes.data[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)
return NULL;
return &ir->funcs.data[fn_id];
}
/* ================================================================
* dump
* ================================================================ */
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;
}
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:
case SPL_IR_ARITH_DIV:
case SPL_IR_ARITH_REM:
case SPL_IR_ARITH_AND:
case SPL_IR_ARITH_OR:
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(")");
break;
case SPL_IR_CMP_EQ:
case SPL_IR_CMP_NE:
case SPL_IR_CMP_LT:
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(")");
break;
case SPL_IR_CAST_TRUNC:
case SPL_IR_CAST_ZEXT:
case SPL_IR_CAST_SEXT:
case SPL_IR_CAST_FEXT:
case SPL_IR_CAST_FTRUNC:
case SPL_IR_CAST_BITCAST:
case SPL_IR_CAST_PTR2INT:
case SPL_IR_CAST_INT2PTR:
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(")");
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_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(")");
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(")");
break;
case SPL_IR_MEM_FENCE:
printf("@mem.fence()(");
dump_ref(n->mem_fence.ordering);
printf(")");
break;
case SPL_IR_TYPE_BITSIZEOF:
printf("@type.bitsizeof(");
ir_type_dump(ty, n->bitsizeof.tid);
printf(")()");
break;
case SPL_IR_TYPE_SIZEOF:
printf("@type.sizeof(");
ir_type_dump(ty, n->ir_sizeof.tid);
printf(")()");
break;
case SPL_IR_TYPE_ALIGNOF:
printf("@type.alignof(");
ir_type_dump(ty, n->ir_alignof.tid);
printf(")()");
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(")");
break;
case SPL_IR_TYPE_FIELD_COUNT:
printf("@type.field_count(");
ir_type_dump(ty, n->field_count.tid);
printf(")()");
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(")");
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(")");
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(")");
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(")");
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(")");
break;
case SPL_IR_CONTROL_JMP:
printf("@control.jmp()(");
dump_ref(n->control_jmp.label);
printf(")");
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(")");
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);
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(")");
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]);
}