Files
scc/libs/mcode/include/x86/scc_x86_patch.h
zzy 41d060d7e7 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模块的机器码生成
- 实现基本块间重定位的地址解析和补丁应用
- 改进符号重定位的处理机制
- 简化机器码段数据的最终处理流程
2026-05-21 16:19:49 +08:00

138 lines
4.4 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.
#ifndef __SCC_X86_PATCH_H__
#define __SCC_X86_PATCH_H__
#include "scc_x86_encode.h"
// x86-64 重定位类型(由底层 patch 函数处理)
typedef enum {
SCC_X86_PATCH_NONE,
SCC_X86_PATCH_PC32, // 32 位 PC 相对偏移CALL/JMP/Jcc
SCC_X86_PATCH_ABS64, // 64 位绝对地址MOV reg, imm64
SCC_X86_PATCH_ABS32, // 32 位绝对地址MOV reg, imm32
SCC_X86_PATCH_DISP8, // 8 位内存位移([RIP+disp8] 或 [base+disp8]
SCC_X86_PATCH_DISP32, // 32 位内存位移([RIP+disp32]
} scc_x86_patch_type_t;
static inline void patch_bytes(scc_mcode_t *mcode, usize offset,
const void *data, usize size) {
u8 *buf = (u8 *)scc_mcode_unsafe_data(mcode);
usize total = scc_mcode_size(mcode);
if (offset + size > total) {
Panic("patch offset out of range: offset=%zu size=%zu total=%zu",
offset, size, total);
}
scc_memcpy(buf + offset, data, size);
}
/* ---------- 实现补丁接口 ---------- */
static inline int scc_x86_patch_disp(scc_mcode_t *mcode, usize offset,
scc_x86_disp_t disp) {
if (!mcode || disp.displacement_bits == 0)
return -1;
usize bytes = disp.displacement_bits / 8;
if (bytes == 0) {
bytes = 4; // RELBR 32
}
if (bytes != 1 && bytes != 2 && bytes != 4 && bytes != 8) {
Panic("invalid displacement bits: %u", disp.displacement_bits);
}
// 将 displacement 截断到对应宽度(小端写入)
i64 val = disp.displacement;
switch (bytes) {
case 1: {
u8 v = (u8)val;
patch_bytes(mcode, offset, &v, 1);
break;
}
case 2: {
u16 v = (u16)val;
patch_bytes(mcode, offset, &v, 2);
break;
}
case 4: {
u32 v = (u32)val;
patch_bytes(mcode, offset, &v, 4);
break;
}
case 8:
patch_bytes(mcode, offset, &val, 8);
break;
}
return 0;
}
static inline int scc_x86_patch_brdisp(scc_mcode_t *mcode, usize offset,
scc_x86_operand_value_t disp) {
if (disp.kind != SCC_X86_OPR_RELBR && disp.kind != SCC_X86_OPR_RELOC) {
Panic("patch_brdisp called with non-branch operand kind %d", disp.kind);
}
i32 brdisp;
if (disp.kind == SCC_X86_OPR_RELBR)
brdisp = disp.brdisp;
else
brdisp = (i32)disp.reloc.imm; // 从重定位占位中获取值(上层会先填好)
patch_bytes(mcode, offset, &brdisp, 4);
return 0;
}
static inline int scc_x86_patch_imm0(scc_mcode_t *mcode, usize offset,
scc_x86_operand_value_t imm0) {
// 注意:原声明未提供大小参数,我们假定调用者保证了正确的宽度。
// 此处默认写入 8 字节(最常用)。若需要其他宽度,请使用扩展版本。
if (imm0.kind != SCC_X86_OPR_IMM && imm0.kind != SCC_X86_OPR_RELOC) {
Panic("patch_imm0 called with non-immediate operand kind %d",
imm0.kind);
}
u64 val;
if (imm0.kind == SCC_X86_OPR_IMM)
val = imm0.imm0;
else
val = (u64)imm0.reloc.imm; // 从重定位占位中获取
patch_bytes(mcode, offset, &val, 8);
return 0;
}
/* ---------- 扩展:带大小的立即数 patch推荐上层使用 ---------- */
static inline int scc_x86_patch_imm0_ex(scc_mcode_t *mcode, usize offset,
u64 value, usize size) {
if (size != 1 && size != 2 && size != 4 && size != 8)
return -1;
switch (size) {
case 1: {
u8 v = (u8)value;
patch_bytes(mcode, offset, &v, 1);
break;
}
case 2: {
u16 v = (u16)value;
patch_bytes(mcode, offset, &v, 2);
break;
}
case 4: {
u32 v = (u32)value;
patch_bytes(mcode, offset, &v, 4);
break;
}
case 8:
patch_bytes(mcode, offset, &value, 8);
break;
}
return 0;
}
static inline void scc_x86_patch(scc_mcode_t *mcode,
scc_x86_patch_type_t patch_type, u64 offset,
i64 value) {
switch (patch_type) {
case SCC_X86_PATCH_PC32:
scc_x86_patch_brdisp(mcode, offset - 4,
scc_x86_op_relbr(value - offset));
break;
default:
TODO();
break;
}
}
#endif /* __SCC_X86_PATCH_H__ */