feat(ir2mcode): 添加IR到机器码转换模块并更新依赖配置

- 新增ir2mcode库用于将IR转换为机器码
- 添加sccf2target依赖以支持目标平台转换
- 在ast库中添加scc_pos依赖支持位置信息
- 更新cbuild.toml配置文件添加新库依赖
- 实现AMD64架构代码生成功能
- 添加寄存器分配器实现栈和寄存器位置管理
- 支持基本的算术运算和内存访问操作
- 添加PE格式目标文件生成支持
This commit is contained in:
zzy
2026-03-20 14:12:25 +08:00
parent 02a6c684f1
commit de6f5d510a
19 changed files with 4046 additions and 290 deletions

View File

@@ -0,0 +1,232 @@
#include <amd64/scc_amd64.h>
#include <amd64/scc_amd64_abi.h>
#include <reg_alloc.h>
#include <scc_ir2mcode.h>
static scc_reg_loc_t *parse_location(scc_ir2mcode_ctx_t *ctx,
scc_ir_bblock_ref_t node_ref) {
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
if (node == null) {
LOG_FATAL("invalid node ref");
return null;
}
usize idx = 0;
switch (node->tag) {
case SCC_IR_NODE_CONST_INT:
scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_ctx, node->type);
Assert(type != 0);
Assert(type->tag == SCC_IR_TYPE_U32 || type->tag == SCC_IR_TYPE_I32);
scc_reg_loc_t loc = {.kind = SCC_REG_KIND_IMM,
.idx = (usize)node->data.const_int.int32};
scc_vec_push(ctx->reg_alloc.reg_loc_vec, loc);
idx = scc_vec_size(ctx->reg_alloc.reg_loc_vec);
break;
case SCC_IR_NODE_CONST_UINT:
case SCC_IR_NODE_CONST_FLOAT:
TODO();
break;
default:
idx = (usize)scc_hashtable_get(ctx->noderef2regloc,
(void *)(usize)node_ref);
break;
}
Assert(idx > 0 && idx <= scc_vec_size(ctx->reg_alloc.reg_loc_vec));
return &scc_vec_at(ctx->reg_alloc.reg_loc_vec, idx - 1);
}
static void load_value_to_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, int reg) {
switch (loc->kind) {
case SCC_REG_KIND_GPR:
if (loc->idx != reg) {
scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->idx);
} else {
TODO();
}
break;
case SCC_REG_KIND_STACK:
scc_mcode_amd64_mov_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP,
-loc->idx);
break;
case SCC_REG_KIND_IMM:
scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->idx); // 或 imm32
break;
default:
LOG_FATAL("unsupported location");
}
}
static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc,
int reg) {
switch (loc->kind) {
case SCC_REG_KIND_GPR:
if (loc->idx != reg) {
scc_mcode_amd64_mov_r64_r64(mcode, loc->idx, reg);
}
case SCC_REG_KIND_STACK:
scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx,
reg);
break;
case SCC_REG_KIND_IMM:
LOG_FATAL("cannot store to immediate");
break;
default:
LOG_FATAL("unsupported location");
}
}
static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
int idx) {
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
if (node == null) {
LOG_ERROR("invalid node ref");
return;
}
switch (node->tag) {
case SCC_IR_NODE_CONV: ///< 类型转换
case SCC_IR_NODE_FUNC_ARG_REF: ///< 函数参数引用
case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用
LOG_ERROR("Unsupported node type: %d", node->tag);
break;
case SCC_IR_NODE_ALLOC: ///< 分配内存(stack)
case SCC_IR_NODE_GLOBAL_ALLOC: ///< 全局分配(bss)
break;
case SCC_IR_NODE_LOAD: ///< 加载数据
{
// node->data.load.target
scc_reg_loc_t *from = parse_location(ctx, node->data.load.target);
scc_reg_loc_t *to = parse_location(ctx, node_ref);
load_value_to_reg(&ctx->mcode, from, SCC_AMD64_RAX);
store_value_from_reg(&ctx->mcode, to, SCC_AMD64_RAX);
break;
}
case SCC_IR_NODE_STORE: ///< 存储数据
{
scc_reg_loc_t *from = parse_location(ctx, node->data.store.value);
scc_reg_loc_t *to = parse_location(ctx, node->data.store.target);
load_value_to_reg(&ctx->mcode, from, SCC_AMD64_RAX);
store_value_from_reg(&ctx->mcode, to, SCC_AMD64_RAX);
break;
}
case SCC_IR_NODE_GET_PTR: ///< 获取指针
case SCC_IR_NODE_GET_ELEM_PTR: ///< 获取元素指针(used by array)
TODO();
case SCC_IR_NODE_OP: ///< 二元运算
scc_reg_loc_t *loc_lhs = parse_location(ctx, node->data.op.lhs);
scc_reg_loc_t *loc_rhs = parse_location(ctx, node->data.op.rhs);
scc_reg_loc_t *loc_res = parse_location(ctx, node_ref);
// 将左操作数加载到 RAX临时结果寄存器
load_value_to_reg(&ctx->mcode, loc_lhs, SCC_AMD64_RAX);
// 将右操作数加载到 RCX
load_value_to_reg(&ctx->mcode, loc_rhs, SCC_AMD64_RCX);
switch (node->data.op.op) {
case SCC_IR_OP_ADD:
scc_mcode_amd64_add_r64_r64(&ctx->mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_SUB:
scc_mcode_amd64_sub_r64_r64(&ctx->mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_MUL:
scc_mcode_amd64_mul_r64(&ctx->mcode, SCC_AMD64_RCX);
break;
default:
LOG_FATAL("unknown op: %d", node->data.op.op);
break;
}
// 将 RAX 中的结果存储到 res 位置
store_value_from_reg(&ctx->mcode, loc_res, SCC_AMD64_RAX);
// [SCC_IR_OP_EMPTY] = "empty", [SCC_IR_OP_NEQ] = "!=",
// [SCC_IR_OP_EQ] = "==", [SCC_IR_OP_GT] = ">",
// [SCC_IR_OP_LT] = "<", [SCC_IR_OP_GE] = ">=",
// [SCC_IR_OP_LE] = "<=", [SCC_IR_OP_ADD] = "+",
// [SCC_IR_OP_SUB] = "-", [SCC_IR_OP_MUL] = "*",
// [SCC_IR_OP_DIV] = "/", [SCC_IR_OP_MOD] = "%",
// [SCC_IR_OP_AND] = "&", [SCC_IR_OP_OR] = "|",
// [SCC_IR_OP_XOR] = "^", [SCC_IR_OP_NOT] = "~",
// [SCC_IR_OP_SHL] = "<<", [SCC_IR_OP_SHR] = ">>",
// [SCC_IR_OP_SAR] = ">>a", // Arithmetic shift right
break;
case SCC_IR_NODE_BRANCH: ///< 有条件分支
case SCC_IR_NODE_JUMP: ///< 无条件跳转
case SCC_IR_NODE_CALL: ///< 调用函数
LOG_ERROR("Unsupported node type: %d", node->tag);
break;
case SCC_IR_NODE_RET: ///< 函数返回
scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RSP, SCC_AMD64_RBP);
scc_mcode_amd64_pop_r64(&ctx->mcode, SCC_AMD64_RBP);
scc_mcode_amd64_ret(&ctx->mcode);
break;
default:
UNREACHABLE();
break;
}
}
static void parse_bblock(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_t *bblock) {
// 打印基本块中的每条指令
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
scc_ir_node_ref_t node_ref = scc_vec_at(bblock->instrs, i);
parse_node(ctx, node_ref, i);
}
}
static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
scc_hashtable_t bblock2offset;
ctx->noderef2regloc = scc_reg_alloc(&ctx->reg_alloc, func);
// 对齐到 16 字节
usize stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15;
scc_mcode_amd64_push_r64(&ctx->mcode, SCC_AMD64_RBP);
scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RBP, SCC_AMD64_RSP);
scc_mcode_amd64_sub_rsp_imm32(&ctx->mcode, stack_size);
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
scc_ir_bblock_t *bblock =
scc_ir_ctx_get_bblock(ctx->ir_ctx, bblock_ref);
if (bblock == null) {
LOG_FATAL("<invalid block>\n");
return;
}
parse_bblock(ctx, bblock);
}
}
void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_with_stack, ctx->ir_ctx);
scc_vec_foreach(ctx->cprog->func_defs, i) {
scc_ir_node_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i);
scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
sccf_sym_t sym = {
.sccf_sect_offset = scc_vec_size(ctx->mcode.mcode),
.sccf_sect_type = SCCF_SECT_CODE,
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
.sccf_sym_size = 0,
.sccf_sym_type = SCCF_SYM_TYPE_FUNC,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
sccf_builder_add_symbol(&ctx->builder, func->name, &sym);
parse_function(ctx, func);
}
sccf_sect_data_t text_section;
scc_vec_unsafe_from_buffer(text_section,
scc_vec_unsafe_get_data(ctx->mcode.mcode),
scc_vec_size(ctx->mcode.mcode));
sccf_builder_add_text_section(&ctx->builder, &text_section);
sccf_sect_data_t data_section;
scc_vec_init(data_section);
sccf_builder_add_data_section(&ctx->builder, &data_section);
}