init basic

This commit is contained in:
ZZY
2025-03-05 15:45:19 +08:00
commit 09299e339c
42 changed files with 5752 additions and 0 deletions

299
ccompiler/middleend/ir.c Normal file
View File

@ -0,0 +1,299 @@
#include "ir.h"
#include "../frontend/frontend.h"
typedef struct ASTNode ASTNode;
// 上下文结构,记录生成过程中的状态
typedef struct {
ir_func_t* current_func; // 当前处理的函数
ir_bblock_t* current_block; // 当前基本块
uint32_t vreg_counter; // 虚拟寄存器计数器
} 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) {
vector_init(node->used_by);
}
static inline ir_node_t* new_ir_node_t() {
ir_node_t* node = xmalloc(sizeof(ir_node_t));
init_ir_node_t(node);
}
ir_node_t* emit_instr(ir_bblock_t* block) {
if (block == NULL) block = ctx.current_block;
ir_node_t *node = new_ir_node_t();
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 = {
}
};
// emit_instr(br, NULL);
}
ir_node_t* gen_ir_expr(ASTNode* node) {
switch (node->type) {
case NT_TERM_VAL: {
ir_node_t* ir = new_ir_node_t();
*ir = (ir_node_t) {
.tag = IR_NODE_CONST_INT,
.data.const_int = {
.val = node->syms.tok.constant.i,
},
};
return ir;
}
case NT_TERM_IDENT: {
ir_node_t* decl = node->syms.decl_node->decl_val.data;
return decl;
}
case NT_TERM_CALL: {
// TODO
ir_node_t* ir = new_ir_node_t();
*ir = (ir_node_t) {
.tag = IR_NODE_CALL,
.data.call = {
.callee = NULL,
},
};
vector_init(ir->data.call.args);
return ir;
}
default:
goto NEXT;
}
return NULL;
NEXT:
ir_node_t* lhs = gen_ir_expr(node->expr.left);
ir_node_t* rhs = node->expr.right ? gen_ir_expr(node->expr.right) : NULL;
if (node->type == NT_COMMA) {
return rhs;
}
ir_node_t* instr = emit_instr(NULL);
vector_push(lhs->used_by, instr);
if (rhs) { vector_push(rhs->used_by, instr); }
ir_node_t* ret;
#define BINOP(operand) do { \
*instr = (ir_node_t){ \
.tag = IR_NODE_OP, \
.data.op = { \
.op = operand, \
.lhs = lhs, \
.rhs = rhs, \
}, \
}; \
ret = instr; \
} while (0)
switch (node->type) {
case NT_ADD :// (expr) + (expr)
BINOP(IR_OP_ADD);
break;
case NT_SUB :// (expr) - (expr)
BINOP(IR_OP_SUB);
break;
case NT_MUL :// (expr) * (expr)
BINOP(IR_OP_MUL);
break;
case NT_DIV :// (expr) / (expr)
BINOP(IR_OP_DIV);
break;
case NT_MOD :// (expr) % (expr)
BINOP(IR_OP_MOD);
break;
case NT_AND :// (expr) & (expr)
BINOP(IR_OP_AND);
break;
case NT_OR :// (expr) | (expr)
BINOP(IR_OP_OR);
break;
case NT_XOR :// (expr) ^ (expr)
BINOP(IR_OP_XOR);
break;
case NT_BIT_NOT :// ~ (expr)
// TODO
// BINOP(IR_OP_NOT);
break;
case NT_L_SH :// (expr) << (expr)
BINOP(IR_OP_SHL);
break;
case NT_R_SH :// (expr) >> (expr)
BINOP(IR_OP_SHR); // Shift right logical.
// TODO
// BINOP(IR_OP_SAR); // Shift right arithmetic.
break;
case NT_EQ :// (expr) == (expr)
BINOP(IR_OP_EQ);
break;
case NT_NEQ :// (expr) != (expr)
BINOP(IR_OP_NEQ);
break;
case NT_LE :// (expr) <= (expr)
BINOP(IR_OP_LE);
break;
case NT_GE :// (expr) >= (expr)
BINOP(IR_OP_GE);
break;
case NT_LT :// (expr) < (expr)
BINOP(IR_OP_LT);
break;
case NT_GT :// (expr) > (expr)
BINOP(IR_OP_GE);
break;
case NT_AND_AND :// (expr) && (expr)
break;
case NT_OR_OR :// (expr) || (expr)
break;
case NT_NOT :// ! (expr)
ir_node_t* zero = xmalloc(sizeof(ir_node_t));
*zero = (ir_node_t){
.tag = IR_NODE_CONST_INT,
.data.const_int = {
.val = 0,
},
};
*instr = (ir_node_t){
.tag = IR_NODE_OP,
.data.op = {
.op = IR_OP_EQ,
.lhs = zero,
.rhs = lhs,
},
};
ret = instr;
break;
case NT_ASSIGN :// (expr) = (expr)
*instr = (ir_node_t){
.tag = IR_NODE_STORE,
.data.store = {
.target = lhs,
.value = rhs,
},
};
ret = rhs;
break;
// case NT_COND : // (expr) ? (expr) : (expr)
default:
// TODO self error msg
error("Unsupported IR generation for AST node type %d", node->type);
break;
}
return ret;
}
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]);
}
} 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;
case NT_STMT_RETURN: {
ir_node_t* ret = gen_ir_expr(node->return_stmt.expr_stmt);
ir_node_t* ir = emit_instr(NULL);
*ir = (ir_node_t) {
.tag = IR_NODE_RET,
.data = {
.ret = {
.ret_val = ret,
}
}
};
break;
}
case NT_BLOCK: {
for (int i = 0; i < node->block.child_size; i ++) {
gen_ir_from_ast(node->block.children[i]);
}
break;
}
case NT_STMT_IF: {
ir_node_t *cond = gen_ir_expr(node->if_stmt.cond);
// xmalloc();
// ir_bblock_t then_block = {
// };
node->if_stmt.if_stmt;
node->if_stmt.else_stmt;
break;
}
case NT_STMT_WHILE: {
node->while_stmt.cond;
node->while_stmt.body;
break;
}
case NT_STMT_DOWHILE: {
node->do_while_stmt.cond;
node->do_while_stmt.body;
break;
}
case NT_STMT_FOR: {
node->for_stmt.init;
node->for_stmt.cond;
node->for_stmt.iter;
node->for_stmt.body;
break;
}
case NT_DECL_VAR: {
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,
.type = &type_i32,
};
node->decl_val.data = ret_node;
if (node->decl_val.expr_stmt != NULL) {
gen_ir_from_ast(node->decl_val.expr_stmt);
}
break;
}
case NT_STMT_EXPR: {
gen_ir_expr(node->expr_stmt.expr_stmt);
break;
}
case NT_STMT_EMPTY: {
break;
}
default:
// TODO: 错误处理
error("unknown node type");
break;
}
}

155
ccompiler/middleend/ir.h Normal file
View File

@ -0,0 +1,155 @@
// ir_core.h
#ifndef IR_CORE_H
#define IR_CORE_H
#include "../../libcore/vector.h"
#include <stddef.h>
#include <stdint.h>
// 错误码定义
typedef enum {
IR_EC_SUCCESS = 0, // 成功
IR_EC_MEMORY_ERROR, // 内存分配失败
IR_EC_TYPE_MISMATCH, // 类型不匹配
IR_EC_INVALID_OPERAND, // 无效操作数
IR_EC_DUPLICATE_SYMBOL, // 符号重定义
} ir_ecode_t;
typedef struct {
enum {
IR_TYPE_INT32,
IR_TYPE_PTR,
IR_TYPE_ARRAY,
IR_TYPE_FUNC,
IR_TYPE_VOID,
} tag;
union {
struct {
struct ir_type *base;
size_t len;
} arr;
struct {
struct ir_type *ret;
struct ir_type **params;
size_t param_cnt;
} func;
};
} ir_type_t;
typedef struct ir_node ir_node_t;
typedef struct ir_bblock {
const char *label;
vector_header(instrs, ir_node_t*);
// ir_arr_t used_by;
} ir_bblock_t; // basic block
typedef struct {
const char *name;
ir_type_t *type;
vector_header(params, ir_node_t*);
vector_header(bblocks, ir_bblock_t*);
} ir_func_t;
typedef struct {
vector_header(global, ir_node_t*);
vector_header(funcs, ir_func_t*);
} ir_prog_t;
struct ir_node {
const ir_type_t* type;
const char* name;
vector_header(used_by, ir_node_t*);
enum {
IR_NODE_CONST_INT,
IR_NODE_ALLOC,
IR_NODE_LOAD,
IR_NODE_STORE,
IR_NODE_GET_PTR,
IR_NODE_OP,
IR_NODE_BRANCH,
IR_NODE_JUMP,
IR_NODE_CALL,
IR_NODE_RET,
} tag;
union {
struct {
int32_t val;
} const_int;
struct {
ir_node_t* target;
} load;
struct {
ir_node_t* target;
ir_node_t* value;
} store;
struct {
ir_node_t* src_addr;
ir_node_t* offset;
} get_ptr;
struct {
enum {
/// Not equal to.
IR_OP_NEQ,
/// Equal to.
IR_OP_EQ,
/// Greater than.
IR_OP_GT,
/// Less than.
IR_OP_LT,
/// Greater than or equal to.
IR_OP_GE,
/// Less than or equal to.
IR_OP_LE,
/// Addition.
IR_OP_ADD,
/// Subtraction.
IR_OP_SUB,
/// Multiplication.
IR_OP_MUL,
/// Division.
IR_OP_DIV,
/// Modulo.
IR_OP_MOD,
/// Bitwise AND.
IR_OP_AND,
/// Bitwise OR.
IR_OP_OR,
/// Bitwise XOR.
IR_OP_XOR,
/// Bitwise NOT.
IR_OP_NOT,
/// Shift left logical.
IR_OP_SHL,
/// Shift right logical.
IR_OP_SHR,
/// Shift right arithmetic.
IR_OP_SAR,
} op;
ir_node_t* lhs;
ir_node_t* rhs;
} op;
struct {
ir_node_t* cond;
ir_bblock_t true_bblock;
ir_bblock_t false_bblock;
} branch;
struct {
ir_bblock_t target_bblock;
} jump;
struct {
ir_func_t callee;
vector_header(args, ir_node_t);
} call;
struct {
ir_node_t* ret_val;
} ret;
} data;
};
extern ir_prog_t prog;
struct ASTNode;
void gen_ir_from_ast(struct ASTNode* node);
#endif // IR_CORE_H

View File

View File

@ -0,0 +1,8 @@
#ifndef __REG_ALLOC_H__
#define __REG_ALLOC_H__
typedef struct {
} reg_alloc_t;
#endif

View File

@ -0,0 +1,8 @@
all: test_ir
test_ir: frontend
gcc -g ../ir.c test_ir.c -L../../frontend -lfrontend -o test_ir
frontend:
make -C ../../frontend

View File

@ -0,0 +1,5 @@
int main(void) {
int a;
a = 1 + 2 * 3;
return a;
}

View File

@ -0,0 +1,18 @@
#include "../ir.h"
#include "../../frontend/frontend.h"
int main(int argc, const char** argv) {
const char* file_name = "test_file.c";
if (argc == 2) {
file_name = argv[1];
}
FILE* fp = fopen(file_name, "r");
if (fp == NULL) {
perror("open file failed");
return 1;
}
printf("open file success\n");
struct ASTNode* root = frontend("test.c", fp, (sread_fn)fread_s);
gen_ir_from_ast(root);
return 0;
}