- 新增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 - 清理构建器中多余的注释和代码
765 lines
30 KiB
C
765 lines
30 KiB
C
#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 地址加载到 RDI(rep 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";
|
||
}
|