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:
@@ -5,30 +5,91 @@
|
||||
#include <arch/scc_x86_mir.h>
|
||||
#include <x86/scc_x86_encode.h>
|
||||
#include <x86/scc_x86_iform.h>
|
||||
#include <x86/scc_x86_patch.h>
|
||||
#include <x86/scc_x86_reg.h>
|
||||
|
||||
void mir_x86_to_mcode(scc_mcode_t *mcode, const scc_mir_x86_instr_t *_ins) {
|
||||
void mir_x86_to_mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||
const scc_mir_x86_instr_t *_ins) {
|
||||
Assert(mcode != nullptr && _ins != nullptr);
|
||||
int skip_reloc = relocs == nullptr;
|
||||
scc_x86_instr_t *ins = (void *)_ins;
|
||||
if (ins->opcode < 0 || ins->opcode >= SCC_X86_IFORM_COUNT) {
|
||||
return;
|
||||
}
|
||||
scc_x86_operand_value_t ops[8] = {0};
|
||||
scc_reloc_t reloc = {0};
|
||||
for (int i = 0; i < ins->num_operands; i++) {
|
||||
if (scc_x86_op_is_vreg(&ins->operands[i]))
|
||||
scc_x86_operand_value_t *op_ptr = &ins->operands[i];
|
||||
if (scc_x86_op_is_vreg(op_ptr))
|
||||
Panic("can't convert vreg to mcode");
|
||||
if (scc_x86_op_is_slot(&ins->operands[i]))
|
||||
if (scc_x86_op_is_slot(op_ptr))
|
||||
Panic("can't convert unresolved slot to mcode");
|
||||
ops[i] = ins->operands[i];
|
||||
ops[i] = *op_ptr;
|
||||
if (op_ptr->kind == SCC_X86_OPR_RELOC) {
|
||||
ops[i].kind = op_ptr->reloc.kind;
|
||||
switch (op_ptr->reloc.kind) {
|
||||
case SCC_X86_OPR_RELBR:
|
||||
ops[i].imm0 = 0;
|
||||
break;
|
||||
default:
|
||||
TODO();
|
||||
break;
|
||||
}
|
||||
if (skip_reloc) {
|
||||
continue;
|
||||
}
|
||||
if (skip_reloc != SCC_RELOC_TARGET_NONE) {
|
||||
LOG_FATAL("can't using twice reloc in one instr");
|
||||
continue;
|
||||
}
|
||||
reloc.addend = op_ptr->reloc.addend;
|
||||
reloc.arch_type = (int)op_ptr->reloc.kind;
|
||||
reloc.size = 0;
|
||||
reloc.offset = scc_mcode_size(mcode);
|
||||
if (op_ptr->reloc.target == SCC_X86_RELOC_TARGET_SYMBOL) {
|
||||
reloc.target_kind = SCC_RELOC_TARGET_SYMBOL;
|
||||
reloc.symbol = op_ptr->reloc.global_name;
|
||||
} else if (op_ptr->reloc.target == SCC_X86_RELOC_TARGET_BBLOCK) {
|
||||
reloc.target_kind = SCC_RELOC_TARGET_BBLOCK;
|
||||
reloc.bblock_id = op_ptr->reloc.bblock_id;
|
||||
} else {
|
||||
TODO();
|
||||
}
|
||||
}
|
||||
}
|
||||
scc_x86_encode_inst(mcode, ins->opcode, ops);
|
||||
if (!skip_reloc && reloc.target_kind != SCC_RELOC_TARGET_NONE) {
|
||||
reloc.offset = scc_mcode_size(mcode);
|
||||
scc_vec_push(*relocs, reloc);
|
||||
}
|
||||
}
|
||||
|
||||
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode,
|
||||
void mir_x86_patch(scc_mcode_t *mcode, scc_reloc_t *reloc, i64 value) {
|
||||
// return;
|
||||
scc_x86_patch_type_t patch_type = SCC_X86_PATCH_NONE;
|
||||
switch (reloc->arch_type) {
|
||||
case SCC_X86_OPR_RELBR:
|
||||
patch_type = SCC_X86_PATCH_PC32;
|
||||
break;
|
||||
default:
|
||||
Panic("unsupported reloc type");
|
||||
break;
|
||||
}
|
||||
scc_x86_patch(mcode, patch_type, reloc->offset + reloc->addend, value);
|
||||
}
|
||||
|
||||
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||
const scc_mir_instr_t *mir_instr) {
|
||||
mir_x86_to_mcode(mcode, (const scc_mir_x86_instr_t *)mir_instr);
|
||||
mir_x86_to_mcode(mcode, relocs, (const scc_mir_x86_instr_t *)mir_instr);
|
||||
}
|
||||
|
||||
void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) {
|
||||
void scc_ir2mcode_patch(scc_mcode_t *mcode, scc_reloc_t *reloc, i64 value) {
|
||||
mir_x86_patch(mcode, reloc, value);
|
||||
}
|
||||
|
||||
void scc_ir2mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||
const scc_mir_module_t *mir_module) {
|
||||
Assert(mir_module != nullptr && mcode != nullptr);
|
||||
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
@@ -42,7 +103,7 @@ void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) {
|
||||
scc_vec_foreach(*instrs, i) {
|
||||
const scc_mir_instr_t *ins =
|
||||
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
||||
scc_ir2mcode_emit_instr(mcode, ins);
|
||||
scc_ir2mcode_emit_instr(mcode, relocs, ins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,70 @@ static inline void scc_ir_symbol_to_sect_data(const scc_cfg_symbol_t *symbol,
|
||||
// }
|
||||
}
|
||||
|
||||
static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode,
|
||||
scc_mir_module_t *mir_module) {
|
||||
|
||||
scc_hashtable_t bblock_offset;
|
||||
|
||||
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
scc_mir_func_t *func = &scc_vec_at(mir_module->cfg_module.funcs, i);
|
||||
|
||||
sccf_sym_t *sym = sccf_builder_get_symbol_unsafe(builder, func->name);
|
||||
Assert(sym != nullptr);
|
||||
sym->sccf_sect_offset = scc_mcode_size(mcode);
|
||||
|
||||
scc_hashtable_usize_init(&bblock_offset);
|
||||
scc_reloc_vec_t relocs;
|
||||
scc_vec_init(relocs);
|
||||
scc_vec_foreach(func->bblocks, i) {
|
||||
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
|
||||
const scc_cfg_bblock_t *bb =
|
||||
scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id);
|
||||
|
||||
// 插入bblock的offset
|
||||
scc_hashtable_set(&bblock_offset, (void *)(usize)id,
|
||||
(void *)scc_mcode_size(mcode));
|
||||
|
||||
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb);
|
||||
scc_vec_foreach(*instrs, i) {
|
||||
const scc_mir_instr_t *ins =
|
||||
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
||||
// FIXME reloc symbol needed
|
||||
scc_ir2mcode_emit_instr(mcode, &relocs, ins);
|
||||
}
|
||||
}
|
||||
|
||||
scc_vec_foreach(relocs, i) {
|
||||
scc_reloc_t *reloc = &scc_vec_at(relocs, i);
|
||||
if (reloc->target_kind == SCC_RELOC_TARGET_BBLOCK) {
|
||||
reloc->target_kind = SCC_RELOC_TARGET_NONE;
|
||||
usize addr = (usize)scc_hashtable_get(
|
||||
&bblock_offset, (void *)(usize)reloc->bblock_id);
|
||||
scc_ir2mcode_patch(mcode, reloc, addr);
|
||||
} else if (reloc->target_kind == SCC_RELOC_TARGET_SYMBOL) {
|
||||
usize sym_idx =
|
||||
sccf_builder_get_symbol_idx(builder, reloc->symbol);
|
||||
Assert(sym_idx != 0);
|
||||
sccf_builder_add_reloc(builder,
|
||||
(sccf_reloc_t){
|
||||
.addend = reloc->addend,
|
||||
.offset = reloc->offset,
|
||||
.reloc_type = reloc->arch_type,
|
||||
.sect_type = SCCF_SECT_CODE,
|
||||
.sym_idx = sym_idx,
|
||||
});
|
||||
} else {
|
||||
TODO();
|
||||
}
|
||||
}
|
||||
scc_vec_free(relocs);
|
||||
// 重定向bblock的reloc
|
||||
scc_hashtable_drop(&bblock_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
||||
// mir_module->symbol_metas
|
||||
// mir_module->cfg_module.funcs
|
||||
@@ -74,54 +138,36 @@ void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
||||
sccf_sect_data_t sect_code = {0};
|
||||
scc_vec_init(sect_code);
|
||||
scc_mcode_t mcode = {0};
|
||||
// TODO choice arch
|
||||
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
scc_mir_func_t *func = &scc_vec_at(mir_module->cfg_module.funcs, i);
|
||||
emit_mir_module(builder, &mcode, mir_module);
|
||||
scc_vec_unsafe_from_buffer(sect_code, (u8 *)scc_mcode_unsafe_data(&mcode),
|
||||
scc_mcode_size(&mcode));
|
||||
|
||||
sccf_sym_t *sym = sccf_builder_get_symbol_unsafe(builder, func->name);
|
||||
Assert(sym != nullptr);
|
||||
sym->sccf_sect_offset = scc_vec_size(mcode.mcode);
|
||||
scc_vec_foreach(builder->relocs, i) {
|
||||
sccf_reloc_t *reloc = &scc_vec_at(builder->relocs, i);
|
||||
if (reloc->sym_idx == 0) {
|
||||
Panic("relocate to an invalid symbol");
|
||||
}
|
||||
sccf_sym_t *sym = &scc_vec_at(builder->symtab, reloc->sym_idx);
|
||||
if (sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN) {
|
||||
|
||||
scc_vec_foreach(func->bblocks, i) {
|
||||
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
|
||||
const scc_cfg_bblock_t *bb =
|
||||
scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id);
|
||||
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb);
|
||||
scc_vec_foreach(*instrs, i) {
|
||||
const scc_mir_instr_t *ins =
|
||||
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
||||
// FIXME reloc symbol needed
|
||||
scc_ir2mcode_emit_instr(&mcode, ins);
|
||||
if (sym->sccf_sect_type == SCCF_SECT_CODE &&
|
||||
sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC) {
|
||||
i64 target_off = sym->sccf_sect_offset;
|
||||
|
||||
scc_ir2mcode_patch(&mcode,
|
||||
&(scc_reloc_t){
|
||||
.target_kind = SCC_RELOC_TARGET_SYMBOL,
|
||||
.arch_type = reloc->reloc_type,
|
||||
.offset = reloc->offset,
|
||||
.addend = reloc->addend,
|
||||
},
|
||||
target_off);
|
||||
reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
scc_vec_unsafe_from_buffer(sect_code, scc_vec_unsafe_get_data(mcode.mcode),
|
||||
scc_vec_size(mcode.mcode));
|
||||
|
||||
// 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_builder_add_text_section(builder, §_code);
|
||||
sccf_builder_add_data_section(builder, §_data);
|
||||
|
||||
Reference in New Issue
Block a user