Files
scc/libs/ir2mcode/src/ir2amd64.c
zzy 694778e4a0 feat(abi): 新增ABI类型布局描述接口和Windows x64实现
- 新增scc_abi包,包含基础类型布局描述接口
- 实现Windows x64 ABI类型布局计算功能
- 定义基本类型枚举和布局信息结构体
- 提供类型布局计算的核心接口函数

refactor(ast2ir): 使用新的ABI接口替换旧的类型转换实现

- 将旧的scc_type_abi_t替换为新的scc_abi_type_calc_t
- 更新AST到IR的类型转换逻辑,使用新的ABI计算接口
- 修改上下文初始化和类型解析相关代码
- 移除废弃的头文件和相关实现

refactor(ir): 统一IR节点引用类型命名并完善构建器功能

- 将scc_ir_node_ref_vec_t重命名为scc_ir_value_ref_vec_t保持一致性
- 更新聚合类型的字段名称从elements到fields
- 添加全局变量分配构建器函数scc_ir_builder_global_alloca
- 清理构建器中多余的注释和代码
2026-04-12 11:30:31 +08:00

765 lines
30 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <amd64/scc_amd64.h>
#include <amd64/scc_amd64_abi.h>
#include <reg_alloc.h>
#include <scc_ir2mcode.h>
#include <type_manager.h>
#define GET_MODULE(ctx) (&(ctx->cprog->module))
static bool scc_type_is_signed(scc_ir_type_t *type) {
return (type->tag == SCC_IR_TYPE_i8 || type->tag == SCC_IR_TYPE_i16 ||
type->tag == SCC_IR_TYPE_i32 || type->tag == SCC_IR_TYPE_i64);
}
static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
scc_ir_value_ref_t node_ref) {
Assert(ctx != nullptr && loc != nullptr);
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
if (value == nullptr) {
LOG_FATAL("invalid value ref");
UNREACHABLE();
return;
}
usize idx = 0;
switch (value->tag) {
case SCC_IR_VALUE_TAG_CONST_INT:
scc_ir_type_t *type =
scc_ir_module_get_type(GET_MODULE(ctx), value->type);
Assert(type != 0);
switch (type->tag) {
case SCC_IR_TYPE_u8:
case SCC_IR_TYPE_i8:
*loc = (scc_reg_loc_t){
.kind = SCC_REG_KIND_IMM,
.data.data = (usize)value->data.const_int.int8,
};
break;
case SCC_IR_TYPE_u16:
case SCC_IR_TYPE_i16:
*loc = (scc_reg_loc_t){
.kind = SCC_REG_KIND_IMM,
.data.data = (usize)value->data.const_int.int16,
};
break;
case SCC_IR_TYPE_u32:
case SCC_IR_TYPE_i32:
*loc = (scc_reg_loc_t){
.kind = SCC_REG_KIND_IMM,
.data.data = (usize)value->data.const_int.int32,
};
break;
case SCC_IR_TYPE_u64:
case SCC_IR_TYPE_i64:
*loc = (scc_reg_loc_t){
.kind = SCC_REG_KIND_IMM,
.data.data = (usize)value->data.const_int.int64,
};
break;
default:
break;
}
return;
case SCC_IR_VALUE_TAG_CONST_UINT:
case SCC_IR_VALUE_TAG_CONST_FLOAT:
TODO();
break;
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC:
TODO();
break;
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
case SCC_IR_VALUE_TAG_ALLOC:
default:
idx = (usize)scc_hashtable_get(ctx->noderef2regloc,
(void *)(usize)node_ref);
break;
}
Assert(idx > 0 && idx <= scc_vec_size(ctx->reg_alloc.loc_vec));
*loc = scc_vec_at(ctx->reg_alloc.loc_vec, idx - 1);
}
static void load_value_to_reg(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
int reg) {
scc_mcode_t *mcode = &ctx->sect_mcode;
switch (loc->kind) {
case SCC_REG_KIND_GPR:
if (loc->data.gpr_idx != reg) {
scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->data.gpr_idx);
} else {
TODO();
}
break;
case SCC_REG_KIND_STACK:
scc_mcode_amd64_mov_r64_m64_disp32(
mcode, reg, SCC_AMD64_RBP,
scc_reg_stack_offset(&ctx->reg_alloc, loc));
break;
case SCC_REG_KIND_STACK_ADDR:
// 将栈地址加载到寄存器(取地址)
scc_mcode_amd64_lea_r64_m64_disp32(
mcode, reg, SCC_AMD64_RBP,
scc_reg_stack_offset(&ctx->reg_alloc, loc));
break;
case SCC_REG_KIND_IMM:
scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->data.data); // 或 imm32
break;
default:
LOG_FATAL("unsupported location");
}
}
static void store_value_from_reg(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
int reg) {
scc_mcode_t *mcode = &ctx->sect_mcode;
switch (loc->kind) {
case SCC_REG_KIND_GPR:
if (loc->data.gpr_idx != reg) {
scc_mcode_amd64_mov_r64_r64(mcode, loc->data.gpr_idx, reg);
}
break;
case SCC_REG_KIND_STACK:
scc_mcode_amd64_mov_m64_disp32_r64(
mcode, SCC_AMD64_RBP, scc_reg_stack_offset(&ctx->reg_alloc, loc),
reg);
break;
case SCC_REG_KIND_STACK_ADDR:
// 将寄存器的值存储到栈地址
scc_mcode_amd64_mov_m64_disp32_r64(
mcode, SCC_AMD64_RBP, scc_reg_stack_offset(&ctx->reg_alloc, loc),
reg);
break;
case SCC_REG_KIND_IMM:
LOG_FATAL("cannot store to immediate");
break;
default:
Panic("unsupported location %d", loc->kind);
break;
}
}
// 临时存储待修补条目
typedef struct patch {
usize pos;
usize target_bb_ref;
} patch_t;
typedef SCC_VEC(patch_t) patch_vec_t;
static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
patch_vec_t *patches) {
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
if (value == nullptr) {
LOG_ERROR("invalid value ref");
return;
}
switch (value->tag) {
case SCC_IR_VALUE_TAG_BUILTIN: {
scc_ir_builtin_t *builtin = &value->data.builtin;
switch (builtin->tag) {
case SCC_IR_BUILTIN_TAG_MEMCPY: {
// 1. 获取操作数的位置
scc_reg_loc_t dest_loc, src_loc, size_loc;
parse_location(ctx, &dest_loc, builtin->func.memcpy.dest);
parse_location(ctx, &src_loc, builtin->func.memcpy.src);
scc_ir_value_t *const_value = scc_ir_module_get_value(
GET_MODULE(ctx), builtin->func.memcpy.size);
Assert(const_value->tag == SCC_IR_VALUE_TAG_CONST_INT);
size_loc.kind = SCC_REG_KIND_IMM;
size_loc.data.data = const_value->data.const_int.int64;
// 2. 将 dest 地址加载到 RDIrep movsb 目标)
load_value_to_reg(ctx, &dest_loc, SCC_AMD64_RDI);
// 3. 将 src 地址加载到 RSI
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RSI);
// 4. 将长度加载到 RCX
load_value_to_reg(ctx, &size_loc, SCC_AMD64_RCX);
// 5. 如果长度可能为 0可以跳过但 rep movsb 处理 0
// 也没问题,只是多一次指令。 生成 rep movsb 指令(字节复制)
// 需要使用 REX.W 前缀保证 64 位操作,但 rep movsb 本身不需要 REX.W
// 为了复制字节,使用 rep movsb (0xF3 0xA4)
scc_mcode_add_u8(&ctx->sect_mcode, 0xF3); // rep prefix
scc_mcode_add_u8(&ctx->sect_mcode, 0xA4); // movsb
break;
}
default:
Panic("unsupported builtin");
}
break;
}
case SCC_IR_VALUE_TAG_CONV: ///< 类型转换
LOG_FATAL("Unsupported value type: %d", value->tag);
break;
///< 函数参数引用
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
///< ABI
break;
case SCC_IR_VALUE_TAG_BLOCK_ARG_REF: ///< 基本块参数引用
break;
case SCC_IR_VALUE_TAG_ALLOC: ///< 分配内存(stack)
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: ///< 全局分配(bss
break;
///< 加载数据
case SCC_IR_VALUE_TAG_LOAD: {
// value->data.load.target
scc_reg_loc_t from;
scc_reg_loc_t to;
parse_location(ctx, &from, value->data.load.target);
parse_location(ctx, &to, node_ref);
load_value_to_reg(ctx, &from, SCC_AMD64_RCX);
// 获取基类型宽度
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
GET_MODULE(ctx), value->data.load.target);
scc_ir_type_t *base_type = scc_ir_module_get_type(
GET_MODULE(ctx), ptr_type->data.pointer.base);
int width = scc_ir2mcode_type_width(GET_MODULE(ctx), base_type);
bool is_signed = scc_type_is_signed(base_type);
// 间接加载到 RAX
if (width == 1) {
if (is_signed)
scc_mcode_amd64_movsx_r64_m8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
else
scc_mcode_amd64_movzx_r64_m8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
} else if (width == 2) {
if (is_signed)
scc_mcode_amd64_movsx_r64_m16(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
else
scc_mcode_amd64_movzx_r64_m16(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
} else if (width == 4) {
if (is_signed)
scc_mcode_amd64_movsx_r64_m32(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
else
scc_mcode_amd64_mov_r32_m32(
&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX); // 32位加载自动清零高位
} else if (width == 8) { // 8
scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
} else {
LOG_WARN("unsupported type width: %d", width);
scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
}
// 存储结果
store_value_from_reg(ctx, &to, SCC_AMD64_RAX);
break;
}
///< 存储数据
case SCC_IR_VALUE_TAG_STORE: {
scc_reg_loc_t val_loc, addr_loc;
parse_location(ctx, &val_loc, value->data.store.value);
parse_location(ctx, &addr_loc, value->data.store.target);
// 将值加载到 RAX
load_value_to_reg(ctx, &val_loc, SCC_AMD64_RAX);
// 将目标地址加载到 RCX
load_value_to_reg(ctx, &addr_loc, SCC_AMD64_RCX);
// 获取目标指针的基类型宽度
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
GET_MODULE(ctx), value->data.store.target);
scc_ir_type_t *base_type = scc_ir_module_get_type(
GET_MODULE(ctx), ptr_type->data.pointer.base);
int width = scc_ir2mcode_type_width(GET_MODULE(ctx), base_type);
// 根据宽度生成存储指令
if (width == 1) {
scc_mcode_amd64_mov_m8_r8(&ctx->sect_mcode, SCC_AMD64_RCX,
SCC_AMD64_RAX);
} else if (width == 2) {
scc_mcode_amd64_mov_m16_r16(&ctx->sect_mcode, SCC_AMD64_RCX,
SCC_AMD64_RAX);
} else if (width == 4) {
scc_mcode_amd64_mov_m32_r32(&ctx->sect_mcode, SCC_AMD64_RCX,
SCC_AMD64_RAX);
} else { // width == 8
scc_mcode_amd64_mov_m64_r64(&ctx->sect_mcode, SCC_AMD64_RCX,
SCC_AMD64_RAX);
}
break;
}
///< 获取指针
case SCC_IR_VALUE_TAG_GET_ELEM_PTR: {
scc_reg_loc_t loc_res;
parse_location(ctx, &loc_res, node_ref);
scc_ir_value_t *src_addr = scc_ir_module_get_value(
GET_MODULE(ctx), value->data.get_elem_ptr.src_addr);
Assert(src_addr != nullptr);
if (value->data.get_elem_ptr.index == 0) {
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
// 全局变量RIP相对寻址
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode,
SCC_AMD64_RAX, 0);
usize sym_idx =
sccf_builder_get_symbol_idx(ctx->builder, src_addr->name);
Assert(sym_idx != 0);
sccf_builder_add_reloc(
ctx->builder,
(sccf_reloc_t){
.reloc_type = SCCF_RELOC_TYPE_REL,
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
.addend = 4,
.sect_type = SCCF_SECT_CODE,
.sym_idx = sym_idx,
});
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
// 栈上变量:地址为 rbp - offset
scc_reg_loc_t src_loc;
parse_location(ctx, &src_loc,
value->data.get_elem_ptr.src_addr);
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
} else {
// 其他情况如链式getptr源地址值已经存储在某个位置直接加载到
// RAX
scc_reg_loc_t src_loc;
parse_location(ctx, &src_loc,
value->data.get_elem_ptr.src_addr);
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
}
} else {
// TODO
parse_value(ctx, value->data.get_elem_ptr.index, patches);
scc_reg_loc_t src_loc;
scc_reg_loc_t idx_loc;
parse_location(ctx, &src_loc, value->data.get_elem_ptr.src_addr);
parse_location(ctx, &idx_loc, value->data.get_elem_ptr.index);
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
load_value_to_reg(ctx, &idx_loc, SCC_AMD64_RDX);
scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX, SCC_AMD64_RDX, 1, 0);
}
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
break;
}
///< 二元运算
case SCC_IR_VALUE_TAG_OP: {
scc_reg_loc_t loc_lhs;
parse_location(ctx, &loc_lhs, value->data.op.lhs);
scc_reg_loc_t loc_rhs;
parse_location(ctx, &loc_rhs, value->data.op.rhs);
scc_reg_loc_t loc_res;
parse_location(ctx, &loc_res, node_ref);
// 将左操作数加载到 RAX临时结果寄存器
load_value_to_reg(ctx, &loc_lhs, SCC_AMD64_RAX);
// 将右操作数加载到 RCX
load_value_to_reg(ctx, &loc_rhs, SCC_AMD64_RCX);
switch (value->data.op.op) {
case SCC_IR_OP_EMPTY:
Panic("unsupported empty op");
break;
case SCC_IR_OP_ADD:
scc_mcode_amd64_add_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_SUB:
scc_mcode_amd64_sub_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_MUL:
scc_mcode_amd64_mul_r64(&ctx->sect_mcode, SCC_AMD64_RCX);
break;
case SCC_IR_OP_DIV:
case SCC_IR_OP_MOD:
TODO();
break;
case SCC_IR_OP_AND:
scc_mcode_amd64_and_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_OR:
scc_mcode_amd64_or_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_XOR:
scc_mcode_amd64_xor_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
break;
case SCC_IR_OP_NOT:
scc_mcode_amd64_not_r64(&ctx->sect_mcode, SCC_AMD64_RAX);
break;
case SCC_IR_OP_SHL:
case SCC_IR_OP_SHR:
case SCC_IR_OP_SAR:
TODO();
break;
case SCC_IR_OP_NEQ:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_NE,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_EQ:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_E,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_GT:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_G,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_LT:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_L,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_GE:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_GE,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
case SCC_IR_OP_LE:
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_LE,
SCC_AMD64_RAX);
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX);
break;
default:
LOG_FATAL("unknown op: %d", value->data.op.op);
break;
}
// 将 RAX 中的结果存储到 res 位置
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
break;
}
///< 有条件分支
case SCC_IR_VALUE_TAG_BRANCH: {
scc_reg_loc_t loc;
parse_location(ctx, &loc, value->data.branch.cond);
// (void)loc;
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
scc_mcode_amd64_cmp_r64_imm32(&ctx->sect_mcode, SCC_AMD64_RAX, 0);
scc_mcode_amd64_jcc_rel32(&ctx->sect_mcode, SCC_AMD64_COND_NE, 0);
patch_t patch_true = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
.target_bb_ref =
(usize)value->data.branch.true_bblock};
scc_vec_push(*patches, patch_true);
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
patch_t patch_false = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
.target_bb_ref =
(usize)value->data.branch.false_bblock};
scc_vec_push(*patches, patch_false);
break;
}
///< 无条件跳转
case SCC_IR_VALUE_TAG_JUMP: {
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
usize pos = scc_vec_size(ctx->sect_mcode.mcode);
patch_t patch = {
.pos = pos, .target_bb_ref = (usize)value->data.jump.target_bblock};
scc_vec_push(*patches, patch);
break;
}
///< 调用函数
case SCC_IR_VALUE_TAG_CALL: {
scc_reg_loc_t loc;
/*
ABI
RAX 不稳定的 返回值寄存器
RCX 不稳定的 第一个整型自变量
RDX 不稳定的 第二个整型自变量
R8 不稳定的 第三个整型自变量
R9 不稳定的 第四个整型自变量
*/
scc_vec_foreach(value->data.call.args, i) {
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
if (i == 0) {
load_value_to_reg(ctx, &loc, SCC_AMD64_RCX);
} else if (i == 1) {
load_value_to_reg(ctx, &loc, SCC_AMD64_RDX);
} else if (i == 2) {
load_value_to_reg(ctx, &loc, SCC_AMD64_R8);
} else if (i == 3) {
load_value_to_reg(ctx, &loc, SCC_AMD64_R9);
} else {
LOG_FATAL("not support more than 4 args");
}
// scc_mcode_amd64_push_r64();
}
scc_ir_func_t *func =
scc_ir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
// FIXME hack func value
if (scc_vec_size(func->bblocks)) {
scc_mcode_amd64_call_rel32(&ctx->sect_mcode, 0);
} else {
scc_mcode_amd64_call_mem_rip_rel32(&ctx->sect_mcode, 0);
}
usize sym_idx = sccf_builder_get_symbol_idx(ctx->builder, func->name);
Assert(sym_idx != 0);
sccf_builder_add_reloc(
ctx->builder, (sccf_reloc_t){
.reloc_type = SCCF_RELOC_TYPE_REL,
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
.addend = 4,
.sect_type = SCCF_SECT_CODE,
.sym_idx = sym_idx,
});
// 处理返回值
scc_ir_type_t *func_type =
scc_ir_module_get_type(GET_MODULE(ctx), func->type);
Assert(func_type);
scc_ir_type_t *ret_type = scc_ir_module_get_type(
GET_MODULE(ctx), func_type->data.function.ret_type);
if (ret_type && ret_type->tag != SCC_IR_TYPE_void) {
parse_location(ctx, &loc, node_ref);
store_value_from_reg(ctx, &loc, SCC_AMD64_RAX);
}
break;
}
///< 函数返回
case SCC_IR_VALUE_TAG_RET: {
if (value->data.ret.ret_val) {
scc_reg_loc_t loc;
parse_location(ctx, &loc, value->data.ret.ret_val);
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
}
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, ctx->stack_size);
scc_mcode_amd64_pop_r64(&ctx->sect_mcode, SCC_AMD64_RBP);
scc_mcode_amd64_ret(&ctx->sect_mcode);
break;
}
default:
LOG_FATAL("unknown value type: %d", value->tag);
UNREACHABLE();
break;
}
}
static void parse_bblock(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_t *bblock,
patch_vec_t *patches) {
// 打印基本块中的每条指令
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, i);
parse_value(ctx, node_ref, patches);
}
}
static u32 hash_func(const void *key) { return (u32)(usize)key; }
static int equal_func(const void *key1, const void *key2) {
return (usize)key1 - (usize)key2;
}
const scc_frame_alloc_ops_t *scc_frame_alloc_win64_ops(void);
static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
// FIXME using other
ctx->noderef2regloc =
scc_reg_alloc_run(&ctx->reg_alloc, func, scc_frame_alloc_win64_ops());
ctx->stack_size = scc_reg_stack_size(&ctx->reg_alloc);
Assert(ctx->noderef2regloc);
usize bblock_cnt = scc_vec_size(func->bblocks);
usize *bblock_offsets = scc_calloc(bblock_cnt, sizeof(usize));
// 建立 bblock_ref -> id 的映射
scc_hashtable_t ref2id;
scc_hashtable_init(&ref2id, hash_func, equal_func);
for (usize i = 0; i < bblock_cnt; i++) {
scc_ir_bblock_ref_t ref = scc_vec_at(func->bblocks, i);
scc_hashtable_set(&ref2id, (void *)(usize)ref, (void *)i);
}
patch_vec_t patches;
scc_vec_init(patches);
scc_mcode_amd64_push_r64(&ctx->sect_mcode, SCC_AMD64_RBP);
scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, ctx->stack_size);
scc_mcode_amd64_lea_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RBP,
SCC_AMD64_RSP, ctx->stack_size);
scc_reg_loc_t loc;
scc_vec_foreach(func->params, i) {
// scc_ir_value_t *param =
// scc_ir_module_get_value(GET_MODULE(ctx), );
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
parse_location(ctx, &loc, node_ref);
if (i == 0) {
store_value_from_reg(ctx, &loc, SCC_AMD64_RCX);
} else if (i == 1) {
store_value_from_reg(ctx, &loc, SCC_AMD64_RDX);
} else if (i == 2) {
store_value_from_reg(ctx, &loc, SCC_AMD64_R8);
} else if (i == 3) {
store_value_from_reg(ctx, &loc, SCC_AMD64_R9);
} else {
LOG_FATAL("not support more than 4 args");
}
// scc_mcode_amd64_push_r64();
}
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_module_get_bblock(GET_MODULE(ctx), bblock_ref);
if (bblock == nullptr) {
LOG_FATAL("<invalid block>\n");
return;
}
bblock_offsets[i] = scc_vec_size(ctx->sect_mcode.mcode);
parse_bblock(ctx, bblock, &patches);
}
// 回填所有跳转偏移
u8 *buf = scc_vec_unsafe_get_data(ctx->sect_mcode.mcode);
scc_vec_foreach(patches, idx) {
patch_t *p = &scc_vec_at(patches, idx);
usize target_id =
(usize)scc_hashtable_get(&ref2id, (void *)(usize)p->target_bb_ref);
usize target_off = bblock_offsets[target_id];
usize next_off = p->pos;
i32 rel = (i32)(target_off - next_off);
// FIXME 写入到指令的偏移字段(小端)
*(u32 *)(&buf[p->pos - 4]) = rel;
}
scc_free(bblock_offsets);
scc_vec_free(patches);
scc_hashtable_drop(&ref2id);
}
void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_strategy_pure_stack,
GET_MODULE(ctx));
scc_vec_foreach(ctx->cprog->global_vals, i) {
scc_ir_value_t *galloc = scc_ir_module_get_value(
GET_MODULE(ctx), scc_vec_at(ctx->cprog->global_vals, i));
Assert(galloc->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC);
scc_ir_value_t *value = scc_ir_module_get_value(
GET_MODULE(ctx), galloc->data.global_alloc.value);
Assert(value != nullptr);
sccf_sym_t sym = (sccf_sym_t){
.sccf_sect_offset = scc_vec_size(ctx->sect_data),
.sccf_sect_type = SCCF_SECT_DATA,
.sccf_sym_bind =
galloc->name ? SCCF_SYM_BIND_GLOBAL : SCCF_SYM_BIND_LOCAL,
.sccf_sym_size =
4, // FIXME on windows using rel32, on linux using ?
.sccf_sym_type = SCCF_SYM_TYPE_DATA,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
scc_vec_foreach(value->data.const_array.fields, j) {
scc_vec_push(ctx->sect_data,
scc_vec_at(value->data.const_array.fields, j));
}
usize sym_idx =
sccf_builder_add_symbol(ctx->builder, galloc->name, &sym);
Assert(sym_idx != 0);
}
scc_vec_foreach(ctx->cprog->func_decls, i) {
scc_ir_value_ref_t func_ref = scc_vec_at(ctx->cprog->func_decls, i);
scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
sccf_sym_t sym = {0};
if (scc_vec_size(func->bblocks)) {
sym = (sccf_sym_t){
.sccf_sect_offset = 0,
.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,
};
} else {
sym = (sccf_sym_t){
.sccf_sect_offset = 0,
.sccf_sect_type = SCCF_SECT_NONE,
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
.sccf_sym_size = 0,
.sccf_sym_type = SCCF_SYM_TYPE_EXTERN,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
}
usize sym_idx = sccf_builder_add_symbol(ctx->builder, func->name, &sym);
Assert(sym_idx != 0);
}
scc_vec_foreach(ctx->cprog->func_defs, i) {
scc_ir_value_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i);
scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
sccf_sym_t *sym =
sccf_builder_get_symbol_unsafe(ctx->builder, func->name);
Assert(sym != nullptr);
sym->sccf_sect_offset = scc_vec_size(ctx->sect_mcode.mcode);
parse_function(ctx, func);
}
u8 *buf = scc_vec_unsafe_get_data(ctx->sect_mcode.mcode);
scc_vec_foreach(ctx->builder->relocs, i) {
sccf_reloc_t *reloc = &scc_vec_at(ctx->builder->relocs, i);
if (reloc->sym_idx == 0) {
Panic("relocate to an invalid symbol");
}
sccf_sym_t *sym = &scc_vec_at(ctx->builder->symtab, reloc->sym_idx);
if (sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN) {
Assert(reloc->reloc_type == SCCF_RELOC_TYPE_REL);
if (sym->sccf_sect_type == SCCF_SECT_CODE &&
sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC) {
i64 target_off = sym->sccf_sect_offset;
i64 next_off = reloc->offset + reloc->addend;
i32 rel = (i32)(target_off - next_off);
// FIXME 写入到指令的偏移字段(小端)
*(i32 *)(&buf[reloc->offset]) = rel;
reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
}
}
}
sccf_sect_data_t text_section;
scc_vec_unsafe_from_buffer(text_section,
scc_vec_unsafe_get_data(ctx->sect_mcode.mcode),
scc_vec_size(ctx->sect_mcode.mcode));
sccf_builder_add_text_section(ctx->builder, &text_section);
sccf_builder_add_data_section(ctx->builder, &ctx->sect_data);
// FIXME maybe _entry and add crt
ctx->builder->entry_symbol_name = "main";
}