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

@@ -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__ */

View File

@@ -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)

View File

@@ -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

View File

@@ -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) {

View File

@@ -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);
} }

View File

@@ -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__ */

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)); 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;

View File

@@ -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,
});
} }
} }
} }

View File

@@ -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__ */

View File

@@ -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);
} }
} }
} }

View File

@@ -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, &sect_code); sccf_builder_add_text_section(builder, &sect_code);
sccf_builder_add_data_section(builder, &sect_data); sccf_builder_add_data_section(builder, &sect_data);

2
libs/mcode/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.json

View File

@@ -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);

View 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__ */

View File

@@ -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) {
// 操作数作为 rmreg 部分为 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);

View File

@@ -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;
/** /**

View File

@@ -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__ */

View File

@@ -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) {

View File

@@ -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;