feat add func call and rewrite codes
This commit is contained in:
0
ccompiler/middleend/Makefile
Normal file
0
ccompiler/middleend/Makefile
Normal file
@ -5,48 +5,61 @@ typedef struct ASTNode ASTNode;
|
||||
|
||||
// 上下文结构,记录生成过程中的状态
|
||||
typedef struct {
|
||||
ir_func_t* current_func; // 当前处理的函数
|
||||
ir_bblock_t* current_block; // 当前基本块
|
||||
uint32_t vreg_counter; // 虚拟寄存器计数器
|
||||
ir_func_t* cur_func; // 当前处理的函数
|
||||
ir_bblock_t* cur_block; // 当前基本块
|
||||
} IRGenContext;
|
||||
IRGenContext ctx;
|
||||
ir_prog_t prog;
|
||||
ir_type_t type_i32 = {
|
||||
.tag = IR_TYPE_INT32,
|
||||
};
|
||||
|
||||
static inline void init_ir_node_t(ir_node_t* node) {
|
||||
node->name = NULL;
|
||||
node->type = NULL;
|
||||
vector_init(node->used_by);
|
||||
}
|
||||
|
||||
static inline ir_node_t* new_ir_node_t() {
|
||||
static inline ir_node_t* new_irnode() {
|
||||
ir_node_t* node = xmalloc(sizeof(ir_node_t));
|
||||
init_ir_node_t(node);
|
||||
}
|
||||
|
||||
static inline ir_bblock_t* new_irbblock(const char* name) {
|
||||
ir_bblock_t* block = xmalloc(sizeof(ir_bblock_t));
|
||||
block->label = name;
|
||||
vector_init(block->instrs);
|
||||
return block;
|
||||
}
|
||||
|
||||
ir_node_t* emit_instr(ir_bblock_t* block) {
|
||||
if (block == NULL) block = ctx.current_block;
|
||||
ir_node_t *node = new_ir_node_t();
|
||||
if (block == NULL) block = ctx.cur_block;
|
||||
ir_node_t *node = new_irnode();
|
||||
vector_push(block->instrs, node);
|
||||
return vector_at(block->instrs, block->instrs.size - 1);
|
||||
}
|
||||
|
||||
void emit_br(ir_node_t cond, const char* true_lable, const char* false_lable) {
|
||||
ir_node_t br = {
|
||||
.tag = IR_NODE_RET,
|
||||
.data = {
|
||||
ir_node_t* emit_br(ir_node_t* cond, ir_bblock_t* trueb, ir_bblock_t* falseb) {
|
||||
ir_node_t* br = emit_instr(NULL);
|
||||
*br = (ir_node_t) {
|
||||
.tag = IR_NODE_BRANCH,
|
||||
.data.branch = {
|
||||
.cond = cond,
|
||||
.true_bblock = trueb,
|
||||
.false_bblock = falseb,
|
||||
}
|
||||
};
|
||||
// emit_instr(br, NULL);
|
||||
return br;
|
||||
}
|
||||
|
||||
ir_node_t* gen_ir_expr(ASTNode* node) {
|
||||
switch (node->type) {
|
||||
case NT_TERM_VAL: {
|
||||
ir_node_t* ir = new_ir_node_t();
|
||||
ir_node_t* ir = new_irnode();
|
||||
*ir = (ir_node_t) {
|
||||
.tag = IR_NODE_CONST_INT,
|
||||
.data.const_int = {
|
||||
.val = node->syms.tok.constant.i,
|
||||
.val = node->syms.tok.val.i,
|
||||
},
|
||||
};
|
||||
return ir;
|
||||
@ -56,15 +69,18 @@ ir_node_t* gen_ir_expr(ASTNode* node) {
|
||||
return decl;
|
||||
}
|
||||
case NT_TERM_CALL: {
|
||||
// TODO
|
||||
ir_node_t* ir = new_ir_node_t();
|
||||
ir_node_t* ir = emit_instr(NULL);
|
||||
*ir = (ir_node_t) {
|
||||
.tag = IR_NODE_CALL,
|
||||
.data.call = {
|
||||
.callee = NULL,
|
||||
.callee = node->call.func_decl->decl_func.def->func.data,
|
||||
},
|
||||
};
|
||||
vector_init(ir->data.call.args);
|
||||
for (int i = 0; i < node->call.params->params.params.size; i++) {
|
||||
vector_push(ir->data.call.args, \
|
||||
gen_ir_expr(node->call.params->params.params.data[i]));
|
||||
}
|
||||
return ir;
|
||||
}
|
||||
default:
|
||||
@ -191,42 +207,75 @@ NEXT:
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static ir_func_t* new_irfunc(const char* name) {
|
||||
ir_func_t *func = xmalloc(sizeof(ir_func_t));
|
||||
|
||||
vector_init(func->bblocks);
|
||||
vector_init(func->params);
|
||||
*func = (ir_func_t) {
|
||||
.name = name,
|
||||
// TODO typing system
|
||||
.type = &type_i32,
|
||||
};
|
||||
return func;
|
||||
}
|
||||
|
||||
static void gen_ir_func(ASTNode* node, ir_func_t* func) {
|
||||
assert(node->type == NT_FUNC);
|
||||
ir_bblock_t *entry = new_irbblock("entry");
|
||||
vector_push(func->bblocks, entry);
|
||||
|
||||
vector_push(prog.funcs, func);
|
||||
IRGenContext prev_ctx = ctx;
|
||||
ctx.cur_func = func;
|
||||
ctx.cur_block = entry;
|
||||
|
||||
ast_node_t* params = node->func.decl->decl_func.params;
|
||||
for (int i = 0; i < params->params.params.size; i ++) {
|
||||
ir_node_t* decl = emit_instr(entry);
|
||||
ast_node_t* param = params->params.params.data[i];
|
||||
vector_push(func->params, decl);
|
||||
*decl = (ir_node_t) {
|
||||
.tag = IR_NODE_ALLOC,
|
||||
.name = param->decl_val.name->syms.tok.val.str,
|
||||
.type = &type_i32,
|
||||
};
|
||||
param->decl_val.data = decl;
|
||||
}
|
||||
gen_ir_from_ast(node->func.body);
|
||||
|
||||
ctx = prev_ctx;
|
||||
}
|
||||
|
||||
void gen_ir_from_ast(struct ASTNode* node) {
|
||||
switch (node->type) {
|
||||
case NT_ROOT: {
|
||||
for (int i = 0; i < node->root.child_size; i ++) {
|
||||
gen_ir_from_ast(node->root.children[i]);
|
||||
for (int i = 0; i < node->root.children.size; i ++) {
|
||||
gen_ir_from_ast(node->root.children.data[i]);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
case NT_DECL_FUNC: {
|
||||
ir_func_t* func = new_irfunc(node->decl_func.name->syms.tok.val.str);
|
||||
if (node->decl_func.def == NULL) {
|
||||
ast_node_t* def = new_ast_node();
|
||||
def->func.body = NULL;
|
||||
def->func.decl = node;
|
||||
node->decl_func.def = def;
|
||||
vector_push(prog.extern_funcs, func);
|
||||
}
|
||||
node->decl_func.def->func.data = func;
|
||||
break;
|
||||
}
|
||||
case NT_FUNC: {
|
||||
ir_func_t *func = xmalloc(sizeof(ir_func_t));
|
||||
*func = (ir_func_t) {
|
||||
.name = node->func.name->syms.tok.constant.str,
|
||||
};
|
||||
vector_init(func->bblocks);
|
||||
|
||||
ir_bblock_t *entry = xmalloc(sizeof(ir_bblock_t));
|
||||
*entry = (ir_bblock_t) {
|
||||
.label = "entry",
|
||||
};
|
||||
vector_init(entry->instrs);
|
||||
vector_push(func->bblocks, entry);
|
||||
|
||||
IRGenContext prev_ctx = ctx;
|
||||
ctx = (IRGenContext) {
|
||||
.current_func = func,
|
||||
.current_block = vector_at(func->bblocks, 0),
|
||||
.vreg_counter = 0,
|
||||
};
|
||||
|
||||
gen_ir_from_ast(node->func.body);
|
||||
|
||||
ctx = prev_ctx;
|
||||
vector_push(prog.funcs, func);
|
||||
} break;
|
||||
gen_ir_func(node, node->func.data);
|
||||
break;
|
||||
}
|
||||
case NT_STMT_RETURN: {
|
||||
ir_node_t* ret = gen_ir_expr(node->return_stmt.expr_stmt);
|
||||
ir_node_t* ret = NULL;
|
||||
if (node->return_stmt.expr_stmt != NULL) {
|
||||
ret = gen_ir_expr(node->return_stmt.expr_stmt);
|
||||
}
|
||||
ir_node_t* ir = emit_instr(NULL);
|
||||
*ir = (ir_node_t) {
|
||||
.tag = IR_NODE_RET,
|
||||
@ -236,22 +285,54 @@ void gen_ir_from_ast(struct ASTNode* node) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
vector_push(ctx.cur_func->bblocks, new_irbblock(NULL));
|
||||
break;
|
||||
}
|
||||
case NT_STMT_BLOCK: {
|
||||
gen_ir_from_ast(node->block_stmt.block);
|
||||
break;
|
||||
}
|
||||
case NT_BLOCK: {
|
||||
for (int i = 0; i < node->block.child_size; i ++) {
|
||||
gen_ir_from_ast(node->block.children[i]);
|
||||
for (int i = 0; i < node->block.children.size; i ++) {
|
||||
gen_ir_from_ast(node->block.children.data[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NT_STMT_IF: {
|
||||
ir_node_t *cond = gen_ir_expr(node->if_stmt.cond);
|
||||
ir_bblock_t* trueb = new_irbblock("true_block");
|
||||
ir_bblock_t* falseb = new_irbblock("false_block");
|
||||
emit_br(cond, trueb, falseb);
|
||||
|
||||
// xmalloc();
|
||||
// ir_bblock_t then_block = {
|
||||
// };
|
||||
node->if_stmt.if_stmt;
|
||||
node->if_stmt.else_stmt;
|
||||
vector_push(ctx.cur_func->bblocks, trueb);
|
||||
ctx.cur_block = trueb;
|
||||
gen_ir_from_ast(node->if_stmt.if_stmt);
|
||||
ir_node_t* jmp = emit_instr(NULL);
|
||||
|
||||
if (node->if_stmt.else_stmt != NULL) {
|
||||
vector_push(ctx.cur_func->bblocks, falseb);
|
||||
ctx.cur_block = falseb;
|
||||
gen_ir_from_ast(node->if_stmt.else_stmt);
|
||||
ir_node_t* jmp = emit_instr(NULL);
|
||||
|
||||
ctx.cur_block = new_irbblock("jmp_block");
|
||||
vector_push(ctx.cur_func->bblocks, ctx.cur_block);
|
||||
*jmp = (ir_node_t) {
|
||||
.tag = IR_NODE_JUMP,
|
||||
.data.jump = {
|
||||
.target_bblock = ctx.cur_block,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
ctx.cur_block = falseb;
|
||||
}
|
||||
*jmp = (ir_node_t) {
|
||||
.tag = IR_NODE_JUMP,
|
||||
.data.jump = {
|
||||
.target_bblock = ctx.cur_block,
|
||||
},
|
||||
};
|
||||
break;
|
||||
}
|
||||
case NT_STMT_WHILE: {
|
||||
@ -275,7 +356,7 @@ void gen_ir_from_ast(struct ASTNode* node) {
|
||||
ir_node_t* ret_node = emit_instr(NULL);
|
||||
*ret_node = (ir_node_t) {
|
||||
.tag = IR_NODE_ALLOC,
|
||||
.name = node->decl_val.name->syms.tok.constant.str,
|
||||
.name = node->decl_val.name->syms.tok.val.str,
|
||||
.type = &type_i32,
|
||||
};
|
||||
node->decl_val.data = ret_node;
|
||||
|
@ -54,6 +54,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
vector_header(global, ir_node_t*);
|
||||
vector_header(funcs, ir_func_t*);
|
||||
vector_header(extern_funcs, ir_func_t*);
|
||||
} ir_prog_t;
|
||||
|
||||
struct ir_node {
|
||||
@ -131,15 +132,15 @@ struct ir_node {
|
||||
} op;
|
||||
struct {
|
||||
ir_node_t* cond;
|
||||
ir_bblock_t true_bblock;
|
||||
ir_bblock_t false_bblock;
|
||||
ir_bblock_t* true_bblock;
|
||||
ir_bblock_t* false_bblock;
|
||||
} branch;
|
||||
struct {
|
||||
ir_bblock_t target_bblock;
|
||||
ir_bblock_t* target_bblock;
|
||||
} jump;
|
||||
struct {
|
||||
ir_func_t callee;
|
||||
vector_header(args, ir_node_t);
|
||||
ir_func_t* callee;
|
||||
vector_header(args, ir_node_t*);
|
||||
} call;
|
||||
struct {
|
||||
ir_node_t* ret_val;
|
||||
|
@ -1,5 +1,7 @@
|
||||
int main(void) {
|
||||
int a;
|
||||
a = 1 + 2 * 3;
|
||||
return a;
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
return add(1, 2);
|
||||
}
|
||||
|
Reference in New Issue
Block a user