feat(lir): 修改HIR到LIR转换以支持可变参数函数

- 移除SCC_LIR_LEA指令类型,改用SCC_LIR_LOAD_ADDR
- 在scc_lir_func_meta_t中添加is_va_arg字段用于标识可变参数函数
- 修改scc_hir2lir函数参数类型,移除const限定符
- 更新比较操作的指令映射逻辑,将条件信息存储在metadata中
- 调整代码结构,在各个switch case分支中统一使用"} break"格式

fix(x86-isel): 修复x86指令选择中的立即数和重定位处理

- 修改emit_direct_call函数以正确处理全局符号重定位
- 更新立即数字段访问从imm到imm0
- 添加新的重定位操作数类型SCC_X86_OPR_RELOC
- 实现重定位目标类型的完整处理逻辑,包括基本块和符号

refactor(x86-mir): 重构x86操作数结构以支持重定位机制

- 将内存操作数的disp字段改为结构体形式包含displacement信息
- 移除不再使用的常用操作数构造器函数
- 保留并完善slot操作数构造器
- 更新内存操作数的调试输出格式

feat(ir2mcode): 添加重定位表支持以处理符号引用

- 定义新的重定位结构体scc_reloc_t用于记录重定位信息
- 修改scc_ir2mcode_emit_instr函数签名以传递重定位表
- 实现重定位补丁应用功能scc_ir2mcode_patch
- 更新机器码生成流程以收集和处理重定位信息

refactor(ir2sccf): 重构SCEF文件生成以支持重定位处理

- 提取独立的emit_mir_module函数处理MIR模块的机器码生成
- 实现基本块间重定位的地址解析和补丁应用
- 改进符号重定位的处理机制
- 简化机器码段数据的最终处理流程
This commit is contained in:
zzy
2026-05-21 16:19:49 +08:00
parent aa4292a30e
commit 41d060d7e7
19 changed files with 608 additions and 227 deletions

View File

@@ -32,17 +32,34 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) {
scc_tree_dump_append_fmt(td, "$%s", preg_name(op->reg));
break;
case SCC_X86_OPR_IMM:
scc_tree_dump_append_fmt(td, "%ld", op->imm);
scc_tree_dump_append_fmt(td, "%ld", op->imm0);
break;
case SCC_X86_OPR_MEM:
if (scc_x86_op_is_slot(op))
scc_tree_dump_append_fmt(td, "[slot:%d]",
scc_x86_op_slot_id(op));
else
scc_tree_dump_append_fmt(td, "[sp%+d]", op->mem.disp);
scc_tree_dump_append_fmt(
td, "[sp %c %llu]",
op->mem.disp.displacement >= 0 ? '+' : '-',
op->mem.disp.displacement < 0 ? -op->mem.disp.displacement
: op->mem.disp.displacement);
break;
case SCC_X86_OPR_RELBR:
scc_tree_dump_append(td, "label");
scc_tree_dump_append(td, "<relbr>");
break;
case SCC_X86_OPR_RELOC:
switch (op->reloc.target) {
case SCC_X86_RELOC_TARGET_BBLOCK:
scc_tree_dump_append_fmt(td, "<#BB%d>", op->reloc.bblock_id);
break;
case SCC_X86_RELOC_TARGET_SYMBOL:
scc_tree_dump_append_fmt(td, "<%s>", op->reloc.global_name);
break;
default:
scc_tree_dump_append_fmt(td, "<reloc>");
break;
}
break;
default:
break;
@@ -75,7 +92,8 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
op = scc_x86_op_imm(*(i64 *)&val->data.fimm);
break;
case SCC_LIR_INSTR_KIND_SYMBOL:
op = scc_x86_op_symbol(val->data.symbol);
// 默认作为绝对地址立即数(后续可优化为 RIP 相对)
op = scc_x86_op_reloc_global_imm(val->data.symbol, 0);
break;
case SCC_LIR_INSTR_KIND_ARG:
Assert(isel->abi_lowering.lower_param);
@@ -94,33 +112,41 @@ static scc_x86_operand_value_t new_vreg_temp(scc_x86_64_isel_t *isel) {
void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
scc_x86_operand_value_t src, u8 size) {
scc_x86_operand_kind_t dst_kind = dst.kind;
if (dst_kind == SCC_X86_OPR_RELOC) {
dst_kind = dst.reloc.kind;
}
scc_x86_operand_kind_t src_kind = src.kind;
if (src_kind == SCC_X86_OPR_RELOC) {
src_kind = src.reloc.kind;
}
if (dst.kind == SCC_X86_OPR_REG) {
if (src.kind == SCC_X86_OPR_REG) {
if (dst_kind == SCC_X86_OPR_REG) {
if (src_kind == SCC_X86_OPR_REG) {
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_8B, dst, src);
} else if (src.kind == SCC_X86_OPR_IMM) {
} else if (src_kind == SCC_X86_OPR_IMM) {
add_instr_2(isel,
(size == 8) ? SCC_X86_IFORM_MOV_GPRV_IMMZ
: SCC_X86_IFORM_MOV_GPRV_IMMV,
dst, src);
} else if (src.kind == SCC_X86_OPR_IMM && src.imm == 0) {
} else if (src_kind == SCC_X86_OPR_IMM && src.imm0 == 0) {
// 特殊:符号作为立即数地址
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, dst, src);
} else if (src.kind == SCC_X86_OPR_MEM) {
} else if (src_kind == SCC_X86_OPR_MEM) {
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src);
} else {
UNREACHABLE();
}
} else if (dst.kind == SCC_X86_OPR_MEM) {
if (src.kind == SCC_X86_OPR_REG) {
} else if (dst_kind == SCC_X86_OPR_MEM) {
if (src_kind == SCC_X86_OPR_REG) {
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, src);
} else if (src.kind == SCC_X86_OPR_IMM) {
} else if (src_kind == SCC_X86_OPR_IMM) {
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_IMMZ, dst, src);
} else if (src.kind == SCC_X86_OPR_IMM) {
} else if (src_kind == SCC_X86_OPR_IMM) {
scc_x86_operand_value_t temp = new_vreg_temp(isel);
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, temp, src);
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, temp);
} else if (src.kind == SCC_X86_OPR_MEM) {
} else if (src_kind == SCC_X86_OPR_MEM) {
scc_x86_operand_value_t temp = new_vreg_temp(isel);
scc_x86_emit_move(isel, temp, src, size);
scc_x86_emit_move(isel, dst, temp, size);
@@ -217,16 +243,6 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op,
add_instr_2(isel, iform, dst, src1);
}
static void emit_spill_load(scc_x86_64_isel_t *isel, int vreg, int slot) {
scc_x86_operand_value_t dst = scc_x86_op_vreg(vreg);
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, scc_x86_op_slot(slot));
}
static void emit_spill_store(scc_x86_64_isel_t *isel, int vreg, int slot) {
scc_x86_operand_value_t src = scc_x86_op_vreg(vreg);
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, scc_x86_op_slot(slot), src);
}
static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
scc_x86_operand_value_t dst = scc_x86_lir_val_to_mir_op(isel, &instr->to);
scc_x86_operand_value_t src0 =
@@ -241,17 +257,16 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
scc_x86_emit_move(isel, dst, src0, size);
break;
case SCC_LIR_LOAD:
// TODO check valid
scc_x86_emit_move(isel, dst, src0, size);
break;
case SCC_LIR_STORE:
// TODO check valid
scc_x86_emit_move(isel, src1, src0, size);
break;
case SCC_LIR_STORE_ADDR:
TODO();
break;
case SCC_LIR_LEA:
case SCC_LIR_LOAD_ADDR:
add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0);
break;
@@ -374,9 +389,9 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
/* ---- 条件分支 ---- */
case SCC_LIR_BR: {
scc_x86_operand_value_t true_bb =
scc_x86_op_block(instr->metadata.br.true_target);
scc_x86_op_reloc_block(instr->metadata.br.true_target, 0);
scc_x86_operand_value_t false_bb =
scc_x86_op_block(instr->metadata.br.false_target);
scc_x86_op_reloc_block(instr->metadata.br.false_target, 0);
add_instr_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0);
add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb);
@@ -385,7 +400,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
case SCC_LIR_JMP: {
scc_x86_operand_value_t jmp_bb =
scc_x86_op_block(instr->metadata.jmp_target);
scc_x86_op_reloc_block(instr->metadata.jmp_target, 0);
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb);
} break;
@@ -458,6 +473,7 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module,
Assert(func_meta != nullptr);
scc_mir_func_meta_init(func_meta);
func_meta->vregs_count = SCC_LIR_FUNC_META(func)->vregs_count;
func_meta->need_va_args = SCC_LIR_FUNC_META(func)->is_va_arg;
func->meta = func_meta;
isel->func = func;

View File

@@ -29,8 +29,13 @@ static void frame_alloc_impl(scc_frame_layout_t *ctx,
ctx->offset += slot->size;
slot->offset = ctx->offset;
}
op->mem.base = SCC_X86_REG_RSP;
op->mem.disp = -slot->offset;
*op = scc_x86_op_mem((scc_x86_mem_t){
.seg = SCC_X86_REG_INVALID,
.base = SCC_X86_REG_RSP,
.disp = {.displacement = -slot->offset},
.index = SCC_X86_REG_INVALID,
.scale = 1,
});
}
}
}