stage1 修复设计问题 实现ast2ir
This commit is contained in:
483
stage1/spl_ir.c
483
stage1/spl_ir.c
@@ -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]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user