feat(backend/riscv32): 实现基础的编译器功能

- 完成 RV32IMA 指令集的代码生成
- 添加整数运算、分支、调用等基本指令支持
- 实现从 IR 到机器码的转换
- 添加简单的测试用例和测试框架
This commit is contained in:
ZZY
2025-03-08 16:50:21 +08:00
parent 95bf44eb3f
commit 172d72b0a0
32 changed files with 980 additions and 469 deletions

View File

@@ -9,22 +9,6 @@ typedef union rv32code {
uint8_t bytes[4];
} rv32code_t;
#define CRT_CODE_SIZE 16
// 使用示例
rv32code_t gcodes[] = {
LI(REG_SP, 0x1000),
LI(REG_RA, 0x0),
CALL_ABS(CRT_CODE_SIZE << 2),
// Exit
ECALL_EXIT2(),
};
void test_raw_gen(FILE* out) {
fwrite(gcodes, sizeof(rv32code_t), sizeof(gcodes)/sizeof(gcodes[0]), out);
}
#include "../../frontend/frontend.h"
#include "../../middleend/ir.h"
typedef struct {
@@ -59,9 +43,9 @@ int write_inst(union rv32code ins, FILE* fp) {
}
#define GENCODE(code) vector_push(ctx.codes, (rv32code_t)(code)); len += 4
#define GENCODES(code) do { \
#define GENCODES(...) do { \
rv32code_t codes[] = { \
code \
__VA_ARGS__ \
}; \
for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i ++) { \
GENCODE(codes[i]); \
@@ -105,13 +89,18 @@ static int func_idx(ir_func_t* tofunc) {
}
static int system_func(const char* name) {
static const char defined_func[][16] = {
"ecall_pnt_int",
static struct {
const char* name;
int ecall_num;
} defined_func[] = {
{"ecall_pnt_int", 1},
{"ecall_pnt_char", 11},
{"ecall_scan_int", 1025 + 4},
};
for (int j = 0; j < sizeof(defined_func)/sizeof(defined_func[0]); j++) {
if (strcmp(name, defined_func[j]) == 0) {
return j;
for (int i = 0; i < sizeof(defined_func)/sizeof(defined_func[0]); i++) {
if (strcmp(name, defined_func[i].name) == 0) {
return defined_func[i].ecall_num;
}
}
return -1;
@@ -119,11 +108,22 @@ static int system_func(const char* name) {
static int get_node_val(ir_node_t* ptr, int reg) {
int len = 0;
if (ptr->tag == IR_NODE_CONST_INT) {
GENCODES(LI(reg, ptr->data.const_int.val));
} else {
int offset = stack_offset(ptr);
GENCODE(LW(reg, REG_SP, offset));
switch (ptr->tag) {
case IR_NODE_CONST_INT: {
GENCODES(LI(reg, ptr->data.const_int.val));
break;
}
// case IR_NODE_CALL: {
// // GENCODE(SW(REG_A0, REG_SP, ctx.stack_offset));
// // GENCODE()
// // break;
// }
default: {
int offset = stack_offset(ptr);
GENCODE(LW(reg, REG_SP, offset));
break;
}
}
return len;
}
@@ -139,8 +139,6 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) {
// S1 = *(S0 + imm)
offset = stack_offset(instr->data.load.target);
GENCODE(LW(REG_T0, REG_SP, offset));
// offset = STACK_OFFSET(instr);
// GENCODE(SW(REG_T0, REG_SP, offset));
break;
}
case IR_NODE_STORE: {
@@ -180,6 +178,27 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) {
case IR_OP_MOD:
GENCODE(REM(REG_T0, REG_T1, REG_T2));
break;
case IR_OP_EQ:
GENCODE(XOR(REG_T0, REG_T1, REG_T2));
GENCODE(SEQZ(REG_T0, REG_T0));
break;
case IR_OP_GE:
GENCODE(SLT(REG_T0, REG_T1, REG_T2));
GENCODE(SEQZ(REG_T0, REG_T0));
break;
case IR_OP_GT:
GENCODE(SGT(REG_T0, REG_T1, REG_T2));
break;
case IR_OP_LE:
GENCODE(SGT(REG_T0, REG_T1, REG_T2));
GENCODE(SEQZ(REG_T0, REG_T0));
break;
case IR_OP_LT:
GENCODE(SLT(REG_T0, REG_T1, REG_T2));
break;
case IR_OP_NEQ:
GENCODE(XOR(REG_T0, REG_T1, REG_T2));
break;
default:
error("ERROR gen_instr op in riscv");
break;
@@ -244,13 +263,15 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) {
}
int system_func_idx = system_func(instr->data.call.callee->name);
if (system_func_idx == 0) {
// ecall_pnt_int
GENCODE(ADDI(REG_A7, REG_X0, 0x1));
GENCODE(ECALL());
break;
if (system_func_idx != -1) {
// ecall
GENCODES(
ADDI(REG_A7, REG_X0, system_func_idx),
ECALL()
);
goto CALL_END;
}
jmp_t* jmp = xmalloc(sizeof(jmp_t));
*jmp = (jmp_t) {
.base_offset = ctx.cur_func_offset + ctx.cur_block_offset + len,
@@ -260,10 +281,11 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) {
.cur_idx = func_idx(ctx.cur_func),
};
vector_push(ctx.call, jmp);
GENCODES((
CALL(0)
));
GENCODES(CALL(0));
CALL_END:
offset = stack_offset(instr);
GENCODE(SW(REG_A0, REG_SP, offset));
break;
}
default:
@@ -335,10 +357,9 @@ static int gen_func(ir_func_t* func) {
return len;
}
static void gen_code(ir_prog_t* prog) {
static int gen_code(ir_prog_t* prog) {
ctx.prog = prog;
for (int i = 0; i < prog->extern_funcs.size; i++) {
if (system_func(prog->extern_funcs.data[i]->name) == -1) {
error("func %s not defined and not a system func", prog->extern_funcs.data[i]->name);
@@ -354,12 +375,12 @@ static void gen_code(ir_prog_t* prog) {
len += ret;
}
for (int i = 0; i < ctx.call.size; i++) {
jmp_t* jmp = vector_at(ctx.call, i);
int32_t code = 0;
// FIXME ERROR
int offset = jmp_cache[jmp->to_idx] - (jmp_cache[jmp->cur_idx] + jmp->base_offset);
assert(offset > -0xfff && offset < 0xfff);
int32_t codes[2] = {
CALL(offset)
};
@@ -369,6 +390,14 @@ static void gen_code(ir_prog_t* prog) {
};
}
}
// Got Main pos;
for (int i = 0; i < prog->funcs.size; i++) {
if (strcmp(vector_at(prog->funcs, i)->name, "main") == 0) {
return jmp_cache[i];
}
}
error("main not found");
}
int main(int argc, char** argv) {
@@ -390,7 +419,23 @@ int main(int argc, char** argv) {
struct ASTNode* root = frontend(infilename, in, (sread_fn)fread_s);
gen_ir_from_ast(root);
gen_code(&prog);
int main_pos = gen_code(&prog);
#define CRT_CODE_SIZE 16
rv32code_t gcodes[] = {
LI(REG_SP, 0x1000),
LI(REG_RA, 0x0),
CALL(0),
// Exit
ECALL_EXIT2(),
};
main_pos += (CRT_CODE_SIZE - 4) * 4;
assert(main_pos > -0xfff && main_pos < 0xfff);
rv32code_t call_main[2] = {
CALL(main_pos)
};
gcodes[4] = call_main[0];
gcodes[5] = call_main[1];
for (int i = 0; i < CRT_CODE_SIZE; i++) {
write_inst((union rv32code) {