stage1 实现部分ast2ir内容
This commit is contained in:
1 parent
f1d86b6e34
commit
3d57260f3f
6 files changed
+298
-148
No files matched your search
+151
-82
@@ -14,8 +14,8 @@ const char *spl_ir_kind_name(spl_ir_kind_t kind) {
|
||||
void spl_ir_init(spl_ir_t *ir) {
|
||||
vec_init(ir->funcs);
|
||||
vec_push(ir->funcs, (spl_ir_func_t){0});
|
||||
vec_init(ir->gdata);
|
||||
vec_push(ir->gdata, (spl_ir_node_t){0});
|
||||
// vec_init(ir->gdata);
|
||||
// vec_push(ir->gdata, (spl_ir_node_t){0});
|
||||
}
|
||||
|
||||
static void node_drop_vecs(spl_ir_node_t *n) {
|
||||
@@ -38,43 +38,52 @@ void spl_ir_drop(spl_ir_t *ir) {
|
||||
spl_ir_func_t *f = &vec_at(ir->funcs, i);
|
||||
vec_for(f->nodes, j) { node_drop_vecs(&vec_at(f->nodes, j)); }
|
||||
vec_free(f->nodes);
|
||||
vec_free(f->labels);
|
||||
}
|
||||
vec_free(ir->funcs);
|
||||
vec_for(ir->gdata, i) { node_drop_vecs(&vec_at(ir->gdata, i)); }
|
||||
vec_free(ir->gdata);
|
||||
// vec_for(ir->gdata, i) { node_drop_vecs(&vec_at(ir->gdata, i)); }
|
||||
// vec_free(ir->gdata);
|
||||
}
|
||||
|
||||
// 申请空的 ir_func 返回 id
|
||||
spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir) {
|
||||
if (ir == NULL) {
|
||||
return 0;
|
||||
}
|
||||
spl_ir_func_t f = {0};
|
||||
vec_init(f.nodes);
|
||||
vec_init(f.labels);
|
||||
vec_push(f.nodes, (spl_ir_node_t){0}); /* 0 = error 哨兵 */
|
||||
vec_push(f.nodes, (spl_ir_node_t){0});
|
||||
vec_push(ir->funcs, f);
|
||||
return vec_size(ir->funcs) - 1;
|
||||
}
|
||||
|
||||
// 从 fn_id 申请空的 ir_node 返回 id
|
||||
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 >= vec_size(ir->funcs))
|
||||
if (!fn_id || fn_id >= vec_size(ir->funcs)) {
|
||||
return 0;
|
||||
}
|
||||
spl_ir_func_t *f = &vec_at(ir->funcs, fn_id);
|
||||
spl_ir_node_t n = {0};
|
||||
vec_push(f->nodes, n);
|
||||
return vec_size(f->nodes) - 1;
|
||||
}
|
||||
|
||||
// 从 fn_id 里通过 node_id 获取 ir_node
|
||||
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 >= vec_size(ir->funcs))
|
||||
if (!fn_id || fn_id >= vec_size(ir->funcs)) {
|
||||
return NULL;
|
||||
}
|
||||
spl_ir_func_t *f = &vec_at(ir->funcs, fn_id);
|
||||
if (!node_id || node_id >= vec_size(f->nodes))
|
||||
if (!node_id || node_id >= vec_size(f->nodes)) {
|
||||
return NULL;
|
||||
}
|
||||
return &vec_at(f->nodes, node_id);
|
||||
}
|
||||
|
||||
// 从 fn_id 获取 ir_func
|
||||
spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id) {
|
||||
if (!fn_id || fn_id >= vec_size(ir->funcs))
|
||||
if (!fn_id || fn_id >= vec_size(ir->funcs)) {
|
||||
return NULL;
|
||||
}
|
||||
return &vec_at(ir->funcs, fn_id);
|
||||
}
|
||||
|
||||
@@ -279,102 +288,126 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) {
|
||||
if (vec_size(func->nodes) == 0)
|
||||
printf(" (extern)\n");
|
||||
}
|
||||
if (vec_size(ir->gdata) > 1) {
|
||||
printf("gdata:\n");
|
||||
vec_for(ir->gdata, i) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
spl_ir_node_t *node = &vec_at(ir->gdata, i);
|
||||
printf(" #%zu ", i);
|
||||
printf("%s", spl_ir_kind_name(node->kind));
|
||||
ir_dump_node(ty, node);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
// if (vec_size(ir->gdata) > 1) {
|
||||
// printf("gdata:\n");
|
||||
// vec_for(ir->gdata, i) {
|
||||
// if (i == 0)
|
||||
// continue;
|
||||
// spl_ir_node_t *node = &vec_at(ir->gdata, i);
|
||||
// printf(" #%zu ", i);
|
||||
// printf("%s", spl_ir_kind_name(node->kind));
|
||||
// ir_dump_node(ty, node);
|
||||
// printf("\n");
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// IR Builder
|
||||
|
||||
// 从当前 fn 申请新的 node 并注入到当前基本块
|
||||
static spl_ir_node_ref_t builder_alloc_node(spl_ir_builder_t *b, spl_ir_kind_t kind) {
|
||||
Assert(!b->terminated && "emit into a terminated block");
|
||||
spl_ir_node_ref_t ref = spl_ir_alloc_node(&b->ir, b->current_fn);
|
||||
Assert(ref != 0);
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
n->kind = kind;
|
||||
n->dbg = b->dbg;
|
||||
b->current_node = ref;
|
||||
if (b->current_block < vec_size(b->blocks)) {
|
||||
vec_at(b->blocks, b->current_block) = ref;
|
||||
} else {
|
||||
Panic("unknown bblock");
|
||||
return 0;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
static spl_ir_func_t *builder_cur_func(spl_ir_builder_t *b) {
|
||||
return spl_ir_func(&b->ir, b->current_fn);
|
||||
}
|
||||
|
||||
static void builder_reloc_add(spl_ir_builder_t *b, spl_ir_node_ref_t label) {
|
||||
if (label == 0) {
|
||||
LOG_WARN("reloc null lable");
|
||||
return;
|
||||
}
|
||||
spl_ir_func_t *f = builder_cur_func(b);
|
||||
if (f && label < vec_size(f->nodes)) {
|
||||
// resolved
|
||||
return;
|
||||
}
|
||||
vec_for(b->reloc_label, i) {
|
||||
if (vec_at(b->reloc_label, i) == label) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
vec_push(b->reloc_label, label);
|
||||
}
|
||||
|
||||
static void builder_reloc_check(spl_ir_builder_t *b) {
|
||||
spl_ir_func_t *f = builder_cur_func(b);
|
||||
if (!f)
|
||||
return;
|
||||
vec_for(b->reloc_label, i) {
|
||||
spl_ir_node_ref_t label = vec_at(b->reloc_label, i);
|
||||
if (label >= vec_size(f->nodes)) {
|
||||
LOG_ERROR("fn `%s`: forward label %%%zu unresolved", f->name ? f->name : "?", label);
|
||||
}
|
||||
}
|
||||
b->reloc_label.size = 0;
|
||||
}
|
||||
|
||||
void spl_ir_builder_init(spl_ir_builder_t *b) {
|
||||
spl_ir_init(&b->ir);
|
||||
b->current_fn = 0;
|
||||
b->current_node = 0;
|
||||
b->dbg = (spl_dbg_node_t){0};
|
||||
vec_init(b->reloc_label);
|
||||
vec_init(b->blocks);
|
||||
b->current_block = 0;
|
||||
vec_init(b->fixups);
|
||||
b->terminated = false;
|
||||
}
|
||||
|
||||
void spl_ir_builder_drop(spl_ir_builder_t *b) {
|
||||
spl_ir_drop(&b->ir);
|
||||
vec_free(b->reloc_label);
|
||||
vec_free(b->blocks);
|
||||
vec_free(b->fixups);
|
||||
}
|
||||
|
||||
spl_ir_func_ref_t spl_ir_builder_fn_new(spl_ir_builder_t *b, const char *name,
|
||||
spl_type_id_t fn_tid) {
|
||||
spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name,
|
||||
spl_type_id_t fn_tid, spl_ir_attr_t attr) {
|
||||
if (b->current_fn) {
|
||||
builder_reloc_check(b);
|
||||
spl_ir_builder_fn_end(b);
|
||||
}
|
||||
spl_ir_func_ref_t fid = spl_ir_alloc_fn(&b->ir);
|
||||
spl_ir_func_t *f = spl_ir_func(&b->ir, fid);
|
||||
f->name = name;
|
||||
f->attr = attr;
|
||||
f->fn_tid = fn_tid;
|
||||
|
||||
b->current_fn = fid;
|
||||
b->current_node = 0;
|
||||
b->current_block = 0;
|
||||
b->blocks.size = 0;
|
||||
b->fixups.size = 0;
|
||||
b->terminated = false;
|
||||
return fid;
|
||||
}
|
||||
|
||||
spl_ir_func_ref_t spl_ir_builder_cur_fn(const spl_ir_builder_t *b) { return b->current_fn; }
|
||||
void spl_ir_builder_fn_end(spl_ir_builder_t *b) {
|
||||
spl_ir_func_t *f = spl_ir_func(&b->ir, b->current_fn);
|
||||
if (!f) {
|
||||
Panic("ir func not found");
|
||||
return;
|
||||
}
|
||||
|
||||
void spl_ir_builder_set_dbg(spl_ir_builder_t *b, spl_dbg_node_t dbg) { b->dbg = dbg; }
|
||||
vec_for(b->fixups, i) {
|
||||
spl_ir_fix_t *fx = &vec_at(b->fixups, i);
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, fx->node);
|
||||
if (!n) {
|
||||
SPL_ERROR(&n->dbg, "unknown node in func");
|
||||
continue;
|
||||
}
|
||||
spl_ir_node_ref_t target = 0;
|
||||
if (fx->block < vec_size(b->blocks)) {
|
||||
target = vec_at(b->blocks, fx->block);
|
||||
}
|
||||
if (target == 0) {
|
||||
Panic("unknown reloc target bblock");
|
||||
}
|
||||
switch (fx->slot) {
|
||||
case SPL_IR_FIX_BR_TRUE:
|
||||
n->control_br.true_label = target;
|
||||
break;
|
||||
case SPL_IR_FIX_BR_FALSE:
|
||||
n->control_br.false_label = target;
|
||||
break;
|
||||
case SPL_IR_FIX_JMP:
|
||||
n->control_jmp.label = target;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_block_new(spl_ir_builder_t *b) {
|
||||
spl_ir_func_t *f = builder_cur_func(b);
|
||||
Assert(f != NULL);
|
||||
return vec_size(f->nodes);
|
||||
b->current_block = 0;
|
||||
b->blocks.size = 0;
|
||||
b->fixups.size = 0;
|
||||
b->terminated = false;
|
||||
}
|
||||
|
||||
usize spl_ir_builder_block_begin(spl_ir_builder_t *b) {
|
||||
vec_push(b->blocks, (spl_ir_block_t){0});
|
||||
usize block = vec_size(b->blocks) - 1;
|
||||
b->current_block = block;
|
||||
b->terminated = false;
|
||||
return block;
|
||||
}
|
||||
|
||||
void spl_ir_builder_block_end(spl_ir_builder_t *b) {
|
||||
if (!b->terminated) {
|
||||
Panic("bblock must be end of terminated");
|
||||
}
|
||||
}
|
||||
|
||||
#define X(name, kind) \
|
||||
@@ -510,6 +543,22 @@ spl_ir_node_ref_t spl_ir_builder_mem_set(spl_ir_builder_t *b, spl_type_id_t tid,
|
||||
return ref;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_type_const_bool(spl_ir_builder_t *b, spl_type_id_t tid, bool val) {
|
||||
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST);
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
n->type_const.tid = tid;
|
||||
n->type_const.bool_lit = val;
|
||||
return ref;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_type_const_ptr(spl_ir_builder_t *b, spl_type_id_t tid, void *val) {
|
||||
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST);
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
n->type_const.tid = tid;
|
||||
n->type_const.ptr_lit = val;
|
||||
return ref;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_type_const_int(spl_ir_builder_t *b, spl_type_id_t tid, usize val) {
|
||||
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST);
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
@@ -640,27 +689,46 @@ spl_ir_node_ref_t spl_ir_builder_control_select(spl_ir_builder_t *b, spl_type_id
|
||||
return ref;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_control_br(spl_ir_builder_t *b, spl_ir_node_ref_t cond,
|
||||
spl_ir_node_ref_t true_label,
|
||||
spl_ir_node_ref_t false_label) {
|
||||
builder_reloc_add(b, true_label);
|
||||
builder_reloc_add(b, false_label);
|
||||
spl_ir_node_ref_t spl_ir_builder_control_br(spl_ir_builder_t *b, spl_ir_node_ref_t cond) {
|
||||
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_BR);
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
n->control_br.cond = cond;
|
||||
n->control_br.true_label = true_label;
|
||||
n->control_br.false_label = false_label;
|
||||
n->control_br.true_label = 0;
|
||||
n->control_br.false_label = 0;
|
||||
b->terminated = true;
|
||||
return ref;
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_control_jmp(spl_ir_builder_t *b, spl_ir_node_ref_t label) {
|
||||
builder_reloc_add(b, label);
|
||||
void spl_ir_builder_control_br_fixup(spl_ir_builder_t *b, spl_ir_node_ref_t ref, usize true_block,
|
||||
usize false_block) {
|
||||
spl_ir_node_t *node = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
if (!(node && node->kind == SPL_IR_CONTROL_BR)) {
|
||||
Panic("fixup must be valid jmp ir node");
|
||||
}
|
||||
spl_ir_fix_t f1 = {.node = ref, .slot = SPL_IR_FIX_BR_TRUE, .block = true_block};
|
||||
vec_push(b->fixups, f1);
|
||||
spl_ir_fix_t f2 = {.node = ref, .slot = SPL_IR_FIX_BR_FALSE, .block = false_block};
|
||||
vec_push(b->fixups, f2);
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_control_jmp(spl_ir_builder_t *b) {
|
||||
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_JMP);
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
n->control_jmp.label = label;
|
||||
n->control_jmp.label = 0;
|
||||
b->terminated = true;
|
||||
return ref;
|
||||
}
|
||||
|
||||
void spl_ir_builder_control_jmp_fixup(spl_ir_builder_t *b, spl_ir_node_ref_t ref,
|
||||
usize target_block) {
|
||||
spl_ir_node_t *node = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
if (!(node && node->kind == SPL_IR_CONTROL_JMP)) {
|
||||
Panic("fixup must be valid jmp ir node");
|
||||
}
|
||||
spl_ir_fix_t fx = {.node = ref, .slot = SPL_IR_FIX_JMP, .block = target_block};
|
||||
vec_push(b->fixups, fx);
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t spl_ir_builder_control_call(spl_ir_builder_t *b, spl_type_id_t tid,
|
||||
spl_ir_node_ref_t func) {
|
||||
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_CALL);
|
||||
@@ -693,6 +761,7 @@ spl_ir_node_ref_t spl_ir_builder_control_ret(spl_ir_builder_t *b, spl_type_id_t
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
n->control_ret.tid = tid;
|
||||
n->control_ret.val = val;
|
||||
b->terminated = true;
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user