- 添加 scc_ast2ir_mir_module 内联函数统一访问模块 - 替换所有直接访问 ctx->builder.cprog->module 的地方 - 移除重复的 scc_hir_type_size 函数实现 - 添加 scc_hir_module_type_size 函数到模块接口 - 更新所有类型大小计算调用使用新函数 feat(hir): 增强构建器安全性和全局变量处理 - 为 scc_hir_builder_integer 添加空指针检查断言 - 修复 scc_hir_builder_global_alloca 中全局变量类型设置 - 改进 scc_hir_builder_get_elem_ptr 处理空指针索引情况 - 重构字符串常量生成使用 get_elem_ptr 构建器函数 refactor(lir): 简化地址表达式表示并增强内置函数支持 - 移除复杂地址结构体 scc_lir_addr_t - 简化 scc_lir_instr 结构体中的地址表示 - 移除 STORE_ADDR 操作码 - 添加 memcpy 和 memset 内置函数操作码 - 在符号元数据中使用联合体替代嵌套结构体 feat(hir2lir): 完善 HIR 到 LIR 转换中的内置函数处理 - 添加 ensure_vreg 辅助函数确保虚拟寄存器操作数 - 正确处理全局变量地址符号引用 - 优化 GET_ELEM_PTR 转换使用类型大小计算 - 完整实现所有内置函数(BUILTIN)的 LIR 转换 - 包括 memcpy、memset、va_start、va_arg、va_end、va_copy 等
136 lines
4.3 KiB
C
136 lines
4.3 KiB
C
#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__ */
|