diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index f251faa..0ea3cc9 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -1362,6 +1362,13 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, break; } + scc_hir_func_t *hir_func = + scc_hir_module_get_func(&ctx->builder.cprog->module, func_ref); + Assert(hir_func != nullptr); + // TODO this is double check defined + Assert(SCC_HIR_FUNC_META(hir_func)->defined == false); + SCC_HIR_FUNC_META(hir_func)->defined = true; + scc_hir_builder_begin_func(&ctx->builder, func_ref); scc_hir_builder_begin_bblock(&ctx->builder, "entry"); diff --git a/libs/ir/hir/include/scc_hir_def.h b/libs/ir/hir/include/scc_hir_def.h index c49284b..ac3bedf 100644 --- a/libs/ir/hir/include/scc_hir_def.h +++ b/libs/ir/hir/include/scc_hir_def.h @@ -249,6 +249,7 @@ typedef struct scc_hir_bblock_meta { typedef struct scc_hir_func_meta { scc_hir_type_ref_t type; scc_hir_value_ref_vec_t params; + int defined; } scc_hir_func_meta_t; #define SCC_HIR_BBLOCK_VALUES(bblock) \ diff --git a/libs/ir/hir/src/scc_hir_builder.c b/libs/ir/hir/src/scc_hir_builder.c index 0653d7b..74fb7c6 100644 --- a/libs/ir/hir/src/scc_hir_builder.c +++ b/libs/ir/hir/src/scc_hir_builder.c @@ -188,6 +188,7 @@ scc_hir_func_ref_t scc_hir_builder_func(scc_hir_builder_t *builder, // 创建新函数 scc_hir_func_t func; scc_hir_func_meta_t *meta = scc_malloc(sizeof(scc_hir_func_meta_t)); + meta->defined = 0; Assert(meta != nullptr); func.meta = meta; scc_hir_func_init(&func, name); diff --git a/libs/ir/lir/include/scc_lir.h b/libs/ir/lir/include/scc_lir.h index 3331b30..6bd4c5d 100644 --- a/libs/ir/lir/include/scc_lir.h +++ b/libs/ir/lir/include/scc_lir.h @@ -185,21 +185,16 @@ typedef struct scc_lir_ins { scc_lir_bblock_id_t jmp_target; struct scc_lir_call { - const char *callee; scc_lir_val_t *args; int arg_count; scc_lir_val_t ret_vreg; u64 clobber_mask; + union { + const char *callee_name; + scc_lir_val_t callee_target; + }; } call; - struct scc_lir_call_indirect { - scc_lir_val_t target; - scc_lir_val_t *args; - int arg_count; - scc_lir_val_t ret_vreg; - u64 clobber_mask; - } call_indirect; - scc_lir_val_t ret_val; struct scc_lir_parallel_copy { diff --git a/libs/ir/lir/include/scc_lir_module.h b/libs/ir/lir/include/scc_lir_module.h index a9a2872..ceb3886 100644 --- a/libs/ir/lir/include/scc_lir_module.h +++ b/libs/ir/lir/include/scc_lir_module.h @@ -33,11 +33,11 @@ void scc_lir_module_drop(scc_lir_module_t *lir_module); * @brief 添加一个函数声明(外部或未定义) * @param mod 模块 * @param name 函数名 - * @param attr 属性 + * @param defined 是否定义 * @return 符号指针 */ scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *lir_module, - const char *name); + const char *name, int defined); /** * @brief 添加一个全局数据符号(定义或外部) @@ -56,4 +56,8 @@ scc_lir_symbol_id_t scc_lir_module_add_data(scc_lir_module_t *lir_module, const u8 *init_data, usize size, u32 align); +scc_lir_symbol_t * +scc_lir_module_unsafe_lookup_symbol(const scc_lir_module_t *lir_module, + const char *name); + #endif /* __SCC_LIR_MODULE_H__ */ diff --git a/libs/ir/lir/src/scc_hir2lir.c b/libs/ir/lir/src/scc_hir2lir.c index 2adf746..8b8b857 100644 --- a/libs/ir/lir/src/scc_hir2lir.c +++ b/libs/ir/lir/src/scc_hir2lir.c @@ -27,6 +27,7 @@ static void ir2lir_ctx_init(ir2lir_ctx_t *ctx, scc_lir_module_t *lir_module, } static void ir2lir_ctx_drop(ir2lir_ctx_t *ctx) { + // FIXME memory leak scc_hashtable_drop(&ctx->value_to_vreg); scc_hashtable_drop(&ctx->func_decl_map); } @@ -373,15 +374,26 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, lir_args[i] = ir_value_to_lir_operand(ctx, arg_ref); } - scc_lir_instr_t instr = { - .op = SCC_LIR_CALL, + // TODO this is on windows all extern is indirect call + // On Linux ELF all call is direct call expect using `-no-plt` + scc_lir_symbol_t *sym = + scc_lir_module_unsafe_lookup_symbol(ctx->lir_module, callee->name); + Assert(sym != nullptr); + int is_direct_call = sym->kind == SCC_CFG_SYMBOL_KIND_FUNC; + scc_lir_instr_t instr = (scc_lir_instr_t){ + .op = is_direct_call ? SCC_LIR_CALL : SCC_LIR_CALL_INDIRECT, .size = size, .to = SCC_LIR_VREG(dst_vreg), - .metadata.call = {.callee = callee->name, - .args = lir_args, + .metadata.call = {.args = lir_args, .arg_count = arg_count, .ret_vreg = SCC_LIR_VREG(dst_vreg), - .clobber_mask = 0}}; + .clobber_mask = 0}, + }; + if (is_direct_call) { + instr.metadata.call.callee_name = callee->name; + } else { + instr.metadata.call.callee_target = SCC_LIR_SYMBOL(callee->name); + } scc_lir_builder_add_instr(ctx, &instr); // 注意:lir_args 内存将随指令结构体复制到基本块向量中,但 // metadata.call.args 指针仍指向 malloc 内存, @@ -598,11 +610,11 @@ void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) { scc_hir_module_get_func(&cprog->module, func_ref); if (!func) continue; - scc_lir_symbol_id_t id = - scc_lir_module_add_func_decl(module, func->name); + scc_lir_symbol_id_t id = scc_lir_module_add_func_decl( + module, func->name, SCC_HIR_FUNC_META(func)->defined); Assert(id != SCC_CFG_ID_nullptr); // 记录映射,供调用时使用 - scc_hashtable_set(&ctx.func_decl_map, (void *)(uintptr_t)func_ref, + scc_hashtable_set(&ctx.func_decl_map, (void *)(usize)func_ref, (void *)func->name); } @@ -613,8 +625,8 @@ void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) { scc_hir_module_get_func(&cprog->module, func_ref); if (!func) continue; + translate_func(&ctx, func); } - ir2lir_ctx_drop(&ctx); } diff --git a/libs/ir/lir/src/scc_lir_dump.c b/libs/ir/lir/src/scc_lir_dump.c index 67af87d..0c8dc78 100644 --- a/libs/ir/lir/src/scc_lir_dump.c +++ b/libs/ir/lir/src/scc_lir_dump.c @@ -290,30 +290,21 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { case SCC_LIR_JMP_INDIRECT: dump_operand(ctx, &ins->arg0); break; - case SCC_LIR_CALL: { + case SCC_LIR_CALL: + case SCC_LIR_CALL_INDIRECT: { const struct scc_lir_call *c = &ins->metadata.call; if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) { dump_operand(ctx, &c->ret_vreg); scc_tree_dump_append(td, " = "); } - scc_tree_dump_append_fmt(td, "call @%s(", - c->callee ? c->callee : ""); - for (u8 i = 0; i < c->arg_count; i++) { - if (i > 0) - scc_tree_dump_append(td, ", "); - dump_operand(ctx, &c->args[i]); - } - scc_tree_dump_append_fmt(td, ") clobber=0x%llx", - (unsigned long long)c->clobber_mask); - } break; - case SCC_LIR_CALL_INDIRECT: { - const struct scc_lir_call_indirect *c = &ins->metadata.call_indirect; - if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) { - dump_operand(ctx, &c->ret_vreg); - scc_tree_dump_append(td, " = "); - } + scc_tree_dump_append(td, "call "); - dump_operand(ctx, &c->target); + if (ins->op == SCC_LIR_CALL) { + scc_tree_dump_append_fmt( + td, "@%s", c->callee_name ? c->callee_name : ""); + } else { + dump_operand(ctx, &c->callee_target); + } scc_tree_dump_append(td, "("); for (u8 i = 0; i < c->arg_count; i++) { if (i > 0) diff --git a/libs/ir/lir/src/scc_lir_module.c b/libs/ir/lir/src/scc_lir_module.c index f8d2978..d187bb2 100644 --- a/libs/ir/lir/src/scc_lir_module.c +++ b/libs/ir/lir/src/scc_lir_module.c @@ -3,7 +3,6 @@ void scc_lir_module_init(scc_lir_module_t *lir_module) { // FIXME // lir_module->lir_module - scc_vec_init(lir_module->func_metas); scc_vec_init(lir_module->symbol_metas); } @@ -14,15 +13,25 @@ void scc_lir_module_drop(scc_lir_module_t *lir_module) { scc_vec_free(lir_module->symbol_metas); } +scc_lir_symbol_t * +scc_lir_module_unsafe_lookup_symbol(const scc_lir_module_t *lir_module, + const char *name) { + // FIXME const ? + return (void *)scc_cfg_module_unsafe_lookup_symbol(&lir_module->cfg_module, + name); +} + scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *lir_module, - const char *name) { + const char *name, + int defined) { if (!lir_module || !name) return SCC_CFG_ID_nullptr; scc_lir_symbol_meta_t *meta = scc_malloc(sizeof(scc_lir_symbol_meta_t)); Assert(meta != nullptr); scc_lir_symbol_t sym = {.name = name, - .kind = SCC_CFG_SYMBOL_KIND_FUNC, + .kind = defined ? SCC_CFG_SYMBOL_KIND_FUNC + : SCC_CFG_SYMBOL_KIND_EXTERN, .linkage = SCC_CFG_SYMBOL_LINK_GLOABL, .meta = meta}; meta->func.func = nullptr; diff --git a/libs/ir/mir/include/arch/scc_x86_isel.h b/libs/ir/mir/include/arch/scc_x86_isel.h index 9a2d63e..98bc607 100644 --- a/libs/ir/mir/include/arch/scc_x86_isel.h +++ b/libs/ir/mir/include/arch/scc_x86_isel.h @@ -20,13 +20,15 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module, // Utils void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst_reg, - scc_x86_operand_value_t src, u8 size); + scc_x86_operand_value_t src); void scc_x86_emit_load(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); void scc_x86_emit_store(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); 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, + u8 size); + static inline void emit_direct_call(scc_x86_64_isel_t *isel, const char *callee) { scc_mir_x86_instr_t instr = {0}; @@ -37,10 +39,11 @@ static inline void emit_direct_call(scc_x86_64_isel_t *isel, } static inline void emit_indirect_call(scc_x86_64_isel_t *isel, - scc_x86_operand_value_t reg) { + scc_x86_operand_value_t mem) { scc_mir_x86_instr_t instr = {0}; - scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_GPRV, reg, + scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_MEMV, mem, scc_pos_create()); + scc_vec_push(isel->instrs, instr); } static inline void emit_ret(scc_x86_64_isel_t *isel) { @@ -56,18 +59,16 @@ static inline void emit_ret(scc_x86_64_isel_t *isel) { scc_vec_push((isel)->instrs, instr); \ } while (0) -#define add_instr_1(isel, iform, arg1, _size) \ +#define add_instr_1(isel, iform, arg1) \ do { \ scc_mir_x86_instr_t instr; \ - (arg1).size = (_size); \ scc_mir_x86_instr_1(&instr, (iform), (arg1), (isel)->pos); \ scc_vec_push((isel)->instrs, instr); \ } while (0) -#define add_instr_2(isel, iform, arg1, arg2, _size) \ +#define add_instr_2(isel, iform, arg1, arg2) \ do { \ scc_mir_x86_instr_t instr; \ - (arg1).size = (_size); \ scc_mir_x86_instr_2(&instr, (iform), (arg1), (arg2), (isel)->pos); \ scc_vec_push((isel)->instrs, instr); \ } while (0) diff --git a/libs/ir/mir/include/arch/scc_x86_mir.h b/libs/ir/mir/include/arch/scc_x86_mir.h index 0de45dc..66675f6 100644 --- a/libs/ir/mir/include/arch/scc_x86_mir.h +++ b/libs/ir/mir/include/arch/scc_x86_mir.h @@ -9,16 +9,12 @@ #include typedef struct { - union { - int opcode; - scc_x86_iform_t iform; - }; - u8 num_operands; - scc_x86_operand_value_t operands[6]; + scc_x86_iform_t opcode; // must be int or enum + int num_operands; + scc_x86_operand_value_t operands[3]; scc_pos_t src_loc; } scc_x86_instr_t; -// x86 后端指令:首字段 int opcode(正 = scc_x86_iform_t,负 = 伪指令) typedef union scc_mir_x86_instr { scc_mir_instr_t instr; scc_x86_instr_t x86_instr; @@ -26,8 +22,6 @@ typedef union scc_mir_x86_instr { typedef SCC_VEC(scc_mir_x86_instr_t) scc_mir_x86_instr_vec_t; -// ── 基本块 values 强制转换 ────────────────────────────────────────────── - #define SCC_MIR_X86_BBLOCK_INSTRS(bb) ((scc_mir_x86_instr_vec_t *)&bb->values) #define SCC_MIR_X86_BBLOCK_INSTRS_C(bb) \ ((const scc_mir_x86_instr_vec_t *)&bb->values) @@ -51,13 +45,14 @@ static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op, } // slot_id 编码为 base=INVALID, disp=slot_id -static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id) { +static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id, u8 size) { 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; + o.size = size; return o; } @@ -68,13 +63,14 @@ static inline int scc_x86_op_slot_id(const scc_x86_operand_value_t *op) { return op->mem.disp.displacement; } -static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, int opcode, - scc_pos_t pos) { +static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, + scc_x86_iform_t opcode, scc_pos_t pos) { out->x86_instr.opcode = opcode; out->x86_instr.num_operands = 0; out->x86_instr.src_loc = pos; } -static inline void scc_mir_x86_instr_1(scc_mir_x86_instr_t *out, int opcode, +static inline void scc_mir_x86_instr_1(scc_mir_x86_instr_t *out, + scc_x86_iform_t opcode, scc_x86_operand_value_t op0, scc_pos_t pos) { out->x86_instr.opcode = opcode; @@ -82,7 +78,8 @@ static inline void scc_mir_x86_instr_1(scc_mir_x86_instr_t *out, int opcode, out->x86_instr.operands[0] = op0; out->x86_instr.src_loc = pos; } -static inline void scc_mir_x86_instr_2(scc_mir_x86_instr_t *out, int opcode, +static inline void scc_mir_x86_instr_2(scc_mir_x86_instr_t *out, + scc_x86_iform_t opcode, scc_x86_operand_value_t op0, scc_x86_operand_value_t op1, scc_pos_t pos) { @@ -92,11 +89,10 @@ static inline void scc_mir_x86_instr_2(scc_mir_x86_instr_t *out, int opcode, out->x86_instr.operands[1] = op1; out->x86_instr.src_loc = pos; } -static inline void scc_mir_x86_instr_3(scc_mir_x86_instr_t *out, int opcode, - scc_x86_operand_value_t op0, - scc_x86_operand_value_t op1, - scc_x86_operand_value_t op2, - scc_pos_t pos) { +static inline void +scc_mir_x86_instr_3(scc_mir_x86_instr_t *out, scc_x86_iform_t opcode, + scc_x86_operand_value_t op0, scc_x86_operand_value_t op1, + scc_x86_operand_value_t op2, scc_pos_t pos) { out->x86_instr.opcode = opcode; out->x86_instr.num_operands = 3; out->x86_instr.operands[0] = op0; @@ -105,4 +101,48 @@ static inline void scc_mir_x86_instr_3(scc_mir_x86_instr_t *out, int opcode, out->x86_instr.src_loc = pos; } +static inline scc_x86_iform_t +scc_mir_x86_mov_reg_mem(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_MEM); + return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_MEMB + : SCC_X86_IFORM_MOV_GPRV_MEMV; +} +static inline scc_x86_iform_t +scc_mir_x86_mov_mem_reg(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_MEM && op1.kind == SCC_X86_OPR_REG); + return op0.size == 1 ? SCC_X86_IFORM_MOV_MEMB_GPR8 + : SCC_X86_IFORM_MOV_MEMV_GPRV; +} +static inline scc_x86_iform_t +scc_mir_x86_mov_reg_reg(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_REG); + return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_GPR8_8A + : SCC_X86_IFORM_MOV_GPRV_GPRV_8B; +} + +static inline scc_x86_iform_t +scc_mir_x86_mov_reg_imm(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_IMM); + return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_IMMB_B0 + : SCC_X86_IFORM_MOV_GPRV_IMMV; +} + +void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, + scc_x86_operand_value_t dst, + scc_x86_operand_value_t src); +void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec, + scc_x86_operand_value_t dst, + scc_x86_operand_value_t src_addr); +void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec, + scc_x86_operand_value_t dst_addr, + scc_x86_operand_value_t src); + #endif /* __SCC_X86_MIR_H__ */ diff --git a/libs/ir/mir/include/core_pass/scc_reg_alloc.h b/libs/ir/mir/include/core_pass/scc_reg_alloc.h index abb9657..8e743a4 100644 --- a/libs/ir/mir/include/core_pass/scc_reg_alloc.h +++ b/libs/ir/mir/include/core_pass/scc_reg_alloc.h @@ -28,8 +28,10 @@ typedef struct scc_reg_alloc_op { void (*alloc_iter_begin)(scc_reg_alloc_iter_t *iter); cbool (*alloc_iter_next)(scc_reg_alloc_iter_t *iter, int *out_vreg, int *out_size, scc_reg_op_access_t *out_access); - void (*alloc_iter_replace_preg)(scc_reg_alloc_iter_t *iter, int preg); - void (*alloc_iter_replace_slot)(scc_reg_alloc_iter_t *iter, int slot); + void (*alloc_iter_replace_preg)(scc_reg_alloc_iter_t *iter, int preg, + int size); + void (*alloc_iter_replace_slot)(scc_reg_alloc_iter_t *iter, int slot, + int size); void (*alloc_iter_end)(scc_reg_alloc_iter_t *iter); // 读写属性与隐式寄存器 diff --git a/libs/ir/mir/src/arch/scc_x86_isel.c b/libs/ir/mir/src/arch/scc_x86_isel.c index 02b7a07..8f1b4f5 100644 --- a/libs/ir/mir/src/arch/scc_x86_isel.c +++ b/libs/ir/mir/src/arch/scc_x86_isel.c @@ -24,8 +24,8 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func, scc_tree_dump_append_fmt(td, " ???"); return; } - scc_x86_iform_t iform = instr->x86_instr.opcode; - const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform]; + scc_x86_iform_t opcode = instr->x86_instr.opcode; + const scc_x86_iform_info_t *info = &scc_x86_iform_table[opcode]; scc_tree_dump_append_fmt(td, " %s", info->iform_name); for (int i = 0; i < instr->x86_instr.num_operands; i += 1) { if (i == 0) @@ -63,12 +63,12 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func, scc_tree_dump_append_fmt(td, "(x%d)", op->mem.scale); } if (op->mem.disp.displacement != 0) { + i64 data = op->mem.disp.displacement < 0 + ? -op->mem.disp.displacement + : op->mem.disp.displacement; scc_tree_dump_append_fmt( - td, " %c %llu", - op->mem.disp.displacement >= 0 ? '+' : '-', - op->mem.disp.displacement < 0 - ? -op->mem.disp.displacement - : op->mem.disp.displacement); + td, " %c %lld/%#llx", + op->mem.disp.displacement >= 0 ? '+' : '-', data, data); } scc_tree_dump_append(td, ")"); } @@ -93,33 +93,34 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func, scc_tree_dump_append(td, ""); break; } - scc_tree_dump_append_fmt(td, "(%zu)", op->size); + scc_tree_dump_append_fmt(td, ".(%zu)", op->size); } } // 将 LIR 值转换为 x86 操作数 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, + u8 size) { scc_x86_operand_value_t op = {0}; switch (val->kind) { case SCC_LIR_INSTR_KIND_NONE: op.kind = SCC_X86_OPR_NONE; break; case SCC_LIR_INSTR_KIND_VREG: - op = scc_x86_op_vreg(val->data.reg); + op = scc_x86_op_vreg(val->data.reg, size); int id = 0; int ret = scc_mir_vreg_lookup(isel->func, val->data.reg, &id); if (ret > 0) { - op = scc_x86_op_preg(id); + op = scc_x86_op_preg(id, size); } else if (ret < 0) { - op = scc_x86_op_slot(id); + op = scc_x86_op_slot(id, size); } break; case SCC_LIR_INSTR_KIND_IMM: - op = scc_x86_op_imm(val->data.imm.data.digit); + op = scc_x86_op_imm(val->data.imm.data.digit, size); break; case SCC_LIR_INSTR_KIND_FIMM: - op = scc_x86_op_imm(*(i64 *)&val->data.fimm); + op = scc_x86_op_imm(*(i64 *)&val->data.fimm, size); break; case SCC_LIR_INSTR_KIND_SYMBOL: op = scc_x86_op_reloc_global_relrip(val->data.symbol, 0); @@ -127,6 +128,7 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, case SCC_LIR_INSTR_KIND_ARG: Assert(isel->abi_lowering.lower_param); isel->abi_lowering.lower_param(isel, val, &op); + op.size = size; break; default: Panic("unsupported lir instr kind %d", val->kind); @@ -159,20 +161,9 @@ static scc_x86_operand_value_t build_mem_op(scc_x86_64_isel_t *isel, } // 虚拟临时寄存器分配(简单递增) -static scc_x86_operand_value_t new_vreg_temp(scc_x86_64_isel_t *isel) { - return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func)); -} - -static void emit_compare(scc_x86_64_isel_t *isel, scc_x86_operand_value_t op0, - scc_x86_operand_value_t op1, u8 size) { - (void)size; - if (scc_x86_op_is_vreg(&op0) && op1.kind == SCC_X86_OPR_IMM) { - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, op0, op1, size); - } else if (scc_x86_op_is_vreg(&op0) && scc_x86_op_is_vreg(&op1)) { - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, op0, op1, size); - } else { - UNREACHABLE(); - } +static scc_x86_operand_value_t new_vreg_temp(scc_x86_64_isel_t *isel, + int size) { + return scc_x86_op_vreg(scc_mir_alloc_vreg(isel->func), size); } static scc_x86_iform_t cond_to_setcc(scc_lir_cond_t cond) { @@ -204,138 +195,75 @@ static scc_x86_iform_t cond_to_setcc(scc_lir_cond_t cond) { static void emit_copy_if_needed(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, - scc_x86_operand_value_t src0, u8 size) { + scc_x86_operand_value_t src0) { if (scc_x86_op_is_vreg(&dst) && scc_x86_op_is_vreg(&src0) && scc_x86_op_get_vreg(&dst) == scc_x86_op_get_vreg(&src0)) { return; } - scc_x86_emit_move(isel, dst, src0, size); + scc_x86_emit_move(isel, dst, src0); } static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op, scc_x86_operand_value_t dst, scc_x86_operand_value_t src0, - scc_x86_operand_value_t src1, u8 size) { - (void)size; - emit_copy_if_needed(isel, dst, src0, size); - dst.size = size; - src0.size = size; - src1.size = size; + scc_x86_operand_value_t src1) { + emit_copy_if_needed(isel, dst, src0); - bool is_imm = (src1.kind == SCC_X86_OPR_IMM); - scc_x86_iform_t iform; + Assert(src0.size == src1.size); + int is_8b = src0.size == 1; + int is_imm = src1.kind == SCC_X86_OPR_IMM; + scc_x86_iform_t opcode; switch (op) { case SCC_LIR_ADD: - iform = is_imm ? SCC_X86_IFORM_ADD_GPRV_IMMZ - : SCC_X86_IFORM_ADD_GPRV_GPRV_03; + opcode = is_imm ? SCC_X86_IFORM_ADD_GPRV_IMMZ + : SCC_X86_IFORM_ADD_GPRV_GPRV_03; break; case SCC_LIR_SUB: - iform = is_imm ? SCC_X86_IFORM_SUB_GPRV_IMMZ - : SCC_X86_IFORM_SUB_GPRV_GPRV_2B; + opcode = is_imm ? SCC_X86_IFORM_SUB_GPRV_IMMZ + : SCC_X86_IFORM_SUB_GPRV_GPRV_2B; break; case SCC_LIR_AND: - iform = is_imm ? SCC_X86_IFORM_AND_GPRV_IMMZ - : SCC_X86_IFORM_AND_GPRV_GPRV_23; + opcode = is_imm ? SCC_X86_IFORM_AND_GPRV_IMMZ + : SCC_X86_IFORM_AND_GPRV_GPRV_23; break; case SCC_LIR_OR: - iform = + opcode = is_imm ? SCC_X86_IFORM_OR_GPRV_IMMZ : SCC_X86_IFORM_OR_GPRV_GPRV_0B; break; case SCC_LIR_XOR: - iform = is_imm ? SCC_X86_IFORM_XOR_GPRV_IMMZ - : SCC_X86_IFORM_XOR_GPRV_GPRV_33; + opcode = is_imm ? SCC_X86_IFORM_XOR_GPRV_IMMZ + : SCC_X86_IFORM_XOR_GPRV_GPRV_33; break; default: UNREACHABLE(); } - add_instr_2(isel, iform, dst, src1, size); + add_instr_2(isel, opcode, dst, src1); } void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst_reg, - scc_x86_operand_value_t src, u8 size) { - if (size == 0) { - size = dst_reg.size; - } - if (dst_reg.size != src.size) { - LOG_WARN("Mismatched register sizes for move %d != %d", dst_reg.size, - src.size); - } - Assert(dst_reg.kind == SCC_X86_OPR_REG); - if (src.kind == SCC_X86_OPR_REG) { - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_8B, dst_reg, src, size); - } else if (src.kind == SCC_X86_OPR_IMM) { - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMV, dst_reg, src, size); - } else if (src.kind == SCC_X86_OPR_MEM || - (src.kind == SCC_X86_OPR_RELOC && - src.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL)) { - add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst_reg, src, size); - } else { - Panic("emit_move: unsupported src kind %d", src.kind); - } + scc_x86_operand_value_t src) { + scc_x86_emit_move_to_vec(&isel->instrs, dst_reg, src); } void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, - scc_x86_operand_value_t src, u8 size) { - if (size == 0) { - size = dst.size; - } - if (dst.size != src.size) { - LOG_WARN("Mismatched register sizes for store %d != %d", dst.size, - src.size); - } + scc_x86_operand_value_t src) { if (dst.kind != SCC_X86_OPR_REG) { - scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel); - scc_x86_emit_move(isel, tmp_reg, dst, size); + scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, dst.size); + scc_x86_emit_move(isel, tmp_reg, dst); dst = tmp_reg; } - scc_x86_operand_value_t mem_op; - if (src.kind == SCC_X86_OPR_REG) { - // 地址在寄存器中 -> 构造 [reg] - mem_op = (scc_x86_operand_value_t){ - .kind = SCC_X86_OPR_MEM, - .mem = {.base = src.reg, - .index = SCC_X86_REG_INVALID, - .scale = 1, - .disp = {.displacement = 0, .displacement_bits = size * 8}}, - }; - } else if (src.kind == SCC_X86_OPR_MEM) { - mem_op = src; - } else { - Panic("emit_load: src must be REG or MEM"); - } - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, mem_op, size); + + scc_x86_emit_load_to_vec(&isel->instrs, dst, src); } void scc_x86_emit_store(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, - scc_x86_operand_value_t src, u8 size) { - if (size == 0) { - size = dst.size; - } - if (dst.size != src.size) { - LOG_WARN("Mismatched register sizes for store %d != %d", dst.size, - src.size); - } + scc_x86_operand_value_t src) { if (src.kind != SCC_X86_OPR_REG) { - scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel); - scc_x86_emit_move(isel, tmp_reg, src, size); + scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, src.size); + scc_x86_emit_move(isel, tmp_reg, src); src = tmp_reg; } - scc_x86_operand_value_t mem_op; - if (dst.kind == SCC_X86_OPR_REG) { - mem_op = (scc_x86_operand_value_t){ - .kind = SCC_X86_OPR_MEM, - .mem = {.base = dst.reg, - .index = SCC_X86_REG_INVALID, - .scale = 1, - .disp = {.displacement = 0, .displacement_bits = 0}}}; - } else if (dst.kind == SCC_X86_OPR_MEM) { - mem_op = dst; - } else { - Panic("emit_store: dst_addr must be REG or MEM"); - } - mem_op.size = size; - src.size = size; - add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, mem_op, src, size); + scc_x86_emit_store_to_vec(&isel->instrs, dst, src); } static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, @@ -343,6 +271,7 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, scc_x86_operand_value_t index, int scale, i64 offset) { usize size = dst.size; + Assert(size == 8); // 前置断言:dst 必须是寄存器 Assert(dst.kind == SCC_X86_OPR_REG); // scale 必须是 1,2,4,8 之一 @@ -351,8 +280,8 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, // ---- 处理 base ---- scc_x86_operand_value_t base_reg = base; if (base.kind != SCC_X86_OPR_REG) { - base_reg = new_vreg_temp(isel); - scc_x86_emit_move(isel, base_reg, base, 8); + base_reg = new_vreg_temp(isel, size); + scc_x86_emit_move(isel, base_reg, base); } // ---- 处理 index * scale ---- @@ -360,8 +289,8 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, Assert(index.kind != SCC_X86_OPR_NONE); // 确保 index 在寄存器中 if (index.kind != SCC_X86_OPR_REG) { - scc_x86_operand_value_t index_tmp = new_vreg_temp(isel); - scc_x86_emit_move(isel, index_tmp, index, 8); + scc_x86_operand_value_t index_tmp = new_vreg_temp(isel, index.size); + scc_x86_emit_move(isel, index_tmp, index); index = index_tmp; } @@ -370,21 +299,20 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, if (base_reg.kind == SCC_X86_OPR_REG && scaled_index.kind == SCC_X86_OPR_REG) { if (dst.reg != base_reg.reg) { - scc_x86_emit_move(isel, dst, base_reg, 8); + scc_x86_emit_move(isel, dst, base_reg); sum = dst; } - add_instr_2(isel, SCC_X86_IFORM_ADD_GPRV_GPRV_03, sum, scaled_index, - size); + add_instr_2(isel, SCC_X86_IFORM_ADD_GPRV_GPRV_03, sum, scaled_index); } else if (base_reg.kind == SCC_X86_OPR_REG) { if (dst.reg != base_reg.reg) - scc_x86_emit_move(isel, dst, base_reg, 8); + scc_x86_emit_move(isel, dst, base_reg); sum = dst; } else if (scaled_index.kind == SCC_X86_OPR_REG) { - scc_x86_emit_move(isel, dst, scaled_index, 8); + scc_x86_emit_move(isel, dst, scaled_index); sum = dst; } else { // base 和 index 都无效 => 结果为 0 - scc_x86_emit_move(isel, dst, scc_x86_op_imm(0), 8); + scc_x86_emit_move(isel, dst, scc_x86_op_imm(0, size)); return; } @@ -393,33 +321,34 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, scc_x86_operand_value_t mem_op = build_mem_op( isel, sum, (scc_x86_operand_value_t){.kind = SCC_X86_OPR_NONE}, 1, offset); - scc_x86_emit_move(isel, dst, mem_op, 8); + scc_x86_emit_move(isel, dst, mem_op); } else if (sum.reg != dst.reg) { - scc_x86_emit_move(isel, dst, sum, 8); + scc_x86_emit_move(isel, dst, sum); } } 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 src0 = - scc_x86_lir_val_to_mir_op(isel, &instr->arg0); - scc_x86_operand_value_t src1 = - scc_x86_lir_val_to_mir_op(isel, &instr->arg1); u8 size = instr->size; + scc_x86_operand_value_t dst = + scc_x86_lir_val_to_mir_op(isel, &instr->to, size); + scc_x86_operand_value_t src0 = + scc_x86_lir_val_to_mir_op(isel, &instr->arg0, size); + scc_x86_operand_value_t src1 = + scc_x86_lir_val_to_mir_op(isel, &instr->arg1, size); switch (instr->op) { /* ---- 数据移动 ---- */ case SCC_LIR_LOAD: // src0 是地址(可能是寄存器或内存操作数),dst 是寄存器 - scc_x86_emit_load(isel, dst, src0, size); + scc_x86_emit_load(isel, dst, src0); break; case SCC_LIR_STORE: // src0 是要存储的值(寄存器),src1 是目标地址 - scc_x86_emit_store(isel, src1, src0, size); + scc_x86_emit_store(isel, src1, src0); break; case SCC_LIR_MOV: // 纯粹的寄存器/立即数复制 - scc_x86_emit_move(isel, dst, src0, size); + scc_x86_emit_move(isel, dst, src0); break; case SCC_LIR_LOAD_ADDR: // 计算地址,结果放入 dst(寄存器) @@ -428,10 +357,10 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { break; /* ---- 一元运算 ---- */ case SCC_LIR_NEG: - add_instr_1(isel, SCC_X86_IFORM_NEG_GPRV, dst, size); + add_instr_1(isel, SCC_X86_IFORM_NEG_GPRV, dst); break; case SCC_LIR_NOT: - add_instr_1(isel, SCC_X86_IFORM_NOT_GPRV, dst, size); + add_instr_1(isel, SCC_X86_IFORM_NOT_GPRV, dst); break; /* ---- 算术/逻辑二元运算 ---- */ case SCC_LIR_ADD: @@ -439,24 +368,23 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { case SCC_LIR_AND: case SCC_LIR_OR: case SCC_LIR_XOR: - emit_binary_op(isel, instr->op, dst, src0, src1, size); + emit_binary_op(isel, instr->op, dst, src0, src1); break; case SCC_LIR_MUL: - emit_copy_if_needed(isel, dst, src0, size); + emit_copy_if_needed(isel, dst, src0); if (src1.kind == SCC_X86_OPR_IMM) { - scc_x86_operand_value_t op = new_vreg_temp(isel); - scc_x86_emit_move(isel, op, src1, size); + scc_x86_operand_value_t op = new_vreg_temp(isel, size); + scc_x86_emit_move(isel, op, src1); src1 = op; } - add_instr_2(isel, SCC_X86_IFORM_IMUL_GPRV_GPRV, dst, src1, size); + add_instr_2(isel, SCC_X86_IFORM_IMUL_GPRV_GPRV, dst, src1); break; case SCC_LIR_SHL: case SCC_LIR_SHR: case SCC_LIR_SAR: { - emit_copy_if_needed(isel, dst, src0, size); - + emit_copy_if_needed(isel, dst, src0); if (src1.kind == SCC_X86_OPR_IMM) { scc_x86_iform_t iform; switch (instr->op) { @@ -472,10 +400,10 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { default: UNREACHABLE(); } - add_instr_2(isel, iform, dst, src1, size); + add_instr_2(isel, iform, dst, src1); } else { - scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL); - scc_x86_emit_move(isel, cl, src1, 1); + scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL, 1); + scc_x86_emit_move(isel, cl, src1); scc_x86_iform_t iform; switch (instr->op) { case SCC_LIR_SHL: @@ -490,7 +418,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { default: UNREACHABLE(); } - add_instr_2(isel, iform, dst, cl, size); + add_instr_2(isel, iform, dst, cl); } } break; @@ -499,44 +427,54 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { case SCC_LIR_DIV_U: case SCC_LIR_REM_S: case SCC_LIR_REM_U: { - scc_x86_operand_value_t rax = scc_x86_op_preg(SCC_X86_REG_RAX); - scc_x86_operand_value_t rdx = scc_x86_op_preg(SCC_X86_REG_RDX); + scc_x86_operand_value_t rax = scc_x86_op_preg(SCC_X86_REG_RAX, size); + scc_x86_operand_value_t rdx = scc_x86_op_preg(SCC_X86_REG_RDX, size); - scc_x86_emit_move(isel, rax, src0, size); + scc_x86_emit_move(isel, rax, src0); if (instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S) { add_instr_0(isel, SCC_X86_IFORM_CQO); } else { - scc_x86_operand_value_t zero = scc_x86_op_imm(0); - scc_x86_emit_move(isel, rdx, zero, size); + scc_x86_operand_value_t zero = scc_x86_op_imm(0, size); + scc_x86_emit_move(isel, rdx, zero); } scc_x86_iform_t div_if = (instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S) ? SCC_X86_IFORM_IDIV_GPRV : SCC_X86_IFORM_DIV_GPRV; - add_instr_1(isel, div_if, src1, size); + add_instr_1(isel, div_if, src1); if (instr->op == SCC_LIR_REM_S || instr->op == SCC_LIR_REM_U) - scc_x86_emit_move(isel, dst, rdx, size); + scc_x86_emit_move(isel, dst, rdx); else - scc_x86_emit_move(isel, dst, rax, size); + scc_x86_emit_move(isel, dst, rax); } break; /* ---- 比较指令 ---- */ case SCC_LIR_CMP: { + Assert(src0.size == src1.size); if (scc_x86_op_is_vreg(&src0) && src1.kind == SCC_X86_OPR_IMM) - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, src0, src1, size); + add_instr_2(isel, + src0.size == 1 ? SCC_X86_IFORM_CMP_GPR8_IMMB_82R7 + : SCC_X86_IFORM_CMP_GPRV_IMMZ, + src0, src1); else if (scc_x86_op_is_vreg(&src0) && scc_x86_op_is_vreg(&src1)) - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, src0, src1, size); + add_instr_2(isel, + src0.size == 1 ? SCC_X86_IFORM_CMP_GPR8_GPR8_3A + : SCC_X86_IFORM_CMP_GPRV_GPRV_3B, + src0, src1); else UNREACHABLE(); scc_x86_iform_t setcc = cond_to_setcc(instr->metadata.cond); - add_instr_1(isel, setcc, dst, size); + add_instr_1(isel, setcc, dst); if (size > 1) { - scc_x86_operand_value_t one = scc_x86_op_imm(1); - add_instr_2(isel, SCC_X86_IFORM_AND_GPRV_IMMZ, dst, one, size); + scc_x86_operand_value_t one = scc_x86_op_imm(1, size); + add_instr_2(isel, + src1.size == 1 ? SCC_X86_IFORM_AND_GPR8_IMMB_82R4 + : SCC_X86_IFORM_AND_GPRV_IMMZ, + dst, one); } } break; @@ -546,22 +484,26 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { scc_x86_op_reloc_block(instr->metadata.br.true_target, 0); scc_x86_operand_value_t false_bb = scc_x86_op_reloc_block(instr->metadata.br.false_target, 0); - - add_instr_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0, size); - add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb, size); - add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb, size); + true_bb.size = instr->size; + false_bb.size = instr->size; + add_instr_2(isel, + src0.size == 1 ? SCC_X86_IFORM_TEST_GPR8_GPR8 + : 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_JMP_RELBRZ, false_bb); } break; case SCC_LIR_JMP: { scc_x86_operand_value_t jmp_bb = scc_x86_op_reloc_block(instr->metadata.jmp_target, 0); - add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb, size); + add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb); } break; /* ---- 栈分配 ---- */ case SCC_LIR_ALLOCA: { scc_x86_operand_value_t op = - scc_x86_lir_val_to_mir_op(isel, &instr->to); + scc_x86_lir_val_to_mir_op(isel, &instr->to, instr->size); scc_mir_x86_instr_t x86instr; x86instr.instr.opcode = SCC_MIR_PSEUDO_ALLOCA; Assert(op.kind == SCC_X86_OPR_REG); @@ -588,13 +530,8 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { isel->abi_lowering.lower_call(isel, instr); } break; case SCC_LIR_CALL_INDIRECT: { - TODO(); - // 假设函数指针的 LIR 值在某个 vreg 中 - // scc_x86_operand_value_t func_ptr_op = - // scc_x86_lir_val_to_mir_op(isel, &func_ptr_val); - // scc_x86_operand_value_t temp_reg = new_vreg_temp(isel); - // scc_x86_emit_lea(isel, temp_reg, func_ptr_op); // 确保得到地址 - // emit_indirect_call(isel, temp_reg); + Assert(isel->abi_lowering.lower_call); + isel->abi_lowering.lower_call(isel, instr); } break; case SCC_LIR_RET: { Assert(isel->abi_lowering.lower_ret); @@ -607,18 +544,18 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { // 将 dest 的地址放入 RDI scc_x86_operand_value_t dest_op = - scc_x86_lir_val_to_mir_op(isel, &dest_val); - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDI), dest_op, 8); + scc_x86_lir_val_to_mir_op(isel, &dest_val, 8); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDI, 8), dest_op); // 将 src 的地址放入 RSI scc_x86_operand_value_t src_op = - scc_x86_lir_val_to_mir_op(isel, &src_val); - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RSI), src_op, 8); + scc_x86_lir_val_to_mir_op(isel, &src_val, 8); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RSI, 8), src_op); // 长度处理保持不变... scc_x86_operand_value_t len_op = - scc_x86_lir_val_to_mir_op(isel, &instr->metadata.memcpy.size); - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX), len_op, 8); + scc_x86_lir_val_to_mir_op(isel, &instr->metadata.memcpy.size, 8); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX, 8), len_op); add_instr_0(isel, SCC_X86_IFORM_REP_MOVSB); } break; @@ -639,6 +576,11 @@ static void sel_func(const scc_lir_module_t *lir_module, scc_lir_instr_vec_t *instrs = SCC_LIR_BBLOCK_VALUES(bb); scc_vec_foreach(*instrs, i) { const scc_lir_instr_t *ins = &scc_vec_at(*instrs, i); + // HACK BR size + if (ins->op == SCC_LIR_CMP && i + 1 < scc_vec_size(*instrs) && + scc_vec_at(*instrs, i + 1).op == SCC_LIR_BR) { + scc_vec_at(*instrs, i + 1).size = ins->size; + } sel_mir(isel, ins); } diff --git a/libs/ir/mir/src/arch/scc_x86_mir.c b/libs/ir/mir/src/arch/scc_x86_mir.c new file mode 100644 index 0000000..62385f4 --- /dev/null +++ b/libs/ir/mir/src/arch/scc_x86_mir.c @@ -0,0 +1,92 @@ +#include + +void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, + scc_x86_operand_value_t dst, + scc_x86_operand_value_t src) { + if (dst.size != src.size) { + LOG_WARN("Mismatched register sizes for move %d != %d", dst.size, + src.size); + } + Assert(dst.kind == SCC_X86_OPR_REG); + scc_mir_x86_instr_t ins; + if (src.kind == SCC_X86_OPR_REG) { + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_reg_reg(dst, src), dst, src, + scc_pos_create()); + } else if (src.kind == SCC_X86_OPR_IMM) { + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_reg_imm(dst, src), dst, src, + scc_pos_create()); + } else if (src.kind == SCC_X86_OPR_MEM || + (src.kind == SCC_X86_OPR_RELOC && + src.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL)) { + scc_mir_x86_instr_2(&ins, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src, + scc_pos_create()); + } else { + Panic("emit_move: unsupported src kind %d", src.kind); + } + scc_vec_push(*vec, ins); +} + +void scc_x86_emit_load_to_vec(scc_mir_x86_instr_vec_t *vec, + scc_x86_operand_value_t dst, + scc_x86_operand_value_t src_addr) { + if (dst.size != src_addr.size) { + LOG_WARN("Mismatched sizes for load %d != %d", dst.size, src_addr.size); + } + Assert(dst.kind == SCC_X86_OPR_REG); + scc_x86_operand_value_t mem_op; + if (src_addr.kind == SCC_X86_OPR_REG) { + mem_op = (scc_x86_operand_value_t){ + .kind = SCC_X86_OPR_MEM, + .mem = + { + .base = src_addr.reg, + .index = SCC_X86_REG_INVALID, + .scale = 1, + .disp.displacement = 0, + .disp.displacement_bits = src_addr.size * 8, + }, + .size = src_addr.size, + }; + } else if (src_addr.kind == SCC_X86_OPR_MEM) { + mem_op = src_addr; + } else { + Panic("emit_load: src must be REG or MEM"); + } + scc_mir_x86_instr_t ins; + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_reg_mem(dst, mem_op), dst, mem_op, + scc_pos_create()); + scc_vec_push(*vec, ins); +} + +void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec, + scc_x86_operand_value_t dst_addr, + scc_x86_operand_value_t src) { + if (dst_addr.size != src.size) { + LOG_WARN("Mismatched sizes for store %d != %d", dst_addr.size, + src.size); + } + Assert(src.kind == SCC_X86_OPR_REG); + scc_x86_operand_value_t mem_op; + if (dst_addr.kind == SCC_X86_OPR_REG) { + mem_op = (scc_x86_operand_value_t){ + .kind = SCC_X86_OPR_MEM, + .mem = + { + .base = dst_addr.reg, + .index = SCC_X86_REG_INVALID, + .scale = 1, + .disp.displacement = 0, + .disp.displacement_bits = dst_addr.size * 8, + }, + .size = dst_addr.size, + }; + } else if (dst_addr.kind == SCC_X86_OPR_MEM) { + mem_op = dst_addr; + } else { + Panic("emit_store: dst_addr must be REG or MEM"); + } + scc_mir_x86_instr_t ins; + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_mem_reg(mem_op, src), mem_op, src, + scc_pos_create()); + scc_vec_push(*vec, ins); +} \ No newline at end of file diff --git a/libs/ir/mir/src/arch/scc_x86_reg_alloc.c b/libs/ir/mir/src/arch/scc_x86_reg_alloc.c index 578998e..fbc303b 100644 --- a/libs/ir/mir/src/arch/scc_x86_reg_alloc.c +++ b/libs/ir/mir/src/arch/scc_x86_reg_alloc.c @@ -6,42 +6,27 @@ static void emit_spill(void *out, int preg, int slot, int size) { scc_mir_x86_instr_vec_t *vec = out; - scc_x86_operand_value_t val_slot = scc_x86_op_slot(slot); - scc_x86_operand_value_t val_preg = scc_x86_op_preg(preg); - val_slot.size = size; - val_preg.size = size; - scc_mir_x86_instr_t ins = { - .x86_instr.opcode = SCC_X86_IFORM_MOV_MEMV_GPRV, - .x86_instr.num_operands = 2, - .x86_instr.operands = {val_slot, val_preg}, - }; - scc_vec_push(*vec, ins); + scc_x86_operand_value_t val_slot = scc_x86_op_slot(slot, size); + scc_x86_operand_value_t val_preg = scc_x86_op_preg(preg, size); + scc_x86_emit_store_to_vec(vec, val_slot, val_preg); } static void emit_reload(void *out, int preg, int slot, int size) { - scc_x86_operand_value_t val_slot = scc_x86_op_slot(slot); - scc_x86_operand_value_t val_preg = scc_x86_op_preg(preg); - val_slot.size = size; - val_preg.size = size; scc_mir_x86_instr_vec_t *vec = out; - scc_mir_x86_instr_t ins = {.x86_instr.opcode = SCC_X86_IFORM_MOV_GPRV_MEMV, - .x86_instr.num_operands = 2, - .x86_instr.operands = {val_preg, val_slot}}; - scc_vec_push(*vec, ins); + scc_x86_operand_value_t val_slot = scc_x86_op_slot(slot, size); + scc_x86_operand_value_t val_preg = scc_x86_op_preg(preg, size); + scc_x86_emit_load_to_vec(vec, val_preg, val_slot); } static void emit_copy(void *out, int dst_preg, int src_preg, int size) { - (void)size; scc_mir_x86_instr_vec_t *vec = out; - scc_mir_x86_instr_t ins = { - .x86_instr.opcode = SCC_X86_IFORM_MOV_GPRV_GPRV_8B, - .x86_instr.num_operands = 2, - .x86_instr.operands = {scc_x86_op_preg(dst_preg), - scc_x86_op_preg(src_preg)}}; - scc_vec_push(*vec, ins); + scc_x86_operand_value_t val_dst = scc_x86_op_preg(dst_preg, size); + scc_x86_operand_value_t val_src = scc_x86_op_preg(src_preg, size); + scc_x86_emit_move_to_vec(vec, val_dst, val_src); } -static scc_reg_op_access_t get_operand_access(int opcode, int op_idx) { +static scc_reg_op_access_t get_operand_access(scc_x86_iform_t opcode, + int op_idx) { if (opcode >= 0 && opcode < SCC_X86_IFORM_COUNT) { const scc_x86_iform_info_t *info = &scc_x86_iform_table[opcode]; if (op_idx >= info->num_ops || op_idx < 0) @@ -137,14 +122,14 @@ static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg, int *out_size, scc_reg_op_access_t *out_access) { const scc_mir_x86_instr_t *ins = (const scc_mir_x86_instr_t *)iter->instr; - int opcode = ins->x86_instr.opcode; + scc_x86_iform_t opcode = ins->x86_instr.opcode; int num_ops = ins->x86_instr.num_operands; while (iter->op_idx < num_ops) { const scc_x86_operand_value_t *op = &ins->x86_instr.operands[iter->op_idx]; - scc_reg_op_access_t base_access = - get_operand_access(opcode, iter->op_idx); + scc_reg_op_access_t base_access = SCC_REG_ALLOC_OP_ACCESS_READWRITE; + // base_access = get_operand_access(opcode, iter->op_idx); *out_size = op->size; if (op->kind == SCC_X86_OPR_REG) { @@ -159,6 +144,7 @@ static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg, continue; } else if (op->kind == SCC_X86_OPR_MEM) { const scc_x86_mem_t *mem = &op->mem; + *out_size = 8; // 子索引 0: 基址寄存器 if (iter->op_sub_idx == 0) { if (mem->base != SCC_X86_REG_INVALID && @@ -195,7 +181,9 @@ static cbool x86_alloc_iter_next(scc_reg_alloc_iter_t *iter, int *out_vreg, return false; } -static void x86_alloc_iter_replace_preg(scc_reg_alloc_iter_t *iter, int preg) { +static void x86_alloc_iter_replace_preg(scc_reg_alloc_iter_t *iter, int preg, + int size) { + (void)size; scc_mir_x86_instr_t *ins = (scc_mir_x86_instr_t *)iter->instr; int op_idx = iter->op_idx; int sub_idx = iter->op_sub_idx; @@ -220,11 +208,12 @@ static void x86_alloc_iter_replace_preg(scc_reg_alloc_iter_t *iter, int preg) { } } -static void x86_alloc_iter_replace_slot(scc_reg_alloc_iter_t *iter, int slot) { +static void x86_alloc_iter_replace_slot(scc_reg_alloc_iter_t *iter, int slot, + int size) { scc_mir_x86_instr_t *ins = (scc_mir_x86_instr_t *)iter->instr; int op_idx = iter->op_idx; if (op_idx < ins->x86_instr.num_operands && iter->op_sub_idx == 0) { - ins->x86_instr.operands[op_idx] = scc_x86_op_slot(slot); + ins->x86_instr.operands[op_idx] = scc_x86_op_slot(slot, size); } else { Panic("x86_alloc_iter_replace_slot: invalid op_idx"); } diff --git a/libs/ir/mir/src/reg_alloc/reg_alloc.c b/libs/ir/mir/src/reg_alloc/reg_alloc.c index 6ef0d8a..d1073ef 100644 --- a/libs/ir/mir/src/reg_alloc/reg_alloc.c +++ b/libs/ir/mir/src/reg_alloc/reg_alloc.c @@ -43,7 +43,7 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx, if (mapping == 1) { ops->mark_reg_used(ctx, preg); - ops->alloc_iter_replace_preg(&iter, preg); + ops->alloc_iter_replace_preg(&iter, preg, size); continue; } if (mapping == 0) @@ -58,7 +58,7 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx, access == SCC_REG_ALLOC_OP_ACCESS_READWRITE) ops->emit_spill(&after, preg, slot, size); - ops->alloc_iter_replace_preg(&iter, preg); + ops->alloc_iter_replace_preg(&iter, preg, size); } ops->alloc_iter_end(&iter); diff --git a/libs/ir/mir/src/target/win64_abi.c b/libs/ir/mir/src/target/win64_abi.c index 2ef07dd..ff28e37 100644 --- a/libs/ir/mir/src/target/win64_abi.c +++ b/libs/ir/mir/src/target/win64_abi.c @@ -29,13 +29,16 @@ static void frame_alloc_impl(scc_frame_layout_t *ctx, ctx->offset += slot->size; slot->offset = ctx->offset; } - *op = scc_x86_op_mem((scc_x86_mem_t){ - .seg = SCC_X86_REG_INVALID, - .base = SCC_X86_REG_RSP, - .disp = {.displacement = -slot->offset}, - .index = SCC_X86_REG_INVALID, - .scale = 1, - }); + + *op = scc_x86_op_mem( + (scc_x86_mem_t){ + .seg = SCC_X86_REG_INVALID, + .base = SCC_X86_REG_RSP, + .disp = {.displacement = -slot->offset}, + .index = SCC_X86_REG_INVALID, + .scale = 1, + }, + op->size); } } } @@ -76,11 +79,12 @@ static void prologue(scc_mir_instr_vec_t *userdata, /// FILL to shadow space } + u8 size = 8; // sub rsp, frame_size if (frame_size > 0) { scc_mir_x86_instr_2(&instr, SCC_X86_IFORM_SUB_GPRV_IMMZ, - scc_x86_op_preg(SCC_X86_REG_RSP), - scc_x86_op_imm(frame_size), scc_pos_create()); + scc_x86_op_preg(SCC_X86_REG_RSP, size), + scc_x86_op_imm(frame_size, size), scc_pos_create()); scc_vec_push(*instrs, instr); } } @@ -98,12 +102,12 @@ static void epilogue(scc_mir_instr_vec_t *userdata, */ scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); int frame_size = meta->frame_size; - + u8 size = 8; // add rsp, frame_size if (frame_size > 0) { scc_mir_x86_instr_2(&instr, SCC_X86_IFORM_ADD_GPRV_IMMZ, - scc_x86_op_preg(SCC_X86_REG_RSP), - scc_x86_op_imm(frame_size), scc_pos_create()); + scc_x86_op_preg(SCC_X86_REG_RSP, size), + scc_x86_op_imm(frame_size, size), scc_pos_create()); scc_vec_push(*instrs, instr); } } @@ -131,41 +135,52 @@ void scc_win_pc_x64_prolog_epilog_init(scc_prolog_epilog_t *ctx) { static void lower_call(void *userdata, const scc_lir_instr_t *instr) { scc_x86_64_isel_t *isel = userdata; + u8 size = 8; for (int i = instr->metadata.call.arg_count - 1; i >= 0; i -= 1) { scc_lir_val_t *args = &instr->metadata.call.args[i]; switch (i) { case 0: - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX), - scc_x86_lir_val_to_mir_op(isel, args), 8); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX, size), + scc_x86_lir_val_to_mir_op(isel, args, size)); break; case 1: - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDX), - scc_x86_lir_val_to_mir_op(isel, args), 8); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDX, size), + scc_x86_lir_val_to_mir_op(isel, args, size)); break; case 2: - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_R8), - scc_x86_lir_val_to_mir_op(isel, args), 8); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_R8, size), + scc_x86_lir_val_to_mir_op(isel, args, size)); break; case 3: - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_R9), - scc_x86_lir_val_to_mir_op(isel, args), 8); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_R9, size), + scc_x86_lir_val_to_mir_op(isel, args, size)); break; default: - scc_x86_operand_value_t op = scc_x86_lir_val_to_mir_op(isel, args); - add_instr_1(isel, - op.kind == SCC_X86_OPR_REG ? SCC_X86_IFORM_PUSH_GPRV_50 - : SCC_X86_IFORM_PUSH_IMMZ, - op, 8); + scc_x86_operand_value_t op = + scc_x86_lir_val_to_mir_op(isel, args, size); + TODO(); + add_instr_1(isel, SCC_X86_ICLASS_PUSH, op); break; } } - emit_direct_call(isel, instr->metadata.call.callee); + if (instr->op == SCC_LIR_CALL) { + emit_direct_call(isel, instr->metadata.call.callee_name); + } else if (instr->op == SCC_LIR_CALL_INDIRECT) { + Assert(instr->metadata.call.callee_target.kind == + SCC_LIR_INSTR_KIND_SYMBOL); + emit_indirect_call( + isel, scc_x86_op_reloc_global_mem( + instr->metadata.call.callee_target.data.symbol, 0)); + } else { + Panic("unhandled opcode"); + } scc_x86_operand_value_t ret_reg = - scc_x86_lir_val_to_mir_op(isel, &instr->to); + scc_x86_lir_val_to_mir_op(isel, &instr->to, size); if (ret_reg.kind != SCC_X86_OPR_NONE) { - scc_x86_emit_move(isel, ret_reg, scc_x86_op_preg(SCC_X86_REG_RAX), 8); + scc_x86_emit_move(isel, ret_reg, + scc_x86_op_preg(SCC_X86_REG_RAX, size)); } } @@ -173,21 +188,22 @@ static void lower_param(void *userdata, const scc_lir_val_t *val, void *out_op) { scc_x86_operand_value_t *out = out_op; Assert(val->kind == SCC_LIR_INSTR_KIND_ARG); + u8 size = 8; switch (val->data.arg) { case 0: - *out = scc_x86_op_preg(SCC_X86_REG_RCX); + *out = scc_x86_op_preg(SCC_X86_REG_RCX, size); break; case 1: - *out = scc_x86_op_preg(SCC_X86_REG_RDX); + *out = scc_x86_op_preg(SCC_X86_REG_RDX, size); break; case 2: - *out = scc_x86_op_preg(SCC_X86_REG_R8); + *out = scc_x86_op_preg(SCC_X86_REG_R8, size); break; case 3: - *out = scc_x86_op_preg(SCC_X86_REG_R9); + *out = scc_x86_op_preg(SCC_X86_REG_R9, size); break; default: - *out = scc_x86_op_slot(-val->data.arg); + *out = scc_x86_op_slot(-val->data.arg, size); break; } } @@ -195,9 +211,15 @@ static void lower_param(void *userdata, const scc_lir_val_t *val, static void lower_ret(void *userdata, const scc_lir_instr_t *instr) { scc_x86_64_isel_t *isel = userdata; scc_lir_val_t ret_val = instr->metadata.ret_val; + u8 size = 0; + if (instr->size) { + size = instr->size; + } else { + size = 8; + } if (ret_val.kind != SCC_LIR_INSTR_KIND_NONE) { - scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RAX), - scc_x86_lir_val_to_mir_op(isel, &ret_val), 8); + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RAX, size), + scc_x86_lir_val_to_mir_op(isel, &ret_val, size)); } emit_ret(isel); } diff --git a/libs/ir2mcode/src/scc_ir2mcode.c b/libs/ir2mcode/src/scc_ir2mcode.c index 78725ba..65563ce 100644 --- a/libs/ir2mcode/src/scc_ir2mcode.c +++ b/libs/ir2mcode/src/scc_ir2mcode.c @@ -83,6 +83,8 @@ void mir_x86_to_mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs, } } + // scc_x86_iform_t iform = + // scc_x86_iclass_to_iform(ins->opcode, ops, ins->num_operands); scc_x86_encode_inst(mcode, ins->opcode, ops); if (!skip_reloc && reloc.target_kind != SCC_RELOC_TARGET_NONE) { reloc.offset = scc_mcode_size(mcode); diff --git a/libs/mcode/include/x86/scc_x86_encode.h b/libs/mcode/include/x86/scc_x86_encode.h index 9fc9895..4e592f4 100644 --- a/libs/mcode/include/x86/scc_x86_encode.h +++ b/libs/mcode/include/x86/scc_x86_encode.h @@ -45,33 +45,52 @@ typedef struct { scc_x86_mem_t mem; scc_x86_reloc_op_t reloc; }; - usize size; + u8 size; } 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}; +static inline scc_x86_operand_value_t scc_x86_op_preg(scc_x86_reg_t reg, + u8 size) { + scc_x86_operand_value_t o = { + .kind = SCC_X86_OPR_REG, + .reg = reg, + .size = size, + }; return o; } static inline scc_x86_reg_t scc_x86_op_vreg_reg(int vreg) { return (int)SCC_X86_REG_COUNT + vreg; } -static inline scc_x86_operand_value_t scc_x86_op_vreg(int vreg) { +static inline scc_x86_operand_value_t scc_x86_op_vreg(int vreg, u8 size) { scc_x86_operand_value_t o = { .kind = SCC_X86_OPR_REG, .reg = scc_x86_op_vreg_reg(vreg), + .size = size, }; 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}; + scc_x86_operand_value_t o = { + .kind = SCC_X86_OPR_RELBR, + .brdisp = rel, + .size = 4, + }; 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}; +static inline scc_x86_operand_value_t scc_x86_op_imm(i64 imm, u8 size) { + scc_x86_operand_value_t o = { + .kind = SCC_X86_OPR_IMM, + .simm0 = imm, + .size = size, + }; 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}; +static inline scc_x86_operand_value_t scc_x86_op_mem(scc_x86_mem_t mem, + u8 size) { + scc_x86_operand_value_t o = { + .kind = SCC_X86_OPR_MEM, + .mem = mem, + .size = size, + }; return o; } @@ -83,6 +102,7 @@ scc_x86_op_reloc_global_imm(const char *sym, i64 addend) { op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL; op.reloc.global_name = sym; op.reloc.addend = addend; + op.size = 0; return op; } @@ -93,6 +113,7 @@ scc_x86_op_reloc_global_relrip(const char *sym, i64 addend) { op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL; op.reloc.global_name = sym; op.reloc.addend = addend; + op.size = 4; return op; } @@ -104,6 +125,7 @@ scc_x86_op_reloc_global_relbr(const char *sym, i64 addend) { op.reloc.target = SCC_X86_RELOC_TARGET_SYMBOL; op.reloc.global_name = sym; op.reloc.addend = addend; + op.size = 4; return op; } @@ -115,6 +137,7 @@ static inline scc_x86_operand_value_t scc_x86_op_reloc_block(int bid, op.reloc.target = SCC_X86_RELOC_TARGET_BBLOCK; op.reloc.bblock_id = bid; op.reloc.addend = addend; + op.size = 4; return op; } @@ -128,11 +151,15 @@ scc_x86_op_reloc_global_mem(const char *sym, i64 addend) { op.reloc.global_name = sym; op.reloc.addend = addend; // 编码时需生成 RIP 相对寻址的 ModRM/SIB + op.size = 0; return op; } /* 按 iform 发射一条指令,ops 数组长度需与 iform 定义的操作数数目一致 */ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, const scc_x86_operand_value_t *ops); +scc_x86_iform_t scc_x86_iclass_to_iform(scc_x86_iclass_t iclass, + const scc_x86_operand_value_t *ops, + int num_ops); #endif /* __SCC_X86_ENCODE_H__ */ diff --git a/libs/mcode/src/scc_x86_encode.c b/libs/mcode/src/scc_x86_encode.c index 21cc42b..385d24b 100644 --- a/libs/mcode/src/scc_x86_encode.c +++ b/libs/mcode/src/scc_x86_encode.c @@ -60,7 +60,14 @@ static int infer_operand_width(const scc_x86_iform_info_t *info, const scc_x86_operand_value_t ops[]) { for (int i = 0; i < info->num_explicit_ops; i++) { if (ops[i].kind == SCC_X86_OPR_REG && !info->ops[i].is_implicit) { - uint16_t w = scc_reg_width(ops[i].reg); + uint16_t w; + if (ops[i].size > 0 && ops[i].reg >= SCC_X86_REG_R8 && + ops[i].reg <= SCC_X86_REG_R15) { + /* R8-R15:宽度由 size 字段推导 */ + w = ops[i].size * 8; + } else { + w = scc_reg_width(ops[i].reg); + } if (w > 0) return w; } @@ -177,7 +184,8 @@ static void emit_escape_map(scc_mcode_t *m, const scc_x86_encoding_t *enc) { } static void emit_opcode(scc_mcode_t *m, const scc_x86_encoding_t *enc, - scc_x86_reg_t rm_reg, scc_x86_reg_t base_reg) { + scc_x86_reg_t rm_reg, scc_x86_reg_t base_reg, + int op_width) { for (int i = 0; i < enc->opcode_len; i++) { uint8_t byte = enc->opcode[i]; if (enc->partial_opcode && i == enc->opcode_len - 1) { @@ -186,6 +194,9 @@ static void emit_opcode(scc_mcode_t *m, const scc_x86_encoding_t *enc, if (target != SCC_X86_REG_INVALID) byte |= (reg_low3(target) & 7); } + /* MOV r8, imm8: B8-BF → B0-B7 */ + if (op_width == 8 && (byte & 0xF8) == 0xB8) + byte -= 8; emit_u8(m, byte); } } @@ -442,100 +453,6 @@ static void emit_modrm_sib_disp(scc_mcode_t *m, } } -static scc_x86_iform_t adapt_iform_to_8bit(scc_x86_iform_t iform, - const scc_x86_operand_value_t *ops, - int num_ops) { - // 只处理第一个操作数是 8 - // 位寄存器的情况(大多数指令的目标或源是第一个寄存器) - if (num_ops > 0 && ops[0].kind == SCC_X86_OPR_REG && - scc_reg_width(ops[0].reg) == 8) { - switch (iform) { - // ---- MOV 类 ---- - case SCC_X86_IFORM_MOV_GPRV_IMMV: - case SCC_X86_IFORM_MOV_GPRV_IMMZ: - return SCC_X86_IFORM_MOV_GPR8_IMMB_B0; - case SCC_X86_IFORM_MOV_GPRV_GPRV_89: // mov r/m, r - return SCC_X86_IFORM_MOV_GPR8_GPR8_88; - case SCC_X86_IFORM_MOV_GPRV_GPRV_8B: // mov r, r/m - return SCC_X86_IFORM_MOV_GPR8_GPR8_8A; - case SCC_X86_IFORM_MOV_GPRV_MEMV: // mov r, mem - return SCC_X86_IFORM_MOV_GPR8_MEMB; - case SCC_X86_IFORM_MOV_MEMV_GPRV: // mov mem, r - return SCC_X86_IFORM_MOV_MEMB_GPR8; - // ---- ADD ---- - case SCC_X86_IFORM_ADD_GPRV_IMMB: - case SCC_X86_IFORM_ADD_GPRV_IMMZ: - return SCC_X86_IFORM_ADD_GPR8_IMMB_80R0; - case SCC_X86_IFORM_ADD_GPRV_GPRV_01: // add r/m, r - return SCC_X86_IFORM_ADD_GPR8_GPR8_00; - case SCC_X86_IFORM_ADD_GPRV_GPRV_03: // add r, r/m - return SCC_X86_IFORM_ADD_GPR8_GPR8_02; - // ---- SUB ---- - case SCC_X86_IFORM_SUB_GPRV_IMMB: - case SCC_X86_IFORM_SUB_GPRV_IMMZ: - return SCC_X86_IFORM_SUB_GPR8_IMMB_80R5; - case SCC_X86_IFORM_SUB_GPRV_GPRV_29: - return SCC_X86_IFORM_SUB_GPR8_GPR8_28; - case SCC_X86_IFORM_SUB_GPRV_GPRV_2B: - return SCC_X86_IFORM_SUB_GPR8_GPR8_2A; - // ---- CMP ---- - case SCC_X86_IFORM_CMP_GPRV_IMMB: - case SCC_X86_IFORM_CMP_GPRV_IMMZ: - return SCC_X86_IFORM_CMP_GPR8_IMMB_80R7; - case SCC_X86_IFORM_CMP_GPRV_GPRV_39: - return SCC_X86_IFORM_CMP_GPR8_GPR8_38; - case SCC_X86_IFORM_CMP_GPRV_GPRV_3B: - return SCC_X86_IFORM_CMP_GPR8_GPR8_3A; - // ---- AND ---- - case SCC_X86_IFORM_AND_GPRV_IMMB: - case SCC_X86_IFORM_AND_GPRV_IMMZ: - return SCC_X86_IFORM_AND_GPR8_IMMB_80R4; - case SCC_X86_IFORM_AND_GPRV_GPRV_21: - return SCC_X86_IFORM_AND_GPR8_GPR8_20; - // ---- OR ---- - case SCC_X86_IFORM_OR_GPRV_IMMB: - case SCC_X86_IFORM_OR_GPRV_IMMZ: - return SCC_X86_IFORM_OR_GPR8_IMMB_80R1; - case SCC_X86_IFORM_OR_GPRV_GPRV_09: - return SCC_X86_IFORM_OR_GPR8_GPR8_08; - // ---- XOR ---- - case SCC_X86_IFORM_XOR_GPRV_IMMB: - case SCC_X86_IFORM_XOR_GPRV_IMMZ: - return SCC_X86_IFORM_XOR_GPR8_IMMB_80R6; - case SCC_X86_IFORM_XOR_GPRV_GPRV_31: - return SCC_X86_IFORM_XOR_GPR8_GPR8_30; - // ---- TEST ---- - case SCC_X86_IFORM_TEST_GPRV_GPRV: - return SCC_X86_IFORM_TEST_GPR8_GPR8; - case SCC_X86_IFORM_TEST_GPRV_IMMZ_F7R0: - return SCC_X86_IFORM_TEST_GPR8_IMMB_F6R0; - // ---- INC/DEC ---- - case SCC_X86_IFORM_INC_GPRV_40: - case SCC_X86_IFORM_INC_GPRV_FFR0: - return SCC_X86_IFORM_INC_GPR8; - case SCC_X86_IFORM_DEC_GPRV_48: - case SCC_X86_IFORM_DEC_GPRV_FFR1: - return SCC_X86_IFORM_DEC_GPR8; - // ---- NEG/NOT ---- - case SCC_X86_IFORM_NEG_GPRV: - return SCC_X86_IFORM_NEG_GPR8; - case SCC_X86_IFORM_NOT_GPRV: - return SCC_X86_IFORM_NOT_GPR8; - // ---- 移位操作 ---- - case SCC_X86_IFORM_SHL_GPRV_ONE_D1R4: - return SCC_X86_IFORM_SHL_GPR8_ONE_D0R4; - case SCC_X86_IFORM_SHR_GPRV_ONE: - return SCC_X86_IFORM_SHR_GPR8_ONE; - case SCC_X86_IFORM_SAR_GPRV_ONE: - return SCC_X86_IFORM_SAR_GPR8_ONE; - // ---- 其他(根据需求继续添加)---- - default: - break; - } - } - return iform; -} - /* ---------- 主编码入口 ---------- */ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, const scc_x86_operand_value_t *ops) { @@ -546,15 +463,9 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform]; int num_ops = info->num_explicit_ops; - // FIXME 自动适配 8 位操作数 - iform = adapt_iform_to_8bit(iform, ops, num_ops); - // FIXME 重新获取 info 因为 iform 可能变了 - info = &scc_x86_iform_table[iform]; - const scc_x86_encoding_t *enc = &info->encode; const scc_x86_operand_t *tmpl = info->ops; - LOG_INFO("[IFORM] %s, explicit_ops=%d (total=%d)", info->iform_name, - num_ops, info->num_ops); + LOG_INFO("[ENCODE] %s", info->iform_name); scc_x86_reg_t reg_field = SCC_X86_REG_INVALID; scc_x86_reg_t rm_field = SCC_X86_REG_INVALID; @@ -616,10 +527,10 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, emit_escape_map(mcode, enc); if (enc->has_modrm) { - emit_opcode(mcode, enc, rm_field, base_reg); + emit_opcode(mcode, enc, rm_field, base_reg, op_width); emit_modrm_sib_disp(mcode, info, ops, op_width); } else { - emit_opcode(mcode, enc, rm_field, base_reg); + emit_opcode(mcode, enc, rm_field, base_reg, op_width); if (imm_idx >= 0) { emit_immediate(mcode, enc, tmpl, imm_idx, imm_val, op_width); } diff --git a/libs/sccf/cbuild.toml b/libs/sccf/cbuild.toml index 025be91..b269066 100644 --- a/libs/sccf/cbuild.toml +++ b/libs/sccf/cbuild.toml @@ -1,5 +1,5 @@ [package] -name = "scc_format" +name = "scc_format" version = "0.1.0" dependencies = [ diff --git a/libs/target/sccf2target/cbuild.toml b/libs/target/sccf2target/cbuild.toml index ba628e3..1b108e5 100644 --- a/libs/target/sccf2target/cbuild.toml +++ b/libs/target/sccf2target/cbuild.toml @@ -1,12 +1,15 @@ [package] -name = "sccf2target" -version = "0.1.0" -authors = [] +name = "sccf2target" +version = "0.1.0" +authors = [] description = "" dependencies = [ { name = "sccf", path = "../../sccf" }, { name = "pe", path = "../pe" }, + { name = "elf", path = "../elf" }, + # for mcode with x86_64 + { name = "mcode", path = "../../mcode" }, ] # features = {} # default_features = []