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,6 +5,6 @@
|
|||||||
#include "scc_lir_module.h"
|
#include "scc_lir_module.h"
|
||||||
#include <scc_hir.h>
|
#include <scc_hir.h>
|
||||||
|
|
||||||
void scc_hir2lir(scc_lir_module_t *module, const scc_hir_cprog_t *cprog);
|
void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog);
|
||||||
|
|
||||||
#endif /* __SCC_IR2LIR_H__ */
|
#endif /* __SCC_IR2LIR_H__ */
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ typedef enum {
|
|||||||
SCC_LIR_LOAD_ADDR,
|
SCC_LIR_LOAD_ADDR,
|
||||||
SCC_LIR_STORE,
|
SCC_LIR_STORE,
|
||||||
SCC_LIR_STORE_ADDR,
|
SCC_LIR_STORE_ADDR,
|
||||||
SCC_LIR_LEA,
|
|
||||||
|
|
||||||
/* 整数算术 */
|
/* 整数算术 */
|
||||||
SCC_LIR_ADD,
|
SCC_LIR_ADD,
|
||||||
@@ -253,6 +252,7 @@ typedef scc_cfg_func_t scc_lir_func_t;
|
|||||||
typedef struct scc_lir_func_meta {
|
typedef struct scc_lir_func_meta {
|
||||||
int vregs_count;
|
int vregs_count;
|
||||||
int frame_size;
|
int frame_size;
|
||||||
|
int is_va_arg;
|
||||||
scc_lir_attr_t attr;
|
scc_lir_attr_t attr;
|
||||||
} scc_lir_func_meta_t;
|
} scc_lir_func_meta_t;
|
||||||
#define SCC_LIR_FUNC_META(func) ((scc_lir_func_meta_t *)(func)->meta)
|
#define SCC_LIR_FUNC_META(func) ((scc_lir_func_meta_t *)(func)->meta)
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ static scc_lir_op_t map_binop(scc_hir_op_type_t op, cbool is_float) {
|
|||||||
case SCC_HIR_OP_SAR:
|
case SCC_HIR_OP_SAR:
|
||||||
return SCC_LIR_SAR;
|
return SCC_LIR_SAR;
|
||||||
default:
|
default:
|
||||||
return map_cmp_cond(op, is_float);
|
return SCC_LIR_CMP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SCC_LIR_NOP;
|
return SCC_LIR_NOP;
|
||||||
@@ -263,15 +263,19 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
scc_lir_val_t rhs = ir_value_to_lir_operand(ctx, value->data.op.rhs);
|
scc_lir_val_t rhs = ir_value_to_lir_operand(ctx, value->data.op.rhs);
|
||||||
scc_lir_op_t op = map_binop(value->data.op.op, is_float);
|
scc_lir_op_t op = map_binop(value->data.op.op, is_float);
|
||||||
|
|
||||||
scc_lir_instr_t instr = {.op = op,
|
scc_lir_instr_t instr = {
|
||||||
.size = size,
|
.op = op,
|
||||||
.ext = ext,
|
.size = size,
|
||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.ext = ext,
|
||||||
.arg0 = lhs,
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg1 = rhs};
|
.arg0 = lhs,
|
||||||
|
.arg1 = rhs,
|
||||||
|
};
|
||||||
|
if (op == SCC_LIR_CMP) {
|
||||||
|
instr.metadata.cond = map_cmp_cond(value->data.op.op, is_float);
|
||||||
|
}
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_LOAD: {
|
case SCC_HIR_VALUE_TAG_LOAD: {
|
||||||
scc_lir_val_t addr =
|
scc_lir_val_t addr =
|
||||||
ir_value_to_lir_operand(ctx, value->data.load.target);
|
ir_value_to_lir_operand(ctx, value->data.load.target);
|
||||||
@@ -281,8 +285,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg0 = addr};
|
.arg0 = addr};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_STORE: {
|
case SCC_HIR_VALUE_TAG_STORE: {
|
||||||
scc_lir_val_t data =
|
scc_lir_val_t data =
|
||||||
ir_value_to_lir_operand(ctx, value->data.store.value);
|
ir_value_to_lir_operand(ctx, value->data.store.value);
|
||||||
@@ -291,8 +294,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
scc_lir_instr_t instr = {
|
scc_lir_instr_t instr = {
|
||||||
.op = SCC_LIR_STORE, .size = size, .arg0 = data, .arg1 = addr};
|
.op = SCC_LIR_STORE, .size = size, .arg0 = data, .arg1 = addr};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: {
|
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: {
|
||||||
// 将指针运算转换为 LEA
|
// 将指针运算转换为 LEA
|
||||||
scc_lir_val_t base =
|
scc_lir_val_t base =
|
||||||
@@ -333,15 +335,14 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
scc_lir_val_t addr =
|
scc_lir_val_t addr =
|
||||||
SCC_LIR_ADDR(dst_vreg, -1, index.data.reg, elem_size);
|
SCC_LIR_ADDR(dst_vreg, -1, index.data.reg, elem_size);
|
||||||
// 更简单的做法:使用 LEA 指令,参数为 base 和 index,由后端展开
|
// 更简单的做法:使用 LEA 指令,参数为 base 和 index,由后端展开
|
||||||
scc_lir_instr_t instr = {.op = SCC_LIR_LEA,
|
scc_lir_instr_t instr = {.op = SCC_LIR_LOAD_ADDR,
|
||||||
.size = SCC_LIR_SIZE_64,
|
.size = SCC_LIR_SIZE_64,
|
||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg0 = base,
|
.arg0 = base,
|
||||||
.arg1 = index};
|
.arg1 = index};
|
||||||
// 实际需要将 index * elem_size 的信息编码,这里简化,假设后端处理
|
// 实际需要将 index * elem_size 的信息编码,这里简化,假设后端处理
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_ALLOC: {
|
case SCC_HIR_VALUE_TAG_ALLOC: {
|
||||||
// alloca 指令:分配栈空间
|
// alloca 指令:分配栈空间
|
||||||
scc_hir_type_t *alloc_ty =
|
scc_hir_type_t *alloc_ty =
|
||||||
@@ -355,8 +356,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.metadata.alloca = {alloc_size, alloc_size}};
|
.metadata.alloca = {alloc_size, alloc_size}};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_CALL: {
|
case SCC_HIR_VALUE_TAG_CALL: {
|
||||||
scc_hir_func_t *callee = scc_hir_module_get_func(
|
scc_hir_func_t *callee = scc_hir_module_get_func(
|
||||||
ctx->hir_module, value->data.call.callee.func_ref);
|
ctx->hir_module, value->data.call.callee.func_ref);
|
||||||
@@ -381,8 +381,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
// metadata.call.args 指针仍指向 malloc 内存,
|
// metadata.call.args 指针仍指向 malloc 内存,
|
||||||
// 这会导致内存泄漏。实际实现中应使用 arena
|
// 这会导致内存泄漏。实际实现中应使用 arena
|
||||||
// 分配或随函数释放。此处为示例简化。
|
// 分配或随函数释放。此处为示例简化。
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_BRANCH: {
|
case SCC_HIR_VALUE_TAG_BRANCH: {
|
||||||
scc_lir_val_t cond =
|
scc_lir_val_t cond =
|
||||||
ir_value_to_lir_operand(ctx, value->data.branch.cond);
|
ir_value_to_lir_operand(ctx, value->data.branch.cond);
|
||||||
@@ -392,15 +391,13 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
.metadata.br = {value->data.branch.true_bblock,
|
.metadata.br = {value->data.branch.true_bblock,
|
||||||
value->data.branch.false_bblock}};
|
value->data.branch.false_bblock}};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_JUMP: {
|
case SCC_HIR_VALUE_TAG_JUMP: {
|
||||||
scc_lir_instr_t instr = {.op = SCC_LIR_JMP,
|
scc_lir_instr_t instr = {.op = SCC_LIR_JMP,
|
||||||
.metadata.jmp_target =
|
.metadata.jmp_target =
|
||||||
value->data.jump.target_bblock};
|
value->data.jump.target_bblock};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_RET: {
|
case SCC_HIR_VALUE_TAG_RET: {
|
||||||
scc_lir_val_t ret_val;
|
scc_lir_val_t ret_val;
|
||||||
if (value->data.ret.ret_val != SCC_HIR_REF_nullptr) {
|
if (value->data.ret.ret_val != SCC_HIR_REF_nullptr) {
|
||||||
@@ -411,8 +408,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
scc_lir_instr_t instr = {.op = SCC_LIR_RET,
|
scc_lir_instr_t instr = {.op = SCC_LIR_RET,
|
||||||
.metadata.ret_val = ret_val};
|
.metadata.ret_val = ret_val};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case SCC_HIR_VALUE_TAG_CONV: {
|
case SCC_HIR_VALUE_TAG_CONV: {
|
||||||
// 类型转换:使用 MOV 指令配合扩展/截断
|
// 类型转换:使用 MOV 指令配合扩展/截断
|
||||||
scc_lir_val_t src =
|
scc_lir_val_t src =
|
||||||
@@ -429,8 +425,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
.to = SCC_LIR_VREG(dst_vreg),
|
.to = SCC_LIR_VREG(dst_vreg),
|
||||||
.arg0 = src};
|
.arg0 = src};
|
||||||
scc_lir_builder_add_instr(ctx, &instr);
|
scc_lir_builder_add_instr(ctx, &instr);
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
// 不生成指令的节点(如 CONST_INT, FUNC_ARG_REF)不会调用本函数
|
// 不生成指令的节点(如 CONST_INT, FUNC_ARG_REF)不会调用本函数
|
||||||
break;
|
break;
|
||||||
@@ -447,6 +442,7 @@ static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
|
|||||||
.attr = SCC_LIR_ATTR_NONE,
|
.attr = SCC_LIR_ATTR_NONE,
|
||||||
.frame_size = 0,
|
.frame_size = 0,
|
||||||
.vregs_count = 0,
|
.vregs_count = 0,
|
||||||
|
.is_va_arg = false,
|
||||||
};
|
};
|
||||||
scc_vec_push(ctx->lir_module->func_metas, lir_func_meta);
|
scc_vec_push(ctx->lir_module->func_metas, lir_func_meta);
|
||||||
ctx->current_func = ir_func;
|
ctx->current_func = ir_func;
|
||||||
@@ -483,7 +479,7 @@ static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
|
|||||||
scc_hashtable_drop(&ctx->value_to_vreg);
|
scc_hashtable_drop(&ctx->value_to_vreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_hir2lir(scc_lir_module_t *module, const scc_hir_cprog_t *cprog) {
|
void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) {
|
||||||
Assert(module != nullptr && cprog != nullptr);
|
Assert(module != nullptr && cprog != nullptr);
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ static const char *op_to_string(scc_lir_op_t op) {
|
|||||||
return "store";
|
return "store";
|
||||||
case SCC_LIR_STORE_ADDR:
|
case SCC_LIR_STORE_ADDR:
|
||||||
return "store.addr";
|
return "store.addr";
|
||||||
case SCC_LIR_LEA:
|
|
||||||
return "lea";
|
|
||||||
case SCC_LIR_ADD:
|
case SCC_LIR_ADD:
|
||||||
return "add";
|
return "add";
|
||||||
case SCC_LIR_SUB:
|
case SCC_LIR_SUB:
|
||||||
@@ -236,7 +234,6 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
|
|||||||
scc_tree_dump_append(td, " <- ");
|
scc_tree_dump_append(td, " <- ");
|
||||||
dump_operand(ctx, &ins->arg0);
|
dump_operand(ctx, &ins->arg0);
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_LEA:
|
|
||||||
case SCC_LIR_NEG:
|
case SCC_LIR_NEG:
|
||||||
case SCC_LIR_NOT:
|
case SCC_LIR_NOT:
|
||||||
case SCC_LIR_FNEG:
|
case SCC_LIR_FNEG:
|
||||||
@@ -419,7 +416,8 @@ void scc_lir_dump_func(scc_lir_dump_ctx_t *ctx, const scc_lir_func_t *func) {
|
|||||||
scc_lir_func_meta_t *meta = SCC_LIR_FUNC_META(func);
|
scc_lir_func_meta_t *meta = SCC_LIR_FUNC_META(func);
|
||||||
// 函数头部
|
// 函数头部
|
||||||
scc_tree_dump_begin_line(td);
|
scc_tree_dump_begin_line(td);
|
||||||
scc_tree_dump_node(td, "func @%s", func->name ? func->name : "<anon>");
|
scc_tree_dump_node(td, "func @%s%s", func->name ? func->name : "<anon>",
|
||||||
|
meta->is_va_arg ? "(...)" : "()");
|
||||||
scc_tree_dump_append_fmt(td, " (vregs: %u, frame: %d)", meta->vregs_count,
|
scc_tree_dump_append_fmt(td, " (vregs: %u, frame: %d)", meta->vregs_count,
|
||||||
meta->frame_size);
|
meta->frame_size);
|
||||||
if (meta->attr != SCC_LIR_ATTR_NONE) {
|
if (meta->attr != SCC_LIR_ATTR_NONE) {
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
|
|||||||
const scc_lir_val_t *val);
|
const scc_lir_val_t *val);
|
||||||
static inline void emit_direct_call(scc_x86_64_isel_t *isel,
|
static inline void emit_direct_call(scc_x86_64_isel_t *isel,
|
||||||
const char *callee) {
|
const char *callee) {
|
||||||
(void)callee;
|
|
||||||
scc_mir_x86_instr_t instr = {0};
|
scc_mir_x86_instr_t instr = {0};
|
||||||
scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_RELBRZ,
|
scc_x86_operand_value_t op = scc_x86_op_reloc_global_relbr(callee, 0);
|
||||||
scc_x86_op_relbr(0), scc_pos_create());
|
scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_RELBRZ, op,
|
||||||
|
scc_pos_create());
|
||||||
scc_vec_push(isel->instrs, instr);
|
scc_vec_push(isel->instrs, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,15 +43,23 @@ static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op,
|
|||||||
op->reg = preg;
|
op->reg = preg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 未解析栈槽编码 (base=INVALID, disp=slot_id) ──────────────────────
|
// slot_id 编码为 base=INVALID, disp=slot_id
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id) {
|
||||||
|
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_MEM};
|
||||||
|
o.mem.base = SCC_X86_REG_INVALID;
|
||||||
|
o.mem.index = SCC_X86_REG_INVALID;
|
||||||
|
o.mem.scale = 1;
|
||||||
|
o.mem.disp.displacement = slot_id;
|
||||||
|
o.mem.disp.displacement_bits = 0;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
static inline bool scc_x86_op_is_slot(const scc_x86_operand_value_t *op) {
|
static inline bool scc_x86_op_is_slot(const scc_x86_operand_value_t *op) {
|
||||||
return op->kind == SCC_X86_OPR_MEM && op->mem.base == SCC_X86_REG_INVALID;
|
return op->kind == SCC_X86_OPR_MEM && op->mem.base == SCC_X86_REG_INVALID;
|
||||||
}
|
}
|
||||||
static inline int scc_x86_op_slot_id(const scc_x86_operand_value_t *op) {
|
static inline int scc_x86_op_slot_id(const scc_x86_operand_value_t *op) {
|
||||||
return op->mem.disp;
|
return op->mem.disp.displacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 指令构建辅助 ──────────────────────────────────────────────────────
|
|
||||||
static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, int opcode,
|
static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, int opcode,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
out->x86_instr.opcode = opcode;
|
out->x86_instr.opcode = opcode;
|
||||||
@@ -89,46 +97,4 @@ static inline void scc_mir_x86_instr_3(scc_mir_x86_instr_t *out, int opcode,
|
|||||||
out->x86_instr.src_loc = pos;
|
out->x86_instr.src_loc = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 常用操作数构造器 ──────────────────────────────────────────────────
|
|
||||||
static inline scc_x86_operand_value_t scc_x86_op_preg(scc_x86_reg_t reg) {
|
|
||||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_REG, .reg = reg};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
static inline scc_x86_operand_value_t scc_x86_op_vreg(int vreg) {
|
|
||||||
scc_x86_operand_value_t o = {
|
|
||||||
.kind = SCC_X86_OPR_REG,
|
|
||||||
.reg = (scc_x86_reg_t)((int)SCC_X86_REG_COUNT + vreg)};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
static inline scc_x86_operand_value_t scc_x86_op_relbr(i32 rel) {
|
|
||||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_RELBR, .imm = rel};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
static inline scc_x86_operand_value_t scc_x86_op_imm(i64 imm) {
|
|
||||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_IMM, .imm = imm};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
// slot_id 编码为 base=INVALID, disp=slot_id
|
|
||||||
static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id) {
|
|
||||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_MEM};
|
|
||||||
o.mem.base = SCC_X86_REG_INVALID;
|
|
||||||
o.mem.index = SCC_X86_REG_INVALID;
|
|
||||||
o.mem.scale = 1;
|
|
||||||
o.mem.disp = slot_id;
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
static inline scc_x86_operand_value_t scc_x86_op_symbol(const char *sym) {
|
|
||||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_IMM,
|
|
||||||
.imm = (i64)(usize)sym};
|
|
||||||
(void)o;
|
|
||||||
// symbol 暂用一个近似值占位,编码阶段处理重定位
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
static inline scc_x86_operand_value_t
|
|
||||||
scc_x86_op_block(scc_cfg_bblock_id_t bid) {
|
|
||||||
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_RELBR, .imm = 0};
|
|
||||||
(void)bid;
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __SCC_X86_MIR_H__ */
|
#endif /* __SCC_X86_MIR_H__ */
|
||||||
|
|||||||
@@ -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));
|
scc_tree_dump_append_fmt(td, "$%s", preg_name(op->reg));
|
||||||
break;
|
break;
|
||||||
case SCC_X86_OPR_IMM:
|
case SCC_X86_OPR_IMM:
|
||||||
scc_tree_dump_append_fmt(td, "%ld", op->imm);
|
scc_tree_dump_append_fmt(td, "%ld", op->imm0);
|
||||||
break;
|
break;
|
||||||
case SCC_X86_OPR_MEM:
|
case SCC_X86_OPR_MEM:
|
||||||
if (scc_x86_op_is_slot(op))
|
if (scc_x86_op_is_slot(op))
|
||||||
scc_tree_dump_append_fmt(td, "[slot:%d]",
|
scc_tree_dump_append_fmt(td, "[slot:%d]",
|
||||||
scc_x86_op_slot_id(op));
|
scc_x86_op_slot_id(op));
|
||||||
else
|
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;
|
break;
|
||||||
case SCC_X86_OPR_RELBR:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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);
|
op = scc_x86_op_imm(*(i64 *)&val->data.fimm);
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_INSTR_KIND_SYMBOL:
|
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;
|
break;
|
||||||
case SCC_LIR_INSTR_KIND_ARG:
|
case SCC_LIR_INSTR_KIND_ARG:
|
||||||
Assert(isel->abi_lowering.lower_param);
|
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,
|
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_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 (dst_kind == SCC_X86_OPR_REG) {
|
||||||
if (src.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);
|
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,
|
add_instr_2(isel,
|
||||||
(size == 8) ? SCC_X86_IFORM_MOV_GPRV_IMMZ
|
(size == 8) ? SCC_X86_IFORM_MOV_GPRV_IMMZ
|
||||||
: SCC_X86_IFORM_MOV_GPRV_IMMV,
|
: SCC_X86_IFORM_MOV_GPRV_IMMV,
|
||||||
dst, src);
|
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);
|
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);
|
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src);
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
} else if (dst.kind == SCC_X86_OPR_MEM) {
|
} else if (dst_kind == SCC_X86_OPR_MEM) {
|
||||||
if (src.kind == SCC_X86_OPR_REG) {
|
if (src_kind == SCC_X86_OPR_REG) {
|
||||||
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, src);
|
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);
|
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);
|
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_GPRV_IMMZ, temp, src);
|
||||||
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, temp);
|
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_operand_value_t temp = new_vreg_temp(isel);
|
||||||
scc_x86_emit_move(isel, temp, src, size);
|
scc_x86_emit_move(isel, temp, src, size);
|
||||||
scc_x86_emit_move(isel, dst, temp, 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);
|
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) {
|
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 dst = scc_x86_lir_val_to_mir_op(isel, &instr->to);
|
||||||
scc_x86_operand_value_t src0 =
|
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);
|
scc_x86_emit_move(isel, dst, src0, size);
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_LOAD:
|
case SCC_LIR_LOAD:
|
||||||
|
// TODO check valid
|
||||||
scc_x86_emit_move(isel, dst, src0, size);
|
scc_x86_emit_move(isel, dst, src0, size);
|
||||||
break;
|
break;
|
||||||
case SCC_LIR_STORE:
|
case SCC_LIR_STORE:
|
||||||
|
// TODO check valid
|
||||||
scc_x86_emit_move(isel, src1, src0, size);
|
scc_x86_emit_move(isel, src1, src0, size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_STORE_ADDR:
|
case SCC_LIR_STORE_ADDR:
|
||||||
TODO();
|
TODO();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCC_LIR_LEA:
|
|
||||||
case SCC_LIR_LOAD_ADDR:
|
case SCC_LIR_LOAD_ADDR:
|
||||||
add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0);
|
add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0);
|
||||||
break;
|
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: {
|
case SCC_LIR_BR: {
|
||||||
scc_x86_operand_value_t true_bb =
|
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_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_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0);
|
||||||
add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb);
|
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: {
|
case SCC_LIR_JMP: {
|
||||||
scc_x86_operand_value_t jmp_bb =
|
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);
|
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -458,6 +473,7 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module,
|
|||||||
Assert(func_meta != nullptr);
|
Assert(func_meta != nullptr);
|
||||||
scc_mir_func_meta_init(func_meta);
|
scc_mir_func_meta_init(func_meta);
|
||||||
func_meta->vregs_count = SCC_LIR_FUNC_META(func)->vregs_count;
|
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;
|
func->meta = func_meta;
|
||||||
|
|
||||||
isel->func = func;
|
isel->func = func;
|
||||||
|
|||||||
@@ -29,8 +29,13 @@ static void frame_alloc_impl(scc_frame_layout_t *ctx,
|
|||||||
ctx->offset += slot->size;
|
ctx->offset += slot->size;
|
||||||
slot->offset = ctx->offset;
|
slot->offset = ctx->offset;
|
||||||
}
|
}
|
||||||
op->mem.base = SCC_X86_REG_RSP;
|
*op = scc_x86_op_mem((scc_x86_mem_t){
|
||||||
op->mem.disp = -slot->offset;
|
.seg = SCC_X86_REG_INVALID,
|
||||||
|
.base = SCC_X86_REG_RSP,
|
||||||
|
.disp = {.displacement = -slot->offset},
|
||||||
|
.index = SCC_X86_REG_INVALID,
|
||||||
|
.scale = 1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,30 @@
|
|||||||
|
|
||||||
#include <scc_mcode.h>
|
#include <scc_mcode.h>
|
||||||
#include <scc_mir_module.h>
|
#include <scc_mir_module.h>
|
||||||
|
|
||||||
|
typedef struct scc_reloc {
|
||||||
|
usize offset; // 占位位置
|
||||||
|
u8 size; // 占位字节数(可选,用于校验)
|
||||||
|
int arch_type; // 架构相关的重定位类型(由后端解释)
|
||||||
|
enum {
|
||||||
|
SCC_RELOC_TARGET_NONE,
|
||||||
|
SCC_RELOC_TARGET_SYMBOL,
|
||||||
|
SCC_RELOC_TARGET_BBLOCK,
|
||||||
|
} target_kind;
|
||||||
|
union {
|
||||||
|
const char *symbol;
|
||||||
|
int bblock_id;
|
||||||
|
};
|
||||||
|
i64 addend;
|
||||||
|
} scc_reloc_t;
|
||||||
|
|
||||||
|
typedef SCC_VEC(scc_reloc_t) scc_reloc_vec_t;
|
||||||
|
|
||||||
// FIXME target choice
|
// FIXME target choice
|
||||||
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode,
|
void scc_ir2mcode_emit_instr(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||||
const scc_mir_instr_t *mir_instr);
|
const scc_mir_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);
|
||||||
|
void scc_ir2mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||||
|
const scc_mir_module_t *mir_module);
|
||||||
|
|
||||||
#endif /* __SCC_IR2MCODE_H__ */
|
#endif /* __SCC_IR2MCODE_H__ */
|
||||||
|
|||||||
@@ -5,30 +5,91 @@
|
|||||||
#include <arch/scc_x86_mir.h>
|
#include <arch/scc_x86_mir.h>
|
||||||
#include <x86/scc_x86_encode.h>
|
#include <x86/scc_x86_encode.h>
|
||||||
#include <x86/scc_x86_iform.h>
|
#include <x86/scc_x86_iform.h>
|
||||||
|
#include <x86/scc_x86_patch.h>
|
||||||
#include <x86/scc_x86_reg.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;
|
scc_x86_instr_t *ins = (void *)_ins;
|
||||||
if (ins->opcode < 0 || ins->opcode >= SCC_X86_IFORM_COUNT) {
|
if (ins->opcode < 0 || ins->opcode >= SCC_X86_IFORM_COUNT) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scc_x86_operand_value_t ops[8] = {0};
|
scc_x86_operand_value_t ops[8] = {0};
|
||||||
|
scc_reloc_t reloc = {0};
|
||||||
for (int i = 0; i < ins->num_operands; i++) {
|
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");
|
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");
|
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);
|
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) {
|
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) {
|
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -42,7 +103,7 @@ void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) {
|
|||||||
scc_vec_foreach(*instrs, i) {
|
scc_vec_foreach(*instrs, i) {
|
||||||
const scc_mir_instr_t *ins =
|
const scc_mir_instr_t *ins =
|
||||||
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
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) {
|
void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
||||||
// mir_module->symbol_metas
|
// mir_module->symbol_metas
|
||||||
// mir_module->cfg_module.funcs
|
// 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};
|
sccf_sect_data_t sect_code = {0};
|
||||||
scc_vec_init(sect_code);
|
scc_vec_init(sect_code);
|
||||||
scc_mcode_t mcode = {0};
|
scc_mcode_t mcode = {0};
|
||||||
|
// TODO choice arch
|
||||||
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||||
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
emit_mir_module(builder, &mcode, mir_module);
|
||||||
if (i == 0)
|
scc_vec_unsafe_from_buffer(sect_code, (u8 *)scc_mcode_unsafe_data(&mcode),
|
||||||
continue;
|
scc_mcode_size(&mcode));
|
||||||
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);
|
scc_vec_foreach(builder->relocs, i) {
|
||||||
Assert(sym != nullptr);
|
sccf_reloc_t *reloc = &scc_vec_at(builder->relocs, i);
|
||||||
sym->sccf_sect_offset = scc_vec_size(mcode.mcode);
|
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) {
|
if (sym->sccf_sect_type == SCCF_SECT_CODE &&
|
||||||
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
|
sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC) {
|
||||||
const scc_cfg_bblock_t *bb =
|
i64 target_off = sym->sccf_sect_offset;
|
||||||
scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id);
|
|
||||||
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb);
|
scc_ir2mcode_patch(&mcode,
|
||||||
scc_vec_foreach(*instrs, i) {
|
&(scc_reloc_t){
|
||||||
const scc_mir_instr_t *ins =
|
.target_kind = SCC_RELOC_TARGET_SYMBOL,
|
||||||
scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i);
|
.arch_type = reloc->reloc_type,
|
||||||
// FIXME reloc symbol needed
|
.offset = reloc->offset,
|
||||||
scc_ir2mcode_emit_instr(&mcode, ins);
|
.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_text_section(builder, §_code);
|
||||||
sccf_builder_add_data_section(builder, §_data);
|
sccf_builder_add_data_section(builder, §_data);
|
||||||
|
|||||||
2
libs/mcode/.gitignore
vendored
Normal file
2
libs/mcode/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
*.json
|
||||||
@@ -6,21 +6,116 @@
|
|||||||
#include "scc_x86_reg.h"
|
#include "scc_x86_reg.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
i64 displacement;
|
||||||
|
u32 displacement_bits;
|
||||||
|
} scc_x86_disp_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
scc_x86_reg_t seg;
|
||||||
scc_x86_reg_t base;
|
scc_x86_reg_t base;
|
||||||
scc_x86_reg_t index;
|
scc_x86_reg_t index;
|
||||||
u8 scale; /* 1,2,4,8 */
|
u32 scale;
|
||||||
i32 disp;
|
scc_x86_disp_t disp;
|
||||||
} scc_x86_mem_t;
|
} scc_x86_mem_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SCC_X86_RELOC_TARGET_SYMBOL,
|
||||||
|
SCC_X86_RELOC_TARGET_BBLOCK,
|
||||||
|
} scc_x86_reloc_target_t;
|
||||||
|
|
||||||
|
typedef struct scc_x86_reloc_op {
|
||||||
|
scc_x86_operand_kind_t kind; // 原始操作数类型
|
||||||
|
scc_x86_reloc_target_t target;
|
||||||
|
union {
|
||||||
|
i64 imm;
|
||||||
|
int bblock_id; // 如果 kind == RELBR
|
||||||
|
const char *global_name; // 如果 kind == SYMBOL
|
||||||
|
};
|
||||||
|
i64 addend; // 额外常量偏移,用于 sym+addend
|
||||||
|
} scc_x86_reloc_op_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scc_x86_operand_kind_t kind;
|
scc_x86_operand_kind_t kind;
|
||||||
union {
|
union {
|
||||||
scc_x86_reg_t reg;
|
scc_x86_reg_t reg;
|
||||||
i64 imm;
|
i32 brdisp;
|
||||||
|
i64 simm0;
|
||||||
|
u64 imm0;
|
||||||
|
u8 imm1;
|
||||||
scc_x86_mem_t mem;
|
scc_x86_mem_t mem;
|
||||||
|
scc_x86_reloc_op_t reloc;
|
||||||
};
|
};
|
||||||
} scc_x86_operand_value_t;
|
} scc_x86_operand_value_t;
|
||||||
|
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_preg(scc_x86_reg_t reg) {
|
||||||
|
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_REG, .reg = reg};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_vreg(int vreg) {
|
||||||
|
scc_x86_operand_value_t o = {
|
||||||
|
.kind = SCC_X86_OPR_REG,
|
||||||
|
.reg = (scc_x86_reg_t)((int)SCC_X86_REG_COUNT + vreg)};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_relbr(i32 rel) {
|
||||||
|
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_RELBR, .brdisp = rel};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_imm(i64 imm) {
|
||||||
|
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_IMM, .simm0 = imm};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_mem(scc_x86_mem_t mem) {
|
||||||
|
scc_x86_operand_value_t o = {.kind = SCC_X86_OPR_MEM, .mem = mem};
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 全局符号重定位(绝对地址加载:MOV reg, imm32/64)
|
||||||
|
static inline scc_x86_operand_value_t
|
||||||
|
scc_x86_op_reloc_global_imm(const char *sym, i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_IMM;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||||
|
op.reloc.global_name = sym;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 全局符号重定位(相对跳转/调用:CALL/JMP rel32)
|
||||||
|
static inline scc_x86_operand_value_t
|
||||||
|
scc_x86_op_reloc_global_relbr(const char *sym, i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_RELBR;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||||
|
op.reloc.global_name = sym;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 基本块重定位(相对跳转)
|
||||||
|
static inline scc_x86_operand_value_t scc_x86_op_reloc_block(int bid,
|
||||||
|
i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_RELBR;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_BBLOCK;
|
||||||
|
op.reloc.bblock_id = bid;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 如果需要支持符号的内存寻址(如 [RIP + sym]),可扩展 kind =
|
||||||
|
// SCC_X86_OPR_MEM
|
||||||
|
static inline scc_x86_operand_value_t
|
||||||
|
scc_x86_op_reloc_global_mem(const char *sym, i64 addend) {
|
||||||
|
scc_x86_operand_value_t op = {.kind = SCC_X86_OPR_RELOC};
|
||||||
|
op.reloc.kind = SCC_X86_OPR_MEM;
|
||||||
|
op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL;
|
||||||
|
op.reloc.global_name = sym;
|
||||||
|
op.reloc.addend = addend;
|
||||||
|
// 编码时需生成 RIP 相对寻址的 ModRM/SIB
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
/* 按 iform 发射一条指令,ops 数组长度需与 iform 定义的操作数数目一致 */
|
/* 按 iform 发射一条指令,ops 数组长度需与 iform 定义的操作数数目一致 */
|
||||||
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
||||||
const scc_x86_operand_value_t *ops);
|
const scc_x86_operand_value_t *ops);
|
||||||
|
|||||||
137
libs/mcode/include/x86/scc_x86_patch.h
Normal file
137
libs/mcode/include/x86/scc_x86_patch.h
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
#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__ */
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <x86/scc_x86_encode.h>
|
#include <x86/scc_x86_encode.h>
|
||||||
#include <x86/scc_x86_iform.h>
|
#include <x86/scc_x86_iform.h>
|
||||||
#include <x86/scc_x86_reg.h>
|
#include <x86/scc_x86_reg.h>
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#ifdef LOG_INFO
|
||||||
|
#undef LOG_INFO
|
||||||
|
#endif
|
||||||
|
#define LOG_INFO(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---------- 内部辅助 ---------- */
|
/* ---------- 内部辅助 ---------- */
|
||||||
static inline void emit_u8(scc_mcode_t *m, uint8_t v) {
|
static inline void emit_u8(scc_mcode_t *m, uint8_t v) {
|
||||||
scc_mcode_add_u8(m, v);
|
scc_mcode_add_u8(m, v);
|
||||||
@@ -54,13 +59,13 @@ static int infer_operand_width(const scc_x86_iform_info_t *info,
|
|||||||
}
|
}
|
||||||
const char *eosz = info->encode.eosz;
|
const char *eosz = info->encode.eosz;
|
||||||
int default_64 = info->encode.default_64b;
|
int default_64 = info->encode.default_64b;
|
||||||
if (!strcmp(eosz, "o16"))
|
if (!scc_strcmp(eosz, "o16"))
|
||||||
return 16;
|
return 16;
|
||||||
if (!strcmp(eosz, "o32"))
|
if (!scc_strcmp(eosz, "o32"))
|
||||||
return 32;
|
return 32;
|
||||||
if (!strcmp(eosz, "o64"))
|
if (!scc_strcmp(eosz, "o64"))
|
||||||
return 64;
|
return 64;
|
||||||
if (!strcmp(eosz, "oszall") || !strcmp(eosz, "osznot16"))
|
if (!scc_strcmp(eosz, "oszall") || !scc_strcmp(eosz, "osznot16"))
|
||||||
return default_64 ? 64 : 32;
|
return default_64 ? 64 : 32;
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
@@ -69,16 +74,11 @@ static int infer_operand_width(const scc_x86_iform_info_t *info,
|
|||||||
static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
||||||
scc_x86_reg_t rm_op, scc_x86_reg_t base,
|
scc_x86_reg_t rm_op, scc_x86_reg_t base,
|
||||||
scc_x86_reg_t idx) {
|
scc_x86_reg_t idx) {
|
||||||
/* 强制要求 / 明确禁止 优先级最高 */
|
|
||||||
if (enc->rex_w == 1)
|
if (enc->rex_w == 1)
|
||||||
return 1;
|
return 1;
|
||||||
if (enc->rex_w == 0)
|
if (enc->rex_w == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* 指令已隐含 64 位语义(如 PUSH/POP),但仍可能被 64 位操作数需要 W?例如
|
|
||||||
* PUSH r64 不需要 W,但 PUSH r/m64 也不需要。总之 default_64b
|
|
||||||
* 时一般无需额外 W,但若操作数明确是 64 位且模板没有禁止,我们仍加上以兼容
|
|
||||||
* movabs 等 */
|
|
||||||
int has_64bit_op = 0;
|
int has_64bit_op = 0;
|
||||||
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 64)
|
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 64)
|
||||||
has_64bit_op = 1;
|
has_64bit_op = 1;
|
||||||
@@ -90,9 +90,6 @@ static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
|||||||
has_64bit_op = 1;
|
has_64bit_op = 1;
|
||||||
|
|
||||||
if (enc->default_64b) {
|
if (enc->default_64b) {
|
||||||
/* 对于默认 64 位的指令(如 CALL, JMP),有些仍需要 REX.W
|
|
||||||
* 访问扩展寄存器,但若 reg/rm 本身是 64 位且需要 REX.B/R 则一并设置 W
|
|
||||||
* 来保证编码正确?这里简单处理:只要访问扩展寄存器就加 W */
|
|
||||||
return (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op)) ||
|
return (reg_op != SCC_X86_REG_INVALID && reg_rex_bit(reg_op)) ||
|
||||||
(rm_op != SCC_X86_REG_INVALID && reg_rex_bit(rm_op)) ||
|
(rm_op != SCC_X86_REG_INVALID && reg_rex_bit(rm_op)) ||
|
||||||
(base != SCC_X86_REG_INVALID && reg_rex_bit(base)) ||
|
(base != SCC_X86_REG_INVALID && reg_rex_bit(base)) ||
|
||||||
@@ -101,7 +98,6 @@ static int need_rexw(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
|||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 普通指令:有 64 位操作数即加 W */
|
|
||||||
return has_64bit_op;
|
return has_64bit_op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,8 +105,7 @@ static int need_66_prefix(const scc_x86_encoding_t *enc, scc_x86_reg_t reg_op,
|
|||||||
scc_x86_reg_t rm_op) {
|
scc_x86_reg_t rm_op) {
|
||||||
if (enc->osz_required)
|
if (enc->osz_required)
|
||||||
return 1;
|
return 1;
|
||||||
// 如果强制指定了操作大小,不自动加66
|
if (!scc_strcmp(enc->eosz, "o32") || !scc_strcmp(enc->eosz, "o64"))
|
||||||
if (!strcmp(enc->eosz, "o32") || !strcmp(enc->eosz, "o64"))
|
|
||||||
return 0;
|
return 0;
|
||||||
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 16)
|
if (reg_op != SCC_X86_REG_INVALID && scc_reg_width(reg_op) == 16)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -215,17 +210,17 @@ static void emit_immediate(scc_mcode_t *m, const scc_x86_encoding_t *enc,
|
|||||||
int64_t imm_val, int op_width) {
|
int64_t imm_val, int op_width) {
|
||||||
const char *oc2 = tmpl[imm_idx].oc2;
|
const char *oc2 = tmpl[imm_idx].oc2;
|
||||||
int imm_size = enc->imm_size;
|
int imm_size = enc->imm_size;
|
||||||
if (!strcmp(oc2, "b"))
|
if (!scc_strcmp(oc2, "b"))
|
||||||
imm_size = 1;
|
imm_size = 1;
|
||||||
else if (!strcmp(oc2, "w"))
|
else if (!scc_strcmp(oc2, "w"))
|
||||||
imm_size = 2;
|
imm_size = 2;
|
||||||
else if (!strcmp(oc2, "z"))
|
else if (!scc_strcmp(oc2, "z"))
|
||||||
imm_size = (op_width <= 16) ? op_width / 8 : (op_width <= 32 ? 4 : 4);
|
imm_size = (op_width <= 16) ? op_width / 8 : (op_width <= 32 ? 4 : 4);
|
||||||
else if (!strcmp(oc2, "v"))
|
else if (!scc_strcmp(oc2, "v"))
|
||||||
imm_size = op_width / 8;
|
imm_size = op_width / 8;
|
||||||
else if (!strcmp(oc2, "d") || !strcmp(oc2, "ss"))
|
else if (!scc_strcmp(oc2, "d") || !scc_strcmp(oc2, "ss"))
|
||||||
imm_size = 4;
|
imm_size = 4;
|
||||||
else if (!strcmp(oc2, "q"))
|
else if (!scc_strcmp(oc2, "q"))
|
||||||
imm_size = 8;
|
imm_size = 8;
|
||||||
|
|
||||||
LOG_INFO("[IMM] val=%lld size=%d", imm_val, imm_size);
|
LOG_INFO("[IMM] val=%lld size=%d", imm_val, imm_size);
|
||||||
@@ -268,9 +263,9 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
if (ops[i].kind == SCC_X86_OPR_REG) {
|
if (ops[i].kind == SCC_X86_OPR_REG) {
|
||||||
LOG_INFO("[OPD] %d: REG kind, name=\"%s\" reg=%d", i, tname,
|
LOG_INFO("[OPD] %d: REG kind, name=\"%s\" reg=%d", i, tname,
|
||||||
ops[i].reg);
|
ops[i].reg);
|
||||||
if (strncmp(tname, "REG0", 4) == 0)
|
if (scc_strcmp(tname, "REG0") == 0)
|
||||||
reg_r = ops[i].reg;
|
reg_r = ops[i].reg;
|
||||||
else if (strncmp(tname, "REG1", 4) == 0)
|
else if (scc_strcmp(tname, "REG1") == 0)
|
||||||
reg_b = ops[i].reg;
|
reg_b = ops[i].reg;
|
||||||
else {
|
else {
|
||||||
if (reg_r == SCC_X86_REG_INVALID)
|
if (reg_r == SCC_X86_REG_INVALID)
|
||||||
@@ -282,7 +277,7 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
has_mem = 1;
|
has_mem = 1;
|
||||||
memdesc = ops[i].mem;
|
memdesc = ops[i].mem;
|
||||||
} else if (ops[i].kind == SCC_X86_OPR_IMM) {
|
} else if (ops[i].kind == SCC_X86_OPR_IMM) {
|
||||||
imm_val = ops[i].imm;
|
imm_val = ops[i].imm0;
|
||||||
imm_idx = i;
|
imm_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,7 +291,7 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
else if (enc->modrm_reg_fix >= 0)
|
else if (enc->modrm_reg_fix >= 0)
|
||||||
modrm |= (enc->modrm_reg_fix & 7) << 3;
|
modrm |= (enc->modrm_reg_fix & 7) << 3;
|
||||||
|
|
||||||
int32_t disp = memdesc.disp;
|
int32_t disp = memdesc.disp.displacement;
|
||||||
int dsize = disp_size(disp, memdesc.base);
|
int dsize = disp_size(disp, memdesc.base);
|
||||||
modrm |= (dsize == 0) ? 0 : (dsize == 8) ? 0x40 : 0x80;
|
modrm |= (dsize == 0) ? 0 : (dsize == 8) ? 0x40 : 0x80;
|
||||||
|
|
||||||
@@ -341,22 +336,38 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
modrm = 0xC0;
|
// 特殊情况:只有一个显式寄存器操作数,且 reg_fix/rm_fix 均未指定,且
|
||||||
if (enc->modrm_reg_fix >= 0)
|
// mod_fix == 3 此时操作数应放在 rm 字段,reg 字段固定为 0(例如 SETZ
|
||||||
modrm |= (enc->modrm_reg_fix & 7) << 3;
|
// 指令)
|
||||||
else if (reg_r != SCC_X86_REG_INVALID)
|
int is_single_reg_op =
|
||||||
modrm |= (reg_low3(reg_r) & 7) << 3;
|
(info->num_explicit_ops == 1 && enc->modrm_reg_fix == -1 &&
|
||||||
|
enc->modrm_rm_fix == -1 && enc->mod_fix == 3);
|
||||||
|
if (is_single_reg_op && reg_r != SCC_X86_REG_INVALID &&
|
||||||
|
reg_b == SCC_X86_REG_INVALID) {
|
||||||
|
// 操作数作为 rm,reg 部分为 0
|
||||||
|
modrm = 0xC0 | (reg_low3(reg_r) & 7);
|
||||||
|
emit_u8(m, modrm);
|
||||||
|
LOG_INFO("[MODRM] single reg operand treated as rm, emit 0x%02x",
|
||||||
|
modrm);
|
||||||
|
} else {
|
||||||
|
modrm = 0xC0;
|
||||||
|
if (enc->modrm_reg_fix >= 0)
|
||||||
|
modrm |= (enc->modrm_reg_fix & 7) << 3;
|
||||||
|
else if (reg_r != SCC_X86_REG_INVALID)
|
||||||
|
modrm |= (reg_low3(reg_r) & 7) << 3;
|
||||||
|
|
||||||
if (enc->modrm_rm_fix >= 0) {
|
if (enc->modrm_rm_fix >= 0) {
|
||||||
modrm |= enc->modrm_rm_fix & 7;
|
modrm |= enc->modrm_rm_fix & 7;
|
||||||
} else if (reg_b != SCC_X86_REG_INVALID) {
|
} else if (reg_b != SCC_X86_REG_INVALID) {
|
||||||
modrm |= reg_low3(reg_b) & 7;
|
modrm |= reg_low3(reg_b) & 7;
|
||||||
} else if (enc->modrm_reg_fix >= 0 && reg_r != SCC_X86_REG_INVALID) {
|
} else if (enc->modrm_reg_fix >= 0 &&
|
||||||
modrm |= reg_low3(reg_r) & 7;
|
reg_r != SCC_X86_REG_INVALID) {
|
||||||
} else if (reg_r != SCC_X86_REG_INVALID) {
|
modrm |= reg_low3(reg_r) & 7;
|
||||||
modrm |= reg_low3(reg_r) & 7;
|
} else if (reg_r != SCC_X86_REG_INVALID) {
|
||||||
|
modrm |= reg_low3(reg_r) & 7;
|
||||||
|
}
|
||||||
|
emit_u8(m, modrm);
|
||||||
}
|
}
|
||||||
emit_u8(m, modrm);
|
|
||||||
}
|
}
|
||||||
LOG_INFO("[MODRM] emit byte 0x%02x", modrm);
|
LOG_INFO("[MODRM] emit byte 0x%02x", modrm);
|
||||||
|
|
||||||
@@ -394,12 +405,12 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
|||||||
for (int i = 0; i < num_ops; i++) {
|
for (int i = 0; i < num_ops; i++) {
|
||||||
const char *tname = tmpl[i].name;
|
const char *tname = tmpl[i].name;
|
||||||
if (ops[i].kind == SCC_X86_OPR_REG) {
|
if (ops[i].kind == SCC_X86_OPR_REG) {
|
||||||
if (strncmp(tname, "REG0", 4) == 0) {
|
if (scc_strcmp(tname, "REG0") == 0) {
|
||||||
if (enc->modrm_reg_fix >= 0)
|
if (enc->modrm_reg_fix >= 0)
|
||||||
rm_field = ops[i].reg; // reg固定 → REG0为rm
|
rm_field = ops[i].reg; // reg固定 → REG0为rm
|
||||||
else
|
else
|
||||||
reg_field = ops[i].reg; // 否则为reg
|
reg_field = ops[i].reg; // 否则为reg
|
||||||
} else if (strncmp(tname, "REG1", 4) == 0) {
|
} else if (scc_strcmp(tname, "REG1") == 0) {
|
||||||
if (enc->modrm_rm_fix >= 0)
|
if (enc->modrm_rm_fix >= 0)
|
||||||
reg_field = ops[i].reg; // rm固定 → REG1为reg
|
reg_field = ops[i].reg; // rm固定 → REG1为reg
|
||||||
else
|
else
|
||||||
@@ -416,11 +427,25 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
|||||||
idx_reg = ops[i].mem.index;
|
idx_reg = ops[i].mem.index;
|
||||||
} else if (ops[i].kind == SCC_X86_OPR_IMM ||
|
} else if (ops[i].kind == SCC_X86_OPR_IMM ||
|
||||||
ops[i].kind == SCC_X86_OPR_RELBR) {
|
ops[i].kind == SCC_X86_OPR_RELBR) {
|
||||||
imm_val = ops[i].imm;
|
imm_val = ops[i].imm0;
|
||||||
imm_idx = i;
|
imm_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== 新增:特殊处理 SETZ 类指令(只有一个寄存器操作数,mod_fix=3 且
|
||||||
|
// reg_fix/rm_fix 未指定)=====
|
||||||
|
if (enc->has_modrm && info->num_explicit_ops == 1 &&
|
||||||
|
enc->modrm_reg_fix == -1 && enc->modrm_rm_fix == -1 &&
|
||||||
|
enc->mod_fix == 3) {
|
||||||
|
if (reg_field != SCC_X86_REG_INVALID &&
|
||||||
|
rm_field == SCC_X86_REG_INVALID) {
|
||||||
|
// 将操作数从 reg_field 移到 rm_field
|
||||||
|
rm_field = reg_field;
|
||||||
|
reg_field = SCC_X86_REG_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
int op_width = infer_operand_width(info, ops);
|
int op_width = infer_operand_width(info, ops);
|
||||||
LOG_INFO("[OPWIDTH] %d bits", op_width);
|
LOG_INFO("[OPWIDTH] %d bits", op_width);
|
||||||
|
|
||||||
@@ -446,4 +471,4 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,11 +72,12 @@ typedef enum {
|
|||||||
SCCF_SECT_RELOCS = 7, ///< 重定位表
|
SCCF_SECT_RELOCS = 7, ///< 重定位表
|
||||||
} sccf_sect_type_t;
|
} sccf_sect_type_t;
|
||||||
|
|
||||||
/** 重定位类型 */
|
/** 重定位类型 (可以被platform任意修改)在此只提供一个样例模板占位符 */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SCCF_RELOC_TYPE_EMPTY = 0, ///< 空展位符
|
SCCF_RELOC_TYPE_EMPTY = 0, ///< 空展位符
|
||||||
SCCF_RELOC_TYPE_ABS = 1, ///< 绝对地址
|
SCCF_RELOC_TYPE_ABS = 1, ///< 绝对地址
|
||||||
SCCF_RELOC_TYPE_REL = 2, ///< 相对地址
|
SCCF_RELOC_TYPE_REL = 2, ///< 相对地址
|
||||||
|
SCCF_RELOC_TYPE_COUNT = 3, ///< 重定位类型数量
|
||||||
} sccf_reloc_type_t;
|
} sccf_reloc_type_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
#ifndef __SCCF2PE_H__
|
||||||
|
#define __SCCF2PE_H__
|
||||||
|
|
||||||
#include <scc_pe_builder.h>
|
#include <scc_pe_builder.h>
|
||||||
#include <sccf_builder.h>
|
#include <sccf_builder.h>
|
||||||
|
|
||||||
void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf);
|
void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf);
|
||||||
|
|
||||||
|
#endif /* __SCCF2PE_H__ */
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <scc_pe_idata.h>
|
#include <scc_pe_idata.h>
|
||||||
#include <sccf2pe.h>
|
#include <sccf2pe.h>
|
||||||
#include <sccf_utils.h>
|
#include <sccf_utils.h>
|
||||||
|
#include <x86/scc_x86_patch.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scc_hashtable_t str2libsym;
|
scc_hashtable_t str2libsym;
|
||||||
@@ -199,6 +200,10 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
|||||||
.size_of_heap_commit = 0x1000,
|
.size_of_heap_commit = 0x1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scc_mcode_t mcode;
|
||||||
|
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||||
|
// FIXME hack
|
||||||
|
mcode.code = *(scc_mcode_buff_t *)code_data;
|
||||||
scc_vec_foreach(relocs, i) {
|
scc_vec_foreach(relocs, i) {
|
||||||
sccf_reloc_t *reloc = &scc_vec_at(relocs, i);
|
sccf_reloc_t *reloc = &scc_vec_at(relocs, i);
|
||||||
if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) {
|
if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) {
|
||||||
@@ -220,14 +225,16 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Assert(rva != 0);
|
Assert(rva != 0);
|
||||||
if (reloc->reloc_type == SCCF_RELOC_TYPE_ABS) {
|
|
||||||
TODO();
|
|
||||||
}
|
|
||||||
rva -= code_range.virual_address + reloc->offset + reloc->addend;
|
|
||||||
Assert(code_data != nullptr);
|
Assert(code_data != nullptr);
|
||||||
// FIXME 需要确保宿主机与目标机器大小端一致
|
// FIXME patch type
|
||||||
*(u32 *)(scc_vec_unsafe_get_data(*code_data) + reloc->offset) = rva;
|
// if (reloc->reloc_type == SCCF_RELOC_TYPE_ABS) {
|
||||||
|
// TODO();
|
||||||
|
// }
|
||||||
|
scc_x86_patch(&mcode, SCC_X86_PATCH_PC32,
|
||||||
|
code_range.virual_address + reloc->offset + reloc->addend,
|
||||||
|
rva);
|
||||||
}
|
}
|
||||||
|
*(scc_mcode_buff_t *)code_data = mcode.code;
|
||||||
|
|
||||||
scc_pe_write_header(builder, &config);
|
scc_pe_write_header(builder, &config);
|
||||||
if (code_data != nullptr) {
|
if (code_data != nullptr) {
|
||||||
|
|||||||
10
src/main.c
10
src/main.c
@@ -307,16 +307,16 @@ sstream_drop:
|
|||||||
if (config.emit_stage == SCC_EMIT_STAGE_FLATBIN) {
|
if (config.emit_stage == SCC_EMIT_STAGE_FLATBIN) {
|
||||||
scc_mcode_t mcode = {0};
|
scc_mcode_t mcode = {0};
|
||||||
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||||
scc_ir2mcode(&mcode, &mir_module);
|
scc_ir2mcode(&mcode, nullptr, &mir_module);
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
LOG_WARN("emit flatbin can't write to stdout");
|
LOG_WARN("emit flatbin can't write to stdout");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
usize ret = scc_fwrite(fp, scc_vec_unsafe_get_data(mcode.mcode),
|
usize mcode_size = scc_mcode_size(&mcode);
|
||||||
scc_vec_size(mcode.mcode));
|
usize ret = scc_fwrite(fp, scc_mcode_unsafe_data(&mcode), mcode_size);
|
||||||
if (ret != scc_vec_size(mcode.mcode)) {
|
if (ret != mcode_size) {
|
||||||
LOG_ERROR("write flatbin failed, write %zu but need write %zu\n",
|
LOG_ERROR("write flatbin failed, write %zu but need write %zu\n",
|
||||||
ret, scc_vec_size(mcode.mcode));
|
ret, mcode_size);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user