From c6e3bb2e202a9d2b8cbb433004e56d2918074e51 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Wed, 20 May 2026 11:07:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(mir):=20=E6=B7=BB=E5=8A=A0x86=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=E7=9B=B8=E5=85=B3=E5=A4=B4=E6=96=87=E4=BB=B6=E5=B9=B6?= =?UTF-8?q?=E9=87=8D=E6=9E=84MIR=E6=8C=87=E4=BB=A4=E8=A1=A8=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建scc_x86_mir.h头文件,定义x86后端MIR指令结构和操作数构造器 - 创建scc_x86_isel.h头文件,定义x86_64指令选择器和相关工具函数 - 创建scc_x86_reg_alloc.h头文件,定义x86寄存器分配架构特定接口 - 移除旧的x86_64_isel.h和x86_64_reg_alloc.h文件 - 重构scc_mir.h中的指令表示,使用联合体存储伪指令数据 - 更新ABI lowering回调参数,使用void指针保持类型无关 - 扩展寄存器分配操作接口,添加指令信息查询和伪指令处理功能 - 更新目标文件包含路径以使用新的头文件命名 --- libs/ir/mir/include/arch/scc_x86_isel.h | 61 ++++ libs/ir/mir/include/arch/scc_x86_mir.h | 134 ++++++++ libs/ir/mir/include/arch/scc_x86_reg_alloc.h | 8 + libs/ir/mir/include/arch/x86_64_isel.h | 66 ---- libs/ir/mir/include/arch/x86_64_reg_alloc.h | 8 - .../mir/include/core_pass/scc_abi_lowering.h | 7 +- libs/ir/mir/include/core_pass/scc_reg_alloc.h | 45 +-- libs/ir/mir/include/scc_mir.h | 93 +++--- libs/ir/mir/include/scc_mir_module.h | 4 + libs/ir/mir/include/target/scc_win64.h | 2 +- .../arch/{x86_64_isel.c => scc_x86_isel.c} | 296 ++++++++---------- libs/ir/mir/src/arch/scc_x86_reg_alloc.c | 201 ++++++++++++ libs/ir/mir/src/arch/x86_64_reg_alloc.c | 83 ----- libs/ir/mir/src/reg_alloc/reg_alloc.c | 259 ++++----------- libs/ir/mir/src/scc_lir2mir.c | 4 +- libs/ir/mir/src/scc_mir.c | 19 +- libs/ir/mir/src/scc_mir_dump.c | 54 ++-- libs/ir/mir/src/scc_mir_module.c | 2 + libs/ir/mir/src/scc_mir_pass.c | 18 +- libs/ir/mir/src/target/win64_abi.c | 159 +++------- libs/ir2mcode/src/scc_ir2mcode.c | 52 +-- libs/ir2mcode/src/scc_ir2sccf.c | 5 +- 22 files changed, 792 insertions(+), 788 deletions(-) create mode 100644 libs/ir/mir/include/arch/scc_x86_isel.h create mode 100644 libs/ir/mir/include/arch/scc_x86_mir.h create mode 100644 libs/ir/mir/include/arch/scc_x86_reg_alloc.h delete mode 100644 libs/ir/mir/include/arch/x86_64_isel.h delete mode 100644 libs/ir/mir/include/arch/x86_64_reg_alloc.h rename libs/ir/mir/src/arch/{x86_64_isel.c => scc_x86_isel.c} (53%) create mode 100644 libs/ir/mir/src/arch/scc_x86_reg_alloc.c delete mode 100644 libs/ir/mir/src/arch/x86_64_reg_alloc.c diff --git a/libs/ir/mir/include/arch/scc_x86_isel.h b/libs/ir/mir/include/arch/scc_x86_isel.h new file mode 100644 index 0000000..22ee35a --- /dev/null +++ b/libs/ir/mir/include/arch/scc_x86_isel.h @@ -0,0 +1,61 @@ +#ifndef __SCC_X86_ISEL_H__ +#define __SCC_X86_ISEL_H__ + +#include +#include + +#include "../core_pass/scc_abi_lowering.h" +#include "scc_x86_mir.h" + +typedef struct scc_x86_64_isel { + scc_mir_x86_instr_vec_t instrs; + scc_mir_func_t *func; + scc_pos_t pos; + scc_abi_lowering_t abi_lowering; +} scc_x86_64_isel_t; + +void scc_isel_x86_64(scc_mir_module_t *mir_module, + const scc_lir_module_t *lir_module, + scc_x86_64_isel_t *isel); + +// Utils +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 scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, + const scc_lir_val_t *val); +static inline void emit_direct_call(scc_x86_64_isel_t *isel, + const char *callee) { + (void)callee; + scc_mir_x86_instr_t instr = {0}; + scc_mir_x86_instr_1(&instr, SCC_X86_IFORM_CALL_NEAR_GPRV, + scc_x86_op_relbr(0), scc_pos_create()); + scc_vec_push(isel->instrs, instr); +} +static inline void emit_ret(scc_x86_64_isel_t *isel) { + scc_mir_x86_instr_t instr = {0}; + scc_mir_x86_instr_0(&instr, SCC_X86_IFORM_RET_NEAR, scc_pos_create()); + scc_vec_push(isel->instrs, instr); +} + +#define add_instr_0(isel, iform) \ + do { \ + scc_mir_x86_instr_t instr; \ + scc_mir_x86_instr_0(&instr, (iform), (isel)->pos); \ + scc_vec_push((isel)->instrs, instr); \ + } while (0) + +#define add_instr_1(isel, iform, arg1) \ + do { \ + scc_mir_x86_instr_t instr; \ + 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) \ + do { \ + scc_mir_x86_instr_t instr; \ + scc_mir_x86_instr_2(&instr, (iform), (arg1), (arg2), (isel)->pos); \ + scc_vec_push((isel)->instrs, instr); \ + } while (0) + +#endif /* __SCC_X86_ISEL_H__ */ diff --git a/libs/ir/mir/include/arch/scc_x86_mir.h b/libs/ir/mir/include/arch/scc_x86_mir.h new file mode 100644 index 0000000..6acff6e --- /dev/null +++ b/libs/ir/mir/include/arch/scc_x86_mir.h @@ -0,0 +1,134 @@ +#ifndef __SCC_X86_MIR_H__ +#define __SCC_X86_MIR_H__ + +#include "../scc_mir.h" +#include +#include +#include +#include +#include + +typedef struct { + int opcode; + uint8_t num_operands; + scc_x86_operand_value_t operands[6]; + 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; +} scc_mir_x86_instr_t; + +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) + +// ── vreg 编码 ────────────────────────────────────────────────────────── +static inline bool scc_x86_op_is_vreg(const scc_x86_operand_value_t *op) { + return op->kind == SCC_X86_OPR_REG && + (int)op->reg >= (int)SCC_X86_REG_COUNT; +} +static inline int scc_x86_op_get_vreg(const scc_x86_operand_value_t *op) { + return (int)op->reg - (int)SCC_X86_REG_COUNT; +} +static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op, + scc_x86_reg_t preg) { + op->kind = SCC_X86_OPR_REG; + op->reg = preg; +} + +// ── 未解析栈槽编码 (base=INVALID, disp=slot_id) ────────────────────── +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; +} +static inline int scc_x86_op_slot_id(const scc_x86_operand_value_t *op) { + return op->mem.disp; +} + +// ── 指令构建辅助 ────────────────────────────────────────────────────── +static inline void scc_mir_x86_instr_0(scc_mir_x86_instr_t *out, int 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, + scc_x86_operand_value_t op0, + scc_pos_t pos) { + out->x86_instr.opcode = opcode; + out->x86_instr.num_operands = 1; + 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, + scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1, + scc_pos_t pos) { + out->x86_instr.opcode = opcode; + out->x86_instr.num_operands = 2; + out->x86_instr.operands[0] = op0; + 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) { + out->x86_instr.opcode = opcode; + out->x86_instr.num_operands = 3; + out->x86_instr.operands[0] = op0; + out->x86_instr.operands[1] = op1; + out->x86_instr.operands[2] = op2; + 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__ */ diff --git a/libs/ir/mir/include/arch/scc_x86_reg_alloc.h b/libs/ir/mir/include/arch/scc_x86_reg_alloc.h new file mode 100644 index 0000000..5ceecda --- /dev/null +++ b/libs/ir/mir/include/arch/scc_x86_reg_alloc.h @@ -0,0 +1,8 @@ +#ifndef __SCC_X86_REG_ALLOC_H__ +#define __SCC_X86_REG_ALLOC_H__ + +#include "../core_pass/scc_reg_alloc.h" + +void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops); + +#endif /* __SCC_X86_REG_ALLOC_H__ */ diff --git a/libs/ir/mir/include/arch/x86_64_isel.h b/libs/ir/mir/include/arch/x86_64_isel.h deleted file mode 100644 index 955b4f1..0000000 --- a/libs/ir/mir/include/arch/x86_64_isel.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __SCC_X86_64_ISEL_H__ -#define __SCC_X86_64_ISEL_H__ - -#include -#include - -#include -#include - -#include "../core_pass/scc_abi_lowering.h" -#include "../scc_mir_module.h" - -typedef struct scc_x86_64_isel { - scc_mir_instr_vec_t instrs; - scc_mir_func_t *func; - scc_abi_lowering_t abi_lowering; -} scc_x86_64_isel_t; - -void scc_isel_x86_64(scc_mir_module_t *mir_module, - const scc_lir_module_t *lir_module, - scc_x86_64_isel_t *isel); - -static void add_instr(scc_x86_64_isel_t *isel, const scc_mir_instr_t *instr) { - scc_vec_push(isel->instrs, *instr); -} - -static inline void add_instr_0(scc_x86_64_isel_t *isel, - scc_x86_iform_t opcode) { - scc_mir_instr_t out = {.opcode = opcode, .num_operands = 0}; - add_instr(isel, &out); -} - -static inline void add_instr_1(scc_x86_64_isel_t *isel, scc_x86_iform_t opcode, - scc_mir_operand_t op1) { - scc_mir_instr_t out = {.opcode = opcode, .num_operands = 1}; - out.operands[0] = op1; - add_instr(isel, &out); -} - -static inline void add_instr_2(scc_x86_64_isel_t *isel, scc_x86_iform_t opcode, - scc_mir_operand_t op1, scc_mir_operand_t op2) { - scc_mir_instr_t out = {.opcode = opcode, .num_operands = 2}; - out.operands[0] = op1; - out.operands[1] = op2; - add_instr(isel, &out); -} - -static inline scc_mir_operand_t reg_operand(scc_x86_reg_t reg) { - return (scc_mir_operand_t){.kind = SCC_MIR_OP_PREG, .preg = reg}; -} - -// Utils - -void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_mir_operand_t dst, - scc_mir_operand_t src, u8 size); -scc_mir_operand_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, - const scc_lir_val_t *val); -static inline void emit_call(scc_x86_64_isel_t *isel, const char *callee) { - scc_mir_operand_t sym = {.kind = SCC_MIR_OP_SYMBOL, .symbol = callee}; - add_instr_1(isel, SCC_X86_IFORM_CALL_NEAR_GPRV, sym); -} -static inline void emit_ret(scc_x86_64_isel_t *isel) { - add_instr_0(isel, SCC_X86_IFORM_RET_NEAR); -} - -#endif /* __SCC_X86_64_ISEL_H__ */ diff --git a/libs/ir/mir/include/arch/x86_64_reg_alloc.h b/libs/ir/mir/include/arch/x86_64_reg_alloc.h deleted file mode 100644 index a65aaa0..0000000 --- a/libs/ir/mir/include/arch/x86_64_reg_alloc.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __SCC_X86_64_REG_ALLOC_H__ -#define __SCC_X86_64_REG_ALLOC_H__ - -#include "../core_pass/scc_reg_alloc.h" - -void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops); - -#endif /* __SCC_X86_64_REG_ALLOC_H__ */ diff --git a/libs/ir/mir/include/core_pass/scc_abi_lowering.h b/libs/ir/mir/include/core_pass/scc_abi_lowering.h index c78d804..3bfd151 100644 --- a/libs/ir/mir/include/core_pass/scc_abi_lowering.h +++ b/libs/ir/mir/include/core_pass/scc_abi_lowering.h @@ -4,9 +4,12 @@ #include "../scc_mir_module.h" #include +// 所有回调通过 void* userdata / void* out_op 保持类型无关 typedef void (*scc_abi_lower_fn)(void *user_data, const scc_lir_instr_t *instr); -typedef scc_mir_operand_t (*scc_abi_lower_param_fn)(void *userdata, - const scc_lir_val_t *val); +// lower_param 将 LIR 值转化为后端操作数,写入 out_op(后端知道实际类型) +typedef void (*scc_abi_lower_param_fn)(void *userdata, + const scc_lir_val_t *val, + void *out_op); typedef struct scc_abi_lowering { scc_abi_lower_fn lower_call; 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 b75f9ec..f2e2b79 100644 --- a/libs/ir/mir/include/core_pass/scc_reg_alloc.h +++ b/libs/ir/mir/include/core_pass/scc_reg_alloc.h @@ -7,37 +7,46 @@ typedef enum { SCC_REG_ALLOC_OP_ACCESS_READ = 0, SCC_REG_ALLOC_OP_ACCESS_WRITE = 1, SCC_REG_ALLOC_OP_ACCESS_READWRITE = 2, -} scc_op_access_t; +} scc_reg_op_access_t; +// 后端回调表 —— 框架通过回调获取/修改指令,不感知具体布局 typedef struct scc_reg_alloc_op { - // preg → [slot] - void (*emit_spill)(scc_mir_instr_vec_t *ctx, int preg, int slot); - // [slot] → preg - void (*emit_reload)(scc_mir_instr_vec_t *ctx, int preg, int slot); - // preg → preg - void (*emit_copy)(scc_mir_instr_vec_t *ctx, int dst_preg, int src_preg, - int size); - - // 通用寄存器申请 / 释放 - int (*acquire_reg)(void *ctx); // 返回一个物理寄存器编号 - void (*release_reg)(void *ctx, int preg); // 归还该寄存器 - - // 显式标记某个寄存器已占用 / 未占用(用于隐式寄存器、固定分配等) + // ── 寄存器池 ── + int (*acquire_reg)(void *ctx); + void (*release_reg)(void *ctx, int preg); void (*mark_reg_used)(void *ctx, int preg); void (*clean_mark_regs)(void *ctx); - // ---- 指令信息查询(只读) ---- - scc_op_access_t (*get_operand_access)(void *ctx, int opcode, int op_idx); + // ── 指令信息 ── + int (*instr_opcode)(const void *instr); + int (*instr_num_operands)(const void *instr); + bool (*op_is_vreg)(const void *instr, int idx); + int (*op_get_vreg)(const void *instr, int idx); + void (*op_set_preg)(void *instr, int idx, int preg); + void (*op_set_slot)(void *instr, int idx, int slot); + // 读写属性与隐式寄存器 + scc_reg_op_access_t (*get_operand_access)(void *ctx, int opcode, + int op_idx); void (*get_implicit_regs)(void *ctx, int opcode, const int **out_uses, const int **out_defs); + + // ── 伪指令处理 ── + bool (*is_pseudo)(const void *instr); + void (*handle_pseudo)(scc_mir_func_t *func, void *instr, void *out); + + // ── 溢出/重载(写入 out 向量) ── + void (*emit_spill)(void *out, int preg, int slot); + void (*emit_reload)(void *out, int preg, int slot); + void (*emit_copy)(void *out, int dst_preg, int src_preg, int size); } scc_reg_alloc_op_t; typedef struct scc_reg_alloc_ctx { scc_reg_alloc_op_t ops; + scc_mir_module_t *module; scc_mir_func_t *func; - scc_mir_instr_vec_t *instrs; } scc_reg_alloc_ctx_t; +// 通用寄存器分配入口:遍历所有函数/基本块,对每条指令做 vreg → preg 分配 void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module); -#endif /* __SCC_REG_ALLOC__ */ +#endif /* __SCC_REG_ALLOC_H__ */ diff --git a/libs/ir/mir/include/scc_mir.h b/libs/ir/mir/include/scc_mir.h index 8a653b1..b0665a5 100644 --- a/libs/ir/mir/include/scc_mir.h +++ b/libs/ir/mir/include/scc_mir.h @@ -1,53 +1,29 @@ -// scc_mir.h (示意) - #ifndef __SCC_MIR_H__ #define __SCC_MIR_H__ -#include +#include +// 伪指令 opcode(负数),所有后端通用约定 typedef enum { - SCC_MIR_OP_NONE, - SCC_MIR_OP_STACK_OFFSET, // 已分配的内存 - SCC_MIR_OP_STACK_SLOT, // 栈空间 - SCC_MIR_OP_VREG, // 虚拟寄存器 - SCC_MIR_OP_PREG, // 物理寄存器 - SCC_MIR_OP_IMM, // 立即数 - SCC_MIR_OP_SYMBOL, // 符号地址(用于重定位) - SCC_MIR_OP_BLOCK // 基本块引用(label) -} scc_mir_op_kind_t; - -typedef struct scc_mir_operand { - scc_mir_op_kind_t kind; - union { - int vreg; // 虚拟寄存器索引 - int preg; // 物理寄存器 - i64 imm; // 立即数 - const char *symbol; // 符号名 - int stack_slot; // 栈槽 ID (由 FrameLayout 分配) - int stack_offset; // 栈偏移 - scc_lir_bblock_id_t block_id; // 目标基本块 - }; -} scc_mir_operand_t; - -typedef enum { - SCC_MIR_PSUEDO_ALLOCA = -1, -} scc_mir_psuedo_op_t; + SCC_MIR_PSEUDO_NONE = 0, + SCC_MIR_PSEUDO_ALLOCA = -1, + SCC_MIR_PSEUDO_VA_START = -2, +} scc_mir_pseudo_t; typedef struct scc_mir_instr { - int opcode; // 目标特定的指令编码 (如 X86::ADD32rr) - int num_operands; // 实际使用的操作数个数 - scc_mir_operand_t - operands[8]; // 固定小数组,RISC 风格指令通常不超过 4 操作数 - scc_pos_t src_loc; // 调试信息 (继承自 LIR) + int opcode; + union { + struct { + int size; + int align; + int vreg; + } alloc; + } data; } scc_mir_instr_t; -typedef SCC_VEC(scc_mir_instr_t) scc_mir_instr_vec_t; -typedef scc_cfg_bblock_t scc_mir_bblock_t; -typedef struct scc_mir_bblock_meta { -} scc_mir_bblock_meta_t; -#define SCC_MIR_BBLOCK_VALUES(bblock) \ - ((scc_mir_instr_vec_t *)&((bblock)->values)) +#define SCC_MIR_BBLOCK_VALUES_PTR(bb) ((void *)(&(bb)->values)) +// 栈槽信息(由 FrameLayout Pass 填充) typedef struct scc_mir_stack_slot { int slot_id; int size; // 通常是 8 字节 (指针大小) @@ -56,18 +32,22 @@ typedef struct scc_mir_stack_slot { } scc_mir_stack_slot_t; typedef SCC_VEC(scc_mir_stack_slot_t) scc_mir_stack_slot_vec_t; +typedef scc_cfg_bblock_t scc_mir_bblock_t; + +// 函数元数据 —— 不包含任何指令结构,由各后端自行定义指令布局 typedef scc_cfg_func_t scc_mir_func_t; typedef struct scc_mir_func_meta { - // 栈帧信息 (由 FrameLayout Pass 填充) int frame_size; int stack_alignment; int vregs_count; - // 寄存器分配信息 + void *target_data; // 目标后端私有数据,例如 x86_64_func_info_t* + scc_mir_stack_slot_vec_t stack_slots; - // vreg -> phys reg and stack slot index - // positive means stack slot index - // negative means physic register + // vreg -> phys reg / stack slot + // 0 = not mapped (still a vreg) + // >0 = stack slot index + // <0 = physical register (negated) scc_hashtable_t vreg2physic; } scc_mir_func_meta_t; #define SCC_MIR_FUNC_META(func) ((scc_mir_func_meta_t *)(func)->meta) @@ -75,11 +55,28 @@ typedef struct scc_mir_func_meta { void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta); int scc_mir_alloc_vreg(scc_mir_func_t *func); -void scc_mir_vreg_op(const scc_mir_func_t *func, int vreg, - scc_mir_operand_t *out); - void scc_mir_vreg_map2preg(scc_mir_func_t *func, int vreg, int preg); int scc_mir_vreg_map2slot(scc_mir_func_t *func, int vreg, int size, int align); + +// 从 vreg2physic 表中查询映射结果: +// 返回 0 → 该 vreg 仍为 vreg,未映射 +// 返回 1 → 已映射到物理寄存器,*out_preg 有效 +// 返回 -1 → 已溢出到栈槽,*out_slot 有效 +static inline int scc_mir_vreg_lookup(const scc_mir_func_t *func, int vreg, + int *out) { + scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); + isize idx = + (isize)scc_hashtable_get(&meta->vreg2physic, (void *)(usize)vreg); + if (idx == 0) + return 0; + if (idx < 0) { + *out = (int)-idx; + return 1; + } + *out = (int)idx; + return -1; +} + static inline scc_mir_stack_slot_t * scc_mir_unsafe_slot(const scc_mir_func_t *func, int slot) { Assert(slot > 0); diff --git a/libs/ir/mir/include/scc_mir_module.h b/libs/ir/mir/include/scc_mir_module.h index 0f047d0..97811a7 100644 --- a/libs/ir/mir/include/scc_mir_module.h +++ b/libs/ir/mir/include/scc_mir_module.h @@ -4,9 +4,13 @@ #include "scc_mir.h" #include +typedef SCC_VEC(char) scc_mir_instr_vec_t; + typedef scc_lir_symbol_meta_vec_t scc_mir_symbol_meta_vec_t; + typedef SCC_VEC(scc_mir_func_meta_t *) scc_mir_func_meta_vec_t; typedef struct scc_mir_module { + usize instr_size; scc_cfg_module_t cfg_module; scc_mir_func_meta_vec_t func_metas; scc_mir_symbol_meta_vec_t symbol_metas; diff --git a/libs/ir/mir/include/target/scc_win64.h b/libs/ir/mir/include/target/scc_win64.h index 9fc9cb0..03541c0 100644 --- a/libs/ir/mir/include/target/scc_win64.h +++ b/libs/ir/mir/include/target/scc_win64.h @@ -1,7 +1,7 @@ #ifndef __SCC_WIN64_H__ #define __SCC_WIN64_H__ -#include "../arch/x86_64_isel.h" +#include "../arch/scc_x86_isel.h" #include "../core_pass/scc_frame_layout.h" #include "../core_pass/scc_prolog_epilog.h" #include "../core_pass/scc_reg_alloc.h" diff --git a/libs/ir/mir/src/arch/x86_64_isel.c b/libs/ir/mir/src/arch/scc_x86_isel.c similarity index 53% rename from libs/ir/mir/src/arch/x86_64_isel.c rename to libs/ir/mir/src/arch/scc_x86_isel.c index ef6018e..ca0592f 100644 --- a/libs/ir/mir/src/arch/x86_64_isel.c +++ b/libs/ir/mir/src/arch/scc_x86_isel.c @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -9,73 +9,77 @@ static const char *preg_name(int preg_id) { return scc_x86_reg_table[preg_id].display_str; } -void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_instr_t *instr) { - scc_x86_iform_t iform = instr->opcode; +void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) { + if (instr->x86_instr.opcode >= SCC_X86_IFORM_COUNT || + instr->x86_instr.opcode < 0) { + 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_tree_dump_append_fmt(td, " %s", info->iform_name); - // Assert(instr->num_operands == info->num_ops); - for (int i = 0; i < instr->num_operands; i += 1) { + for (int i = 0; i < instr->x86_instr.num_operands; i += 1) { if (i == 0) scc_tree_dump_append(td, " "); else scc_tree_dump_append_fmt(td, ", "); - scc_mir_operand_t *op = &instr->operands[i]; + const scc_x86_operand_value_t *op = &instr->x86_instr.operands[i]; switch (op->kind) { - case SCC_MIR_OP_VREG: - scc_tree_dump_append_fmt(td, "%%%d", op->vreg); + case SCC_X86_OPR_REG: + if (scc_x86_op_is_vreg(op)) + scc_tree_dump_append_fmt(td, "%%%d", scc_x86_op_get_vreg(op)); + else + scc_tree_dump_append_fmt(td, "$%s", preg_name(op->reg)); break; - case SCC_MIR_OP_PREG: - scc_tree_dump_append_fmt(td, "$%s", preg_name(op->preg)); - break; - case SCC_MIR_OP_IMM: + case SCC_X86_OPR_IMM: scc_tree_dump_append_fmt(td, "%ld", op->imm); break; - case SCC_MIR_OP_BLOCK: - scc_tree_dump_append_fmt(td, "#BB%d", op->block_id); + case SCC_X86_OPR_MEM: + if (scc_x86_op_is_slot(op)) + scc_tree_dump_append_fmt(td, "[slot:%d]", + scc_x86_op_slot_id(op)); + else + scc_tree_dump_append_fmt(td, "[sp%+d]", op->mem.disp); break; - case SCC_MIR_OP_SYMBOL: - scc_tree_dump_append_fmt(td, "@%s", op->symbol); + case SCC_X86_OPR_RELBR: + scc_tree_dump_append(td, "label"); break; - case SCC_MIR_OP_STACK_SLOT: - scc_tree_dump_append_fmt(td, "[%d]", op->stack_slot); - break; - case SCC_MIR_OP_STACK_OFFSET: - scc_tree_dump_append_fmt(td, "[sp, %d]", op->stack_offset); default: break; } } } -// 将 LIR 值转换为 MIR 操作数 -scc_mir_operand_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, - const scc_lir_val_t *val) { - scc_mir_operand_t op = {0}; +// 将 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) { + scc_x86_operand_value_t op = {0}; switch (val->kind) { case SCC_LIR_INSTR_KIND_NONE: - op.kind = SCC_MIR_OP_NONE; + op.kind = SCC_X86_OPR_NONE; break; case SCC_LIR_INSTR_KIND_VREG: - op.kind = SCC_MIR_OP_VREG; - op.vreg = val->data.reg; + op = scc_x86_op_vreg(val->data.reg); + int id = 0; + int ret = scc_mir_vreg_lookup(isel->func, val->data.reg, &id); + if (ret > 0) { + op = scc_x86_op_preg(id); + } else if (ret < 0) { + op = scc_x86_op_slot(id); + } break; case SCC_LIR_INSTR_KIND_IMM: - op.kind = SCC_MIR_OP_IMM; - // FIXME hack ap - op.imm = val->data.imm.data.digit; + op = scc_x86_op_imm(val->data.imm.data.digit); break; case SCC_LIR_INSTR_KIND_FIMM: - // 浮点立即数暂时作为普通立即数处理(后端需特殊处理) - op.kind = SCC_MIR_OP_IMM; - op.imm = *(i64 *)&val->data.fimm; + op = scc_x86_op_imm(*(i64 *)&val->data.fimm); break; case SCC_LIR_INSTR_KIND_SYMBOL: - op.kind = SCC_MIR_OP_SYMBOL; - op.symbol = val->data.symbol; + op = scc_x86_op_symbol(val->data.symbol); break; case SCC_LIR_INSTR_KIND_ARG: Assert(isel->abi_lowering.lower_param); - op = isel->abi_lowering.lower_param(isel, val); + isel->abi_lowering.lower_param(isel, val, &op); break; default: UNREACHABLE(); @@ -84,39 +88,40 @@ scc_mir_operand_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, } // 虚拟临时寄存器分配(简单递增) -static scc_mir_operand_t new_vreg_temp(scc_x86_64_isel_t *isel) { - return (scc_mir_operand_t){.kind = SCC_MIR_OP_VREG, - .vreg = scc_mir_alloc_vreg(isel->func)}; +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)); } -void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_mir_operand_t dst, - scc_mir_operand_t src, u8 size) { - if (dst.kind == SCC_MIR_OP_VREG || dst.kind == SCC_MIR_OP_PREG) { - if (src.kind == SCC_MIR_OP_VREG || src.kind == SCC_MIR_OP_PREG) { - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89, dst, src); - } else if (src.kind == SCC_MIR_OP_IMM) { +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) { + + if (dst.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); + } else if (src.kind == SCC_X86_OPR_IMM) { add_instr_2(isel, (size == 8) ? SCC_X86_IFORM_MOV_GPRV_IMMZ : SCC_X86_IFORM_MOV_GPRV_IMMV, dst, src); - } else if (src.kind == SCC_MIR_OP_SYMBOL) { + } else if (src.kind == SCC_X86_OPR_IMM && src.imm == 0) { + // 特殊:符号作为立即数地址 add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, dst, src); - } else if (src.kind == SCC_MIR_OP_STACK_SLOT) { + } else if (src.kind == SCC_X86_OPR_MEM) { add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src); } else { UNREACHABLE(); } - } else if (dst.kind == SCC_MIR_OP_STACK_SLOT) { - if (src.kind == SCC_MIR_OP_VREG || src.kind == SCC_MIR_OP_PREG) { + } else if (dst.kind == SCC_X86_OPR_MEM) { + if (src.kind == SCC_X86_OPR_REG) { add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, dst, src); - } else if (src.kind == SCC_MIR_OP_IMM) { + } else if (src.kind == SCC_X86_OPR_IMM) { add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_IMMZ, dst, src); - } else if (src.kind == SCC_MIR_OP_SYMBOL) { - scc_mir_operand_t temp = new_vreg_temp(isel); + } else if (src.kind == SCC_X86_OPR_IMM) { + 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_MEMV_GPRV, dst, temp); - } else if (src.kind == SCC_MIR_OP_STACK_SLOT) { - scc_mir_operand_t temp = new_vreg_temp(isel); + } else if (src.kind == SCC_X86_OPR_MEM) { + scc_x86_operand_value_t temp = new_vreg_temp(isel); scc_x86_emit_move(isel, temp, src, size); scc_x86_emit_move(isel, dst, temp, size); } else { @@ -127,19 +132,18 @@ void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_mir_operand_t dst, } } -static void emit_compare(scc_x86_64_isel_t *isel, scc_mir_operand_t op0, - scc_mir_operand_t op1, u8 size) { - // cmp op0, op1 (注意 x86 是 cmp a, b 即 a - b) - if (op0.kind == SCC_MIR_OP_VREG && op1.kind == SCC_MIR_OP_IMM) { +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); - } else if (op0.kind == SCC_MIR_OP_VREG && op1.kind == SCC_MIR_OP_VREG) { - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_39, op0, op1); + } 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); } else { UNREACHABLE(); } } -/* 条件码到 setcc 指令的映射 */ static scc_x86_iform_t cond_to_setcc(scc_lir_cond_t cond) { switch (cond) { case SCC_LIR_COND_EQ: @@ -151,58 +155,61 @@ static scc_x86_iform_t cond_to_setcc(scc_lir_cond_t cond) { case SCC_LIR_COND_SLE: return SCC_X86_IFORM_SETLE_GPR8; case SCC_LIR_COND_SGT: - return SCC_X86_IFORM_SETNLE_GPR8; // SETG + return SCC_X86_IFORM_SETNLE_GPR8; case SCC_LIR_COND_SGE: - return SCC_X86_IFORM_SETNL_GPR8; // SETGE + return SCC_X86_IFORM_SETNL_GPR8; case SCC_LIR_COND_ULT: return SCC_X86_IFORM_SETB_GPR8; case SCC_LIR_COND_ULE: return SCC_X86_IFORM_SETBE_GPR8; case SCC_LIR_COND_UGT: - return SCC_X86_IFORM_SETNBE_GPR8; // SETA + return SCC_X86_IFORM_SETNBE_GPR8; case SCC_LIR_COND_UGE: - return SCC_X86_IFORM_SETNB_GPR8; // SETAE + return SCC_X86_IFORM_SETNB_GPR8; default: UNREACHABLE(); } } -static void emit_copy_if_needed(scc_x86_64_isel_t *isel, scc_mir_operand_t dst, - scc_mir_operand_t src0, u8 size) { - if (dst.kind == SCC_MIR_OP_VREG && src0.kind == SCC_MIR_OP_VREG && - dst.vreg == src0.vreg) { +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) { + 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); } static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op, - scc_mir_operand_t dst, scc_mir_operand_t src0, - scc_mir_operand_t src1, u8 size) { + 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); - bool is_imm = (src1.kind == SCC_MIR_OP_IMM); + bool is_imm = (src1.kind == SCC_X86_OPR_IMM); scc_x86_iform_t iform; switch (op) { case SCC_LIR_ADD: iform = is_imm ? SCC_X86_IFORM_ADD_GPRV_IMMZ - : SCC_X86_IFORM_ADD_GPRV_GPRV_01; + : 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_29; + : 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_21; + : SCC_X86_IFORM_AND_GPRV_GPRV_23; break; case SCC_LIR_OR: iform = - is_imm ? SCC_X86_IFORM_OR_GPRV_IMMZ : SCC_X86_IFORM_OR_GPRV_GPRV_09; + 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_31; + : SCC_X86_IFORM_XOR_GPRV_GPRV_33; break; default: UNREACHABLE(); @@ -210,33 +217,22 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op, add_instr_2(isel, iform, dst, src1); } -static scc_mir_operand_t stack_slot_op(int offset) { - return (scc_mir_operand_t){.kind = SCC_MIR_OP_STACK_SLOT, - .stack_slot = offset}; +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_load(scc_x86_64_isel_t *isel, int vreg, int offset) { - scc_mir_operand_t dst = {.kind = SCC_MIR_OP_VREG, .vreg = vreg}; - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, stack_slot_op(offset)); +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 emit_spill_store(scc_x86_64_isel_t *isel, int vreg, int offset) { - scc_mir_operand_t src = {.kind = SCC_MIR_OP_VREG, .vreg = vreg}; - add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, stack_slot_op(offset), src); -} - -// static void emit_alloca(scc_x86_64_isel_t *isel, scc_mir_operand_t dst, -// i64 size) { -// scc_mir_operand_t imm = {.kind = SCC_MIR_OP_IMM, .imm = size}; -// scc_mir_operand_t rsp = {.kind = SCC_MIR_OP_PREG, .preg = -// SCC_X86_REG_RSP}; add_instr_2(isel, SCC_X86_IFORM_SUB_GPRV_IMMZ, rsp, -// imm); scc_x86_emit_move(isel, dst, rsp, 8); -// } - static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { - scc_mir_operand_t dst = scc_x86_lir_val_to_mir_op(isel, &instr->to); - scc_mir_operand_t src0 = scc_x86_lir_val_to_mir_op(isel, &instr->arg0); - scc_mir_operand_t src1 = scc_x86_lir_val_to_mir_op(isel, &instr->arg1); + 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; switch (instr->op) { @@ -244,23 +240,19 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { case SCC_LIR_MOV: scc_x86_emit_move(isel, dst, src0, size); break; - case SCC_LIR_LOAD: - // 从 [addr] 加载到 vreg(addr 通常为 vreg) - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV, dst, src0); + scc_x86_emit_move(isel, dst, src0, size); + break; + case SCC_LIR_STORE: + scc_x86_emit_move(isel, src1, src0, size); break; case SCC_LIR_STORE_ADDR: TODO(); break; - case SCC_LIR_STORE: - // 将 src0 存入 [src1] - add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV, src1, src0); - break; case SCC_LIR_LEA: case SCC_LIR_LOAD_ADDR: - // 地址计算,src0 是复杂地址(LIR 的 MEM 类型) add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0); break; @@ -282,10 +274,9 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { break; case SCC_LIR_MUL: - // imul dst, src0, src1 → 需要 mov + imul emit_copy_if_needed(isel, dst, src0, size); - if (src1.kind == SCC_MIR_OP_IMM) { - scc_mir_operand_t op = new_vreg_temp(isel); + 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); src1 = op; } @@ -295,10 +286,9 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { case SCC_LIR_SHL: case SCC_LIR_SHR: case SCC_LIR_SAR: { - // 双地址:dst = dst op count emit_copy_if_needed(isel, dst, src0, size); - if (src1.kind == SCC_MIR_OP_IMM) { + if (src1.kind == SCC_X86_OPR_IMM) { scc_x86_iform_t iform; switch (instr->op) { case SCC_LIR_SHL: @@ -315,10 +305,8 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { } add_instr_2(isel, iform, dst, src1); } else { - // 移位量在 CL(需要先 mov cl, src1) - scc_mir_operand_t cl = {.kind = SCC_MIR_OP_PREG, - .preg = SCC_X86_REG_CL}; - scc_x86_emit_move(isel, cl, src1, 1); // CL 是 8 位 + scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL); + scc_x86_emit_move(isel, cl, src1, 1); scc_x86_iform_t iform; switch (instr->op) { case SCC_LIR_SHL: @@ -342,19 +330,15 @@ 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_mir_operand_t rax = {.kind = SCC_MIR_OP_PREG, - .preg = SCC_X86_REG_RAX}; - scc_mir_operand_t rdx = {.kind = SCC_MIR_OP_PREG, - .preg = SCC_X86_REG_RDX}; + 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_emit_move(isel, rax, src0, size); if (instr->op == SCC_LIR_DIV_S || instr->op == SCC_LIR_REM_S) { - // 有符号扩展:cqo / cdq(根据 size 选择,这里简化为 64 位 cqo) add_instr_0(isel, SCC_X86_IFORM_CQO); } else { - // 无符号:xor edx, edx - scc_mir_operand_t zero = {.kind = SCC_MIR_OP_IMM, .imm = 0}; + scc_x86_operand_value_t zero = scc_x86_op_imm(0); scc_x86_emit_move(isel, rdx, zero, size); } @@ -364,7 +348,6 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { : SCC_X86_IFORM_DIV_GPRV; add_instr_1(isel, div_if, src1); - // 结果:商在 RAX,余数在 RDX if (instr->op == SCC_LIR_REM_S || instr->op == SCC_LIR_REM_U) scc_x86_emit_move(isel, dst, rdx, size); else @@ -373,68 +356,57 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { /* ---- 比较指令 ---- */ case SCC_LIR_CMP: { - // 1. 比较并设置标志位 - if (src0.kind == SCC_MIR_OP_VREG && src1.kind == SCC_MIR_OP_IMM) + 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); - else if (src0.kind == SCC_MIR_OP_VREG && src1.kind == SCC_MIR_OP_VREG) - add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_39, 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); else UNREACHABLE(); - // 2. 标志位 -> 布尔值 (写入 dst) scc_x86_iform_t setcc = cond_to_setcc(instr->metadata.cond); - add_instr_1(isel, setcc, dst); // 注意 setcc 只写低 8 位 - // 若需 32/64 位布尔值,可再 movzx dst, dst + add_instr_1(isel, setcc, dst); if (size > 1) { - // movzx dst, dst (假设 MOVZX_GPRV_GPR8 存在;这里临时用 and 模拟) - // 简单处理:用 and dst, 1 清理高位 - scc_mir_operand_t one = {.kind = SCC_MIR_OP_IMM, .imm = 1}; + scc_x86_operand_value_t one = scc_x86_op_imm(1); add_instr_2(isel, SCC_X86_IFORM_AND_GPRV_IMMZ, dst, one); } } break; /* ---- 条件分支 ---- */ case SCC_LIR_BR: { - // arg0 是 CMP 产生的布尔值 (0 或 1) - // test src0, src0 ; jnz true_bb ; jmp false_bb - scc_mir_operand_t true_bb = {.kind = SCC_MIR_OP_BLOCK, - .block_id = - instr->metadata.br.true_target}; - scc_mir_operand_t false_bb = {.kind = SCC_MIR_OP_BLOCK, - .block_id = - instr->metadata.br.false_target}; + scc_x86_operand_value_t true_bb = + scc_x86_op_block(instr->metadata.br.true_target); + scc_x86_operand_value_t false_bb = + scc_x86_op_block(instr->metadata.br.false_target); - // test src0, src0 add_instr_2(isel, SCC_X86_IFORM_TEST_GPRV_GPRV, src0, src0); - // jnz true add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb); - // jmp false add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb); } break; case SCC_LIR_JMP: { - add_instr_1( - isel, SCC_X86_IFORM_JMP_RELBRZ, - (scc_mir_operand_t){.kind = SCC_MIR_OP_BLOCK, - .block_id = instr->metadata.jmp_target}); + scc_x86_operand_value_t jmp_bb = + scc_x86_op_block(instr->metadata.jmp_target); + add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb); } break; /* ---- 栈分配 ---- */ - case SCC_LIR_ALLOCA: - // emit_alloca(isel, dst, instr->metadata.alloca.size_bytes); - scc_mir_operand_t op = scc_x86_lir_val_to_mir_op(isel, &instr->to); - add_instr_2(isel, (scc_x86_iform_t)SCC_MIR_PSUEDO_ALLOCA, op, - (scc_mir_operand_t){ - .kind = SCC_MIR_OP_IMM, - .imm = instr->size, - }); - Assert(op.kind == SCC_MIR_OP_VREG); - // FIXME - scc_mir_vreg_map2slot(isel->func, op.vreg, instr->size, 8); + case SCC_LIR_ALLOCA: { + scc_x86_operand_value_t op = + scc_x86_lir_val_to_mir_op(isel, &instr->to); + scc_mir_x86_instr_t x86instr; + x86instr.instr.opcode = SCC_MIR_PSEUDO_ALLOCA; + Assert(op.kind == SCC_X86_OPR_REG); + x86instr.instr.data.alloc.vreg = op.reg; + x86instr.instr.data.alloc.size = instr->size; + x86instr.instr.data.alloc.align = 0; + scc_vec_push(isel->instrs, x86instr); + scc_mir_vreg_map2slot(isel->func, instr->to.data.reg, instr->size, 0); break; + } /* ---- 其他(占位) ---- */ case SCC_LIR_NOP: + add_instr_0(isel, SCC_X86_IFORM_NOP_90); break; /* ---- 调用与返回 ---- */ @@ -475,6 +447,7 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module, const scc_lir_module_t *lir_module, scc_x86_64_isel_t *isel) { + mir_module->instr_size = sizeof(scc_mir_x86_instr_t); scc_vec_foreach(lir_module->cfg_module.funcs, i) { if (i == 0) continue; @@ -484,7 +457,6 @@ void scc_isel_x86_64(scc_mir_module_t *mir_module, scc_malloc(sizeof(scc_mir_func_meta_t)); Assert(func_meta != nullptr); scc_mir_func_meta_init(func_meta); - // FIXME func_meta->vregs_count = SCC_LIR_FUNC_META(func)->vregs_count; func->meta = func_meta; diff --git a/libs/ir/mir/src/arch/scc_x86_reg_alloc.c b/libs/ir/mir/src/arch/scc_x86_reg_alloc.c new file mode 100644 index 0000000..25c7602 --- /dev/null +++ b/libs/ir/mir/src/arch/scc_x86_reg_alloc.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include + +/* ========== 指令访问回调 ========== */ + +static int instr_opcode(const void *instr) { + return ((const scc_mir_x86_instr_t *)instr)->x86_instr.opcode; +} +static int instr_num_operands(const void *instr) { + return ((const scc_mir_x86_instr_t *)instr)->x86_instr.num_operands; +} +static bool op_is_vreg(const void *instr, int idx) { + return scc_x86_op_is_vreg( + &((const scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx]); +} +static int op_get_vreg(const void *instr, int idx) { + return scc_x86_op_get_vreg( + &((const scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx]); +} +static void op_set_preg(void *instr, int idx, int preg) { + scc_x86_op_set_preg( + &((scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx], + (scc_x86_reg_t)preg); +} +static void op_set_slot(void *instr, int idx, int slot) { + ((scc_mir_x86_instr_t *)instr)->x86_instr.operands[idx] = + scc_x86_op_slot(slot); +} + +/* ========== 伪指令处理 ========== */ + +static bool is_pseudo(const void *instr) { + return ((const scc_mir_x86_instr_t *)instr)->x86_instr.opcode < 0; +} + +static void handle_pseudo(scc_mir_func_t *func, void *instr, void *out) { + scc_mir_x86_instr_t *ins = instr; + scc_mir_x86_instr_vec_t *out_vec = out; + if (ins->x86_instr.opcode == SCC_MIR_PSEUDO_ALLOCA) { + // // 指令选择时已分配 slot,直接替换为 slot 操作数 + // if (scc_x86_op_is_vreg(&ins->x86_instr.operands[0])) { + // int vreg = scc_x86_op_get_vreg(&ins->x86_instr.operands[0]); + // int slot = scc_mir_vreg_map2slot(func, vreg, 8, 8); + // ins->x86_instr.operands[0] = scc_x86_op_slot(slot); + // } + // scc_vec_push(*out_vec, *ins); + } else { + scc_vec_push(*out_vec, *ins); + } +} + +/* ========== Spill / Reload / Copy ========== */ + +static void emit_spill(void *out, int preg, int slot) { + scc_mir_x86_instr_vec_t *vec = out; + scc_mir_x86_instr_t ins = { + .x86_instr.opcode = SCC_X86_IFORM_MOV_MEMV_GPRV, + .x86_instr.num_operands = 2, + .x86_instr.operands = {scc_x86_op_slot(slot), scc_x86_op_preg(preg)}}; + scc_vec_push(*vec, ins); +} + +static void emit_reload(void *out, int preg, int slot) { + 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 = {scc_x86_op_preg(preg), scc_x86_op_slot(slot)}}; + scc_vec_push(*vec, ins); +} + +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); +} + +/* ========== 操作数读写属性 ========== */ + +static scc_reg_op_access_t get_operand_access(void *ctx, int opcode, + int op_idx) { + (void)ctx; + 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) + return SCC_REG_ALLOC_OP_ACCESS_READWRITE; + if (info->ops[op_idx].rw[0] == 'r') + return info->ops[op_idx].rw[1] == 'w' + ? SCC_REG_ALLOC_OP_ACCESS_READWRITE + : SCC_REG_ALLOC_OP_ACCESS_READ; + else if (info->ops[op_idx].rw[0] == 'w') + return SCC_REG_ALLOC_OP_ACCESS_WRITE; + } + return SCC_REG_ALLOC_OP_ACCESS_READWRITE; +} + +/* ========== 隐式寄存器 ========== */ + +static void get_implicit_regs(void *ctx, int opcode, const int **uses, + const int **defs) { + (void)ctx; + static const int empty[] = {-1}; + static const int rax[] = {SCC_X86_REG_RAX, -1}; + static const int rdx[] = {SCC_X86_REG_RDX, -1}; + static const int rax_rdx[] = {SCC_X86_REG_RAX, SCC_X86_REG_RDX, -1}; + static const int cl[] = {SCC_X86_REG_CL, -1}; + + switch (opcode) { + case SCC_X86_IFORM_IDIV_GPRV: + case SCC_X86_IFORM_DIV_GPRV: + *uses = rax_rdx; + *defs = rax_rdx; + break; + case SCC_X86_IFORM_CQO: + *uses = rax; + *defs = rax_rdx; + break; + case SCC_X86_IFORM_SAR_GPRV_CL: + *uses = cl; + *defs = empty; + break; + default: + *uses = empty; + *defs = empty; + break; + } +} + +/* ========== 寄存器池 ========== */ + +static const int reg_pool[] = { + SCC_X86_REG_R8, SCC_X86_REG_R9, SCC_X86_REG_R10, SCC_X86_REG_R11, + SCC_X86_REG_R12, SCC_X86_REG_R13, SCC_X86_REG_R14, SCC_X86_REG_R15}; +static uint32_t reg_mask = 0; + +static int acquire_reg(void *ctx) { + (void)ctx; + for (int i = 0; i < SCC_ARRLEN(reg_pool); i++) + if (!(reg_mask & (1u << i))) { + reg_mask |= (1u << i); + return reg_pool[i]; + } + UNREACHABLE(); +} + +static void release_reg(void *ctx, int preg) { + (void)ctx; + for (int i = 0; i < SCC_ARRLEN(reg_pool); i++) + if (reg_pool[i] == preg) { + reg_mask &= ~(1u << i); + return; + } +} + +static void mark_reg_used(void *ctx, int preg) { + (void)ctx; + for (int i = 0; i < SCC_ARRLEN(reg_pool); i++) + if (reg_pool[i] == preg) { + reg_mask |= (1u << i); + return; + } +} + +static void clean_mark_regs(void *ctx) { + (void)ctx; + reg_mask = 0; +} + +/* ========== 注册全部 x86 回调 ========== */ + +void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) { + ops->acquire_reg = acquire_reg; + ops->release_reg = release_reg; + ops->mark_reg_used = mark_reg_used; + ops->clean_mark_regs = clean_mark_regs; + + ops->instr_opcode = instr_opcode; + ops->instr_num_operands = instr_num_operands; + ops->op_is_vreg = op_is_vreg; + ops->op_get_vreg = op_get_vreg; + ops->op_set_preg = op_set_preg; + ops->op_set_slot = op_set_slot; + + ops->get_operand_access = get_operand_access; + ops->get_implicit_regs = get_implicit_regs; + + ops->is_pseudo = is_pseudo; + ops->handle_pseudo = handle_pseudo; + + ops->emit_spill = emit_spill; + ops->emit_reload = emit_reload; + ops->emit_copy = emit_copy; +} diff --git a/libs/ir/mir/src/arch/x86_64_reg_alloc.c b/libs/ir/mir/src/arch/x86_64_reg_alloc.c deleted file mode 100644 index 4e3be5d..0000000 --- a/libs/ir/mir/src/arch/x86_64_reg_alloc.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -static void x86_emit_spill(scc_mir_instr_vec_t *ctx, int preg, int slot) { - scc_mir_instr_t ins = { - .opcode = SCC_X86_IFORM_MOV_MEMV_GPRV, - .num_operands = 2, - .operands = {{.kind = SCC_MIR_OP_STACK_SLOT, .stack_slot = slot}, - {.kind = SCC_MIR_OP_PREG, .preg = preg}}}; - scc_vec_push(*ctx, ins); -} - -static void x86_emit_reload(scc_mir_instr_vec_t *ctx, int preg, int slot) { - scc_mir_instr_t ins = { - .opcode = SCC_X86_IFORM_MOV_GPRV_MEMV, - .num_operands = 2, - .operands = {{.kind = SCC_MIR_OP_PREG, .preg = preg}, - {.kind = SCC_MIR_OP_STACK_SLOT, .stack_slot = slot}}}; - scc_vec_push(*ctx, ins); -} - -static void x86_emit_copy(scc_mir_instr_vec_t *ctx, int dst_preg, int src_preg, - int size) { - scc_mir_instr_t ins = { - .opcode = SCC_X86_IFORM_MOV_GPRV_GPRV_89, - .num_operands = 2, - .operands = {{.kind = SCC_MIR_OP_PREG, .preg = dst_preg}, - {.kind = SCC_MIR_OP_PREG, .preg = src_preg}}}; - scc_vec_push(*ctx, ins); -} - -/* ---- 临时寄存器 ---- */ -static int x86_acquire_temp_reg(void *vctx) { return SCC_X86_REG_R11; } - -static void x86_release_temp_reg(void *vctx, int preg) { /* 简单模式无需操作 */ -} - -/* ---- 操作数读写属性 ---- */ -static scc_op_access_t x86_get_operand_access(void *vctx, int opcode, - int op_idx) { - switch (opcode) { - default: - return SCC_REG_ALLOC_OP_ACCESS_READWRITE; // 保守 - } -} - -/* ---- 隐式寄存器 ---- */ -static void x86_get_implicit_regs(void *vctx, int opcode, const int **uses, - const int **defs) { - static const int empty[] = {-1}; - static const int rax[] = {SCC_X86_REG_RAX, -1}; - static const int rdx[] = {SCC_X86_REG_RDX, -1}; - static const int rax_rdx[] = {SCC_X86_REG_RAX, SCC_X86_REG_RDX, -1}; - static const int cl[] = {SCC_X86_REG_CL, -1}; - - switch (opcode) { - case SCC_X86_IFORM_IDIV_GPRV: - case SCC_X86_IFORM_DIV_GPRV: - *uses = rax_rdx; - *defs = rax_rdx; - break; - case SCC_X86_IFORM_CQO: - *uses = rax; - *defs = rax_rdx; - break; - case SCC_X86_IFORM_SAR_GPRV_CL: - *uses = cl; - *defs = empty; - break; - default: - *uses = empty; - *defs = empty; - break; - } -} - -void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) { - ops->emit_spill = x86_emit_spill; - ops->emit_reload = x86_emit_reload; - ops->emit_copy = x86_emit_copy; - ops->get_operand_access = x86_get_operand_access; - ops->get_implicit_regs = x86_get_implicit_regs; -} diff --git a/libs/ir/mir/src/reg_alloc/reg_alloc.c b/libs/ir/mir/src/reg_alloc/reg_alloc.c index 2aa46cf..66fb68a 100644 --- a/libs/ir/mir/src/reg_alloc/reg_alloc.c +++ b/libs/ir/mir/src/reg_alloc/reg_alloc.c @@ -1,174 +1,76 @@ #include -#include #include -// static void alloc_instr(scc_reg_alloc_ctx_t *ctx, -// scc_mir_instr_vec_t *instr_vec, -// scc_mir_instr_t *instr) { -// const scc_reg_alloc_op_t *ops = &ctx->ops; -// scc_mir_instr_vec_t before, after; -// scc_vec_init(before); -// scc_vec_init(after); - -// // 1. 标记隐式寄存器为占用 -// const int *implicit_uses, *implicit_defs; -// ops->get_implicit_regs(ctx, instr->opcode, &implicit_uses, -// &implicit_defs); for (const int *p = implicit_uses; *p != -1; p++) -// ops->mark_reg_used(ctx, *p); -// for (const int *p = implicit_defs; *p != -1; p++) -// ops->mark_reg_used(ctx, *p); - -// SCC_VEC(int) preg_vec; -// scc_vec_init(preg_vec); - -// for (int i = 0; i < instr->num_operands; i++) { -// if (instr->operands[i].kind != SCC_MIR_OP_VREG) -// continue; - -// int vreg = instr->operands[i].vreg; -// scc_mir_vreg_op(ctx->func, vreg, &instr->operands[i]); - -// if (instr->operands[i].kind != SCC_MIR_OP_VREG) -// continue; - -// // FIXME size alian -// int slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8); -// int preg = -1; -// // if (implicit_uses && implicit_uses[0] != -1) -// // preg = implicit_uses[0]; -// // else -// preg = ops->acquire_reg(ctx); -// scc_vec_push(preg_vec, preg); - -// // 根据操作数读写属性决定是否需要 reload -// scc_op_access_t acc = ops->get_operand_access(ctx, instr->opcode, i); -// if (acc == SCC_REG_ALLOC_OP_ACCESS_READ || -// acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) { -// ops->emit_reload(&before, preg, slot); -// } - -// if (acc == SCC_REG_ALLOC_OP_ACCESS_WRITE || -// acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) { -// ops->emit_spill(&after, preg, slot); -// } - -// // 替换操作数为物理寄存器 -// instr->operands[i].kind = SCC_MIR_OP_PREG; -// instr->operands[i].preg = preg; -// } - -// scc_vec_foreach(preg_vec, i) { -// int preg = scc_vec_at(preg_vec, i); -// ops->release_reg(ctx, preg); -// } - -// scc_vec_foreach(before, i) scc_vec_push(*instr_vec, scc_vec_at(before, -// i)); scc_vec_push(*instr_vec, *instr); scc_vec_foreach(after, i) -// scc_vec_push(*instr_vec, scc_vec_at(after, i)); - -// // 7. 取消隐式寄存器的占用标记 -// Assert(ops->mark_reg_used != nullptr); -// for (const int *p = implicit_defs; *p != -1; p++) -// ops->mark_reg_used(ctx, *p); -// for (const int *p = implicit_uses; *p != -1; p++) -// ops->release_reg(ctx, *p); - -// scc_vec_free(before); -// scc_vec_free(after); -// } - static void alloc_instr(scc_reg_alloc_ctx_t *ctx, scc_mir_instr_vec_t *instr_vec, scc_mir_instr_t *instr) { const scc_reg_alloc_op_t *ops = &ctx->ops; + usize instr_size = ctx->module->instr_size; + if (ops->is_pseudo(instr)) { + ops->handle_pseudo(ctx->func, (void *)instr, instr_vec); + return; + } + scc_mir_instr_vec_t before, after; scc_vec_init(before); scc_vec_init(after); + SCC_VEC(int) allocated; + scc_vec_init(allocated); - // 隐式寄存器标记 + int opcode = ops->instr_opcode(instr); + + // 标记隐式寄存器 const int *implicit_uses, *implicit_defs; - ops->get_implicit_regs(ctx, instr->opcode, &implicit_uses, &implicit_defs); + ops->get_implicit_regs(ctx, opcode, &implicit_uses, &implicit_defs); for (const int *p = implicit_uses; *p != -1; p++) ops->mark_reg_used(ctx, *p); for (const int *p = implicit_defs; *p != -1; p++) ops->mark_reg_used(ctx, *p); - // 指令内 vreg→preg 的简单映射(操作数不超过 8 个) - int local_vreg[8], local_preg[8]; - int local_cnt = 0; - - SCC_VEC(int) allocated_pregs; - scc_vec_init(allocated_pregs); - - for (int i = 0; i < instr->num_operands; i++) { - scc_mir_operand_t *op = &instr->operands[i]; - - // 只处理 vreg - if (op->kind != SCC_MIR_OP_VREG) + int num_ops = ops->instr_num_operands(instr); + for (int op_i = 0; op_i < num_ops; op_i++) { + if (!ops->op_is_vreg(instr, op_i)) continue; - int vreg = op->vreg; + int vreg = ops->op_get_vreg(instr, op_i); + int id = 0; + int mapping = scc_mir_vreg_lookup(ctx->func, vreg, &id); + int preg = id, slot = id; - // 查询当前 vreg 的映射(可能已经被之前的分配改为 MEM 等,但我们只需要 - // slot) - scc_mir_vreg_op(ctx->func, vreg, op); - int slot; - if (op->kind == SCC_MIR_OP_VREG) { - // 还没有 slot → 分配一个 + if (mapping == 1) { + // 已预着色 + ops->mark_reg_used(ctx, preg); + ops->op_set_preg(instr, op_i, preg); + continue; + } + + if (mapping == 0) slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8); - } else { - // 已经是 MEM,直接用它的 slot - Assert(op->kind == SCC_MIR_OP_STACK_SLOT); - slot = op->stack_slot; - } - // 在本指令内查找是否已为这个 vreg 分配了 preg - int preg = -1; - for (int k = 0; k < local_cnt; k++) { - if (local_vreg[k] == vreg) { - preg = local_preg[k]; - break; - } - } - if (preg == -1) { - // 新分配 - preg = ops->acquire_reg(ctx); - scc_vec_push(allocated_pregs, preg); - local_vreg[local_cnt] = vreg; - local_preg[local_cnt] = preg; - local_cnt++; - } + preg = ops->acquire_reg(ctx); + scc_vec_push(allocated, preg); - // 读写属性 - scc_op_access_t acc = ops->get_operand_access(ctx, instr->opcode, i); - - // reload: slot → preg + scc_reg_op_access_t acc = ops->get_operand_access(ctx, opcode, op_i); if (acc == SCC_REG_ALLOC_OP_ACCESS_READ || - acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) { + acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) ops->emit_reload(&before, preg, slot); - } - - // spill: preg → slot if (acc == SCC_REG_ALLOC_OP_ACCESS_WRITE || - acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) { + acc == SCC_REG_ALLOC_OP_ACCESS_READWRITE) ops->emit_spill(&after, preg, slot); - } - // 替换操作数 - op->kind = SCC_MIR_OP_PREG; - op->preg = preg; + ops->op_set_preg(instr, op_i, preg); } - // 释放本指令分配的临时寄存器 - scc_vec_foreach(allocated_pregs, i) - ops->release_reg(ctx, scc_vec_at(allocated_pregs, i)); - // 合并指令流 - scc_vec_foreach(before, i) scc_vec_push(*instr_vec, scc_vec_at(before, i)); - scc_vec_push(*instr_vec, *instr); - scc_vec_foreach(after, i) scc_vec_push(*instr_vec, scc_vec_at(after, i)); + scc_vec_foreach(before, i) scc_vec_sized_push( + *instr_vec, instr_size, scc_vec_sized_at_ptr(before, instr_size, i), + instr_size); + scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size); + scc_vec_foreach(after, i) scc_vec_sized_push( + *instr_vec, instr_size, scc_vec_sized_at_ptr(after, instr_size, i), + instr_size); - // 隐式寄存器清理 + // 清理隐式寄存器 for (const int *p = implicit_defs; *p != -1; p++) ops->mark_reg_used(ctx, *p); for (const int *p = implicit_uses; *p != -1; p++) @@ -176,63 +78,40 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx, scc_vec_free(before); scc_vec_free(after); - scc_vec_free(allocated_pregs); + scc_vec_foreach(allocated, l) + ops->release_reg(ctx, scc_vec_at(allocated, l)); + scc_vec_free(allocated); } -/* 对一个基本块执行分配 */ -static void alloc_bb(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module, - scc_cfg_bblock_id_t bb_id) { - scc_cfg_bblock_t *bb = - scc_cfg_module_unsafe_get_bblock(&module->cfg_module, bb_id); - Assert(bb != nullptr); - scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES(bb); - - scc_mir_instr_vec_t new_instrs; - scc_vec_init(new_instrs); - - scc_vec_foreach(*old_instrs, i) { - scc_mir_instr_t ins = scc_vec_at(*old_instrs, i); - if (ins.opcode == SCC_MIR_PSUEDO_ALLOCA) { - scc_mir_vreg_op(ctx->func, ins.operands[0].vreg, &ins.operands[0]); - scc_vec_push(new_instrs, ins); - continue; - } - alloc_instr(ctx, &new_instrs, &ins); - } - - scc_vec_free(*old_instrs); - *old_instrs = new_instrs; -} - -/* 对一个函数运行分配 */ -static void alloc_func(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module, - scc_mir_func_t *func) { - ctx->ops.clean_mark_regs(ctx); - - ctx->func = func; - scc_vec_foreach(func->bblocks, i) { - scc_cfg_bblock_id_t bb_id = scc_vec_at(func->bblocks, i); - alloc_bb(ctx, module, bb_id); - } -} - -/* 公开入口 */ void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module) { - Assert(ctx != nullptr && module != nullptr); - - Assert(ctx->ops.acquire_reg != nullptr); - Assert(ctx->ops.clean_mark_regs != nullptr); - Assert(ctx->ops.emit_copy != nullptr); - Assert(ctx->ops.emit_reload != nullptr); - Assert(ctx->ops.emit_spill != nullptr); - Assert(ctx->ops.get_implicit_regs != nullptr); - Assert(ctx->ops.get_operand_access != nullptr); - Assert(ctx->ops.mark_reg_used != nullptr); - Assert(ctx->ops.release_reg != nullptr); + const scc_reg_alloc_op_t *ops = &ctx->ops; + ctx->module = module; scc_vec_foreach(module->cfg_module.funcs, i) { if (i == 0) continue; - alloc_func(ctx, module, &scc_vec_at(module->cfg_module.funcs, i)); + scc_mir_func_t *func = &scc_vec_at(module->cfg_module.funcs, i); + + ops->clean_mark_regs(ctx); + ctx->func = func; + + scc_vec_foreach(func->bblocks, j) { + scc_cfg_bblock_id_t bb_id = scc_vec_at(func->bblocks, j); + scc_cfg_bblock_t *bb = + scc_cfg_module_unsafe_get_bblock(&module->cfg_module, bb_id); + + scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb); + scc_mir_instr_vec_t new_instrs; + scc_vec_init(new_instrs); + + scc_vec_foreach(*old_instrs, k) { + scc_mir_instr_t *instr = scc_vec_sized_at_ptr( + *old_instrs, ctx->module->instr_size, k); + alloc_instr(ctx, &new_instrs, instr); + } + + scc_vec_free(*old_instrs); + *old_instrs = new_instrs; + } } } diff --git a/libs/ir/mir/src/scc_lir2mir.c b/libs/ir/mir/src/scc_lir2mir.c index dcbcea4..9a13209 100644 --- a/libs/ir/mir/src/scc_lir2mir.c +++ b/libs/ir/mir/src/scc_lir2mir.c @@ -1,10 +1,10 @@ -#include +#include #include #include void scc_lir2mir(scc_mir_module_t *mir_module, const scc_lir_module_t *lir_module) { - // FIXME hack cfg module + // Move mir_module->cfg_module = lir_module->cfg_module; scc_x86_64_isel_t isel; diff --git a/libs/ir/mir/src/scc_mir.c b/libs/ir/mir/src/scc_mir.c index 7418f80..9dae72d 100644 --- a/libs/ir/mir/src/scc_mir.c +++ b/libs/ir/mir/src/scc_mir.c @@ -4,6 +4,7 @@ void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta) { func_meta->frame_size = 0; func_meta->stack_alignment = 0; func_meta->vregs_count = 0; + func_meta->target_data = nullptr; scc_vec_init(func_meta->stack_slots); // For null stack slot @@ -16,24 +17,6 @@ int scc_mir_alloc_vreg(scc_mir_func_t *func) { return meta->vregs_count++; } -void scc_mir_vreg_op(const scc_mir_func_t *func, int vreg, - scc_mir_operand_t *out) { - scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); - isize idx = - (isize)scc_hashtable_get(&meta->vreg2physic, (void *)(usize)vreg); - if (idx == 0) { - out->kind = SCC_MIR_OP_VREG; - out->vreg = vreg; - } else if (idx < 0) { - out->kind = SCC_MIR_OP_PREG; - out->preg = (int)-idx; - } else { - out->kind = SCC_MIR_OP_STACK_SLOT; - Assert(idx < scc_vec_size(meta->stack_slots)); - out->stack_slot = (int)(usize)idx; - } -} - void scc_mir_vreg_map2preg(scc_mir_func_t *func, int vreg, int preg) { scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); isize val = diff --git a/libs/ir/mir/src/scc_mir_dump.c b/libs/ir/mir/src/scc_mir_dump.c index 1d1ddfd..89b14d5 100644 --- a/libs/ir/mir/src/scc_mir_dump.c +++ b/libs/ir/mir/src/scc_mir_dump.c @@ -1,37 +1,11 @@ +#include #include -void scc_x86_instr_dump(scc_tree_dump_t *dump, const scc_mir_instr_t *instr); - -void scc_mir_dump_instr(scc_mir_dump_ctx_t *ctx, const scc_mir_instr_t *ins) { - scc_tree_dump_t *td = ctx->dump_ctx; - scc_tree_dump_begin_line(td); - if (ins->opcode >= 0) { - scc_x86_instr_dump(td, ins); - return; - } - - switch (ins->opcode) { - case SCC_MIR_PSUEDO_ALLOCA: - scc_tree_dump_node(td, " @alloca"); - scc_tree_dump_append_fmt(td, "(%d)", ins->operands[1].imm); - if (ins->operands[0].kind == SCC_MIR_OP_VREG) { - scc_tree_dump_append_fmt(td, " %%%d", ins->operands[0].vreg); - } else if (ins->operands[0].kind == SCC_MIR_OP_STACK_SLOT) { - scc_tree_dump_append_fmt(td, " [%d]", ins->operands[0].stack_slot); - } else { - scc_tree_dump_append(td, ""); - } - break; - default: - break; - } -} - +void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr); void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) { Assert(ctx != nullptr && bb != nullptr); scc_tree_dump_t *td = ctx->dump_ctx; - // 基本块头部 scc_tree_dump_begin_line(td); scc_tree_dump_branch(td, "#BB%zu", bb->id); if (bb->name) { @@ -39,11 +13,22 @@ void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) { } scc_tree_dump_append(td, ":"); - // 输出每条指令 - scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb); - scc_vec_foreach(*instrs, i) { - const scc_mir_instr_t *ins = &scc_vec_at(*instrs, i); - scc_mir_dump_instr(ctx, ins); + for (int i = 0; i < scc_vec_size(bb->values); i += 1) { + scc_tree_dump_begin_line(td); + scc_mir_instr_t *instr = + scc_vec_sized_at_ptr(bb->values, ctx->mir_module->instr_size, i); + if (instr->opcode < 0) { + switch (instr->opcode) { + case SCC_MIR_PSEUDO_ALLOCA: + scc_tree_dump_append_fmt(td, " alloca(%d)", + instr->data.alloc.size); + break; + default: + break; + } + } else { + scc_x86_instr_dump(td, (void *)instr); + } } } @@ -52,11 +37,9 @@ void scc_mir_dump_func(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func) { scc_tree_dump_t *td = ctx->dump_ctx; scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); - // 函数头部 scc_tree_dump_begin_line(td); scc_tree_dump_node(td, "func @%s", func->name ? func->name : ""); - // 输出所有基本块 scc_vec_foreach(func->bblocks, i) { scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i); const scc_cfg_bblock_t *bb = @@ -67,7 +50,6 @@ void scc_mir_dump_func(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func) { void scc_mir_dump_module(scc_mir_dump_ctx_t *ctx) { scc_vec_foreach(ctx->mir_module->cfg_module.symbols, i) { - // FIXME 0 is null if (i == 0) continue; scc_cfg_symbol_t *sym = diff --git a/libs/ir/mir/src/scc_mir_module.c b/libs/ir/mir/src/scc_mir_module.c index f628c90..b4ec9ff 100644 --- a/libs/ir/mir/src/scc_mir_module.c +++ b/libs/ir/mir/src/scc_mir_module.c @@ -1,6 +1,8 @@ #include "scc_mir_module.h" void scc_mir_module_init(scc_mir_module_t *mir_module) { + mir_module->instr_size = 0; + mir_module->cfg_module = (scc_cfg_module_t){0}; scc_vec_init(mir_module->func_metas); scc_vec_init(mir_module->symbol_metas); } diff --git a/libs/ir/mir/src/scc_mir_pass.c b/libs/ir/mir/src/scc_mir_pass.c index 3a04e2f..0a0ab65 100644 --- a/libs/ir/mir/src/scc_mir_pass.c +++ b/libs/ir/mir/src/scc_mir_pass.c @@ -1,4 +1,5 @@ -#include +#include +#include #include // #include @@ -28,7 +29,7 @@ void scc_prolog_epilog(scc_prolog_epilog_t *ctx, scc_mir_module_t *module) { scc_cfg_bblock_t *bb = scc_cfg_module_unsafe_get_bblock(&module->cfg_module, bb_id); Assert(bb != nullptr); - scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES(bb); + scc_mir_instr_vec_t *old_instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb); scc_mir_instr_vec_t new_instrs; scc_vec_init(new_instrs); @@ -39,13 +40,15 @@ void scc_prolog_epilog(scc_prolog_epilog_t *ctx, scc_mir_module_t *module) { } scc_vec_foreach(*old_instrs, i) { - scc_mir_instr_t ins = scc_vec_at(*old_instrs, i); - if (ins.opcode == SCC_MIR_PSUEDO_ALLOCA) { + scc_mir_instr_t *ins = + scc_vec_sized_at_ptr(*old_instrs, module->instr_size, i); + if (ins->opcode == SCC_MIR_PSEUDO_ALLOCA) { continue; } - scc_vec_push(new_instrs, ins); + // FIXME error + scc_vec_sized_push(new_instrs, module->instr_size, ins, + module->instr_size); } - scc_vec_free(*old_instrs); *old_instrs = new_instrs; } @@ -53,8 +56,7 @@ void scc_prolog_epilog(scc_prolog_epilog_t *ctx, scc_mir_module_t *module) { } void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) { - scc_reg_alloc_ctx_t reg_alloc_ctx = { - .func = nullptr, .instrs = nullptr, .ops = {0}}; + scc_reg_alloc_ctx_t reg_alloc_ctx = {.func = nullptr, .ops = {0}}; scc_reg_alloc_fill_arch_x86(®_alloc_ctx.ops); scc_win_pc_x64_reg_alloc_fill(®_alloc_ctx.ops); diff --git a/libs/ir/mir/src/target/win64_abi.c b/libs/ir/mir/src/target/win64_abi.c index 146a4cb..80709b1 100644 --- a/libs/ir/mir/src/target/win64_abi.c +++ b/libs/ir/mir/src/target/win64_abi.c @@ -1,54 +1,42 @@ #include #include -#include +#include #include #include -static const int WIN64_DEFAULT_ALIGN = 8; static const int WIN64_STACK_ALIGN = 16; -static void transit_vreg(scc_mir_func_meta_t *func, scc_mir_operand_t *op) { - Assert(op->kind == SCC_MIR_OP_VREG); -} - static void frame_alloc_impl(scc_frame_layout_t *ctx, scc_mir_module_t *mir_module, scc_mir_func_t *mir_func) { - /* - WIN ABI - */ ctx->offset = 8; scc_mir_func_meta_t *func_meta = SCC_MIR_FUNC_META(mir_func); scc_vec_foreach(mir_func->bblocks, i) { scc_cfg_bblock_id_t id = scc_vec_at(mir_func->bblocks, i); scc_cfg_bblock_t *bb = scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id); - scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb); + scc_mir_x86_instr_vec_t *instrs = SCC_MIR_X86_BBLOCK_INSTRS(bb); scc_vec_foreach(*instrs, j) { - scc_mir_instr_t *ins = &scc_vec_at(*instrs, j); - for (int k = 0; k < ins->num_operands; k += 1) { - scc_mir_operand_t *op = &ins->operands[k]; - if (op->kind == SCC_MIR_OP_VREG) { - Panic("vreg not supported in frame layout"); - } else if (op->kind == SCC_MIR_OP_STACK_SLOT) { + scc_mir_x86_instr_t *ins = &scc_vec_at(*instrs, j); + for (int k = 0; k < ins->x86_instr.num_operands; k++) { + scc_x86_operand_value_t *op = &ins->x86_instr.operands[k]; + if (scc_x86_op_is_slot(op)) { + int slot_id = scc_x86_op_slot_id(op); scc_mir_stack_slot_t *slot = - scc_mir_unsafe_slot(mir_func, op->stack_slot); - op->kind = SCC_MIR_OP_STACK_OFFSET; + scc_mir_unsafe_slot(mir_func, slot_id); if (slot->offset == 0) { - // FIXME align ctx->offset += slot->size; slot->offset = ctx->offset; } - op->stack_offset = slot->offset; + op->mem.base = SCC_X86_REG_RSP; + op->mem.disp = -slot->offset; } } } } - // Windows shadow space - int total_size = ctx->offset + 32; // 加上影子空间 - // 16 字节栈对齐 + int total_size = ctx->offset + 32; // shadow space ctx->offset = (total_size + WIN64_STACK_ALIGN - 1) & ~(WIN64_STACK_ALIGN - 1); func_meta->frame_size = ctx->offset; @@ -77,17 +65,19 @@ static void prologue(void *userdata, const scc_mir_func_t *func) { int frame_size = meta->frame_size; // 之前计算好的 // 1. push rbp - add_instr_1(isel, SCC_X86_IFORM_PUSH_GPRV_50, reg_operand(SCC_X86_REG_RBP)); + add_instr_1(isel, SCC_X86_IFORM_PUSH_GPRV_50, + scc_x86_op_preg(SCC_X86_REG_RBP)); // 2. mov rbp, rsp - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89, - reg_operand(SCC_X86_REG_RBP), reg_operand(SCC_X86_REG_RSP)); + add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_8B, + scc_x86_op_preg(SCC_X86_REG_RBP), + scc_x86_op_preg(SCC_X86_REG_RSP)); // 3. sub rsp, frame_size if (frame_size > 0) { - scc_mir_operand_t imm = {.kind = SCC_MIR_OP_IMM, .imm = frame_size}; + scc_x86_operand_value_t imm = scc_x86_op_imm(frame_size); add_instr_2(isel, SCC_X86_IFORM_SUB_GPRV_IMMZ, - reg_operand(SCC_X86_REG_RSP), imm); + scc_x86_op_preg(SCC_X86_REG_RSP), imm); } } @@ -101,11 +91,13 @@ static void epilogue(void *userdata, const scc_mir_func_t *func) { ret */ // 1. mov rsp, rbp - add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89, - reg_operand(SCC_X86_REG_RSP), reg_operand(SCC_X86_REG_RBP)); + add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_8B, + scc_x86_op_preg(SCC_X86_REG_RSP), + scc_x86_op_preg(SCC_X86_REG_RBP)); // 2. pop rbp - add_instr_1(isel, SCC_X86_IFORM_POP_GPRV_58, reg_operand(SCC_X86_REG_RBP)); + add_instr_1(isel, SCC_X86_IFORM_POP_GPRV_8F, + scc_x86_op_preg(SCC_X86_REG_RBP)); } void scc_win_pc_x64_prolog_epilog_init(scc_prolog_epilog_t *ctx) { @@ -115,81 +107,65 @@ 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; - /* - Windows x64 parameter passing - https://learn.microsoft.com/zh-cn/cpp/build/x64-calling-convention?view=msvc-180#parameter-passing - - eg. - func1(int a, int b, int c, int d, int e, int f); - // a in RCX, b in RDX, c in R8, d in R9, f then e passed on stack - - func2(float a, double b, float c, double d, float e, float f); - // a in XMM0, b in XMM1, c in XMM2, d in XMM3, f then e passed on stack - - func3(int a, double b, int c, float d, int e, float f); - // a in RCX, b in XMM1, c in R8, d in XMM3, f then e passed on stack - - func4(__m64 a, __m128 b, struct c, float d, __m128 e, __m128 f); - // a in RCX, ptr to b in RDX, ptr to c in R8, d in XMM3, - // ptr to f passed on stack, then ptr to e passed on stack - */ 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, reg_operand(SCC_X86_REG_RCX), + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RCX), scc_x86_lir_val_to_mir_op(isel, args), 8); break; case 1: - scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_RDX), + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RDX), scc_x86_lir_val_to_mir_op(isel, args), 8); break; case 2: - scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_R8), + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_R8), scc_x86_lir_val_to_mir_op(isel, args), 8); break; case 3: - scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_R9), + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_R9), scc_x86_lir_val_to_mir_op(isel, args), 8); break; default: - // Using stack - scc_mir_operand_t op = scc_x86_lir_val_to_mir_op(isel, args); + scc_x86_operand_value_t op = scc_x86_lir_val_to_mir_op(isel, args); add_instr_1(isel, - op.kind == SCC_MIR_OP_PREG || op.kind == SCC_MIR_OP_VREG - ? SCC_X86_IFORM_PUSH_GPRV_50 - : SCC_X86_IFORM_PUSH_IMMZ, + op.kind == SCC_X86_OPR_REG ? SCC_X86_IFORM_PUSH_GPRV_50 + : SCC_X86_IFORM_PUSH_IMMZ, op); break; } } - emit_call(isel, instr->metadata.call.callee); + emit_direct_call(isel, instr->metadata.call.callee); - scc_mir_operand_t ret_reg = scc_x86_lir_val_to_mir_op(isel, &instr->to); - if (ret_reg.kind == SCC_MIR_OP_VREG) { - scc_x86_emit_move(isel, ret_reg, reg_operand(SCC_X86_REG_RAX), 8); - } else { - TODO(); + scc_x86_operand_value_t ret_reg = + scc_x86_lir_val_to_mir_op(isel, &instr->to); + if (ret_reg.kind != SCC_X86_OPR_NONE) { + scc_x86_emit_move(isel, ret_reg, scc_x86_op_preg(SCC_X86_REG_RAX), 8); } } -static scc_mir_operand_t lower_param(void *userdata, const scc_lir_val_t *val) { - scc_x86_64_isel_t *isel = userdata; +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); switch (val->data.arg) { case 0: - return reg_operand(SCC_X86_REG_RCX); + *out = scc_x86_op_preg(SCC_X86_REG_RCX); + break; case 1: - return reg_operand(SCC_X86_REG_RDX); + *out = scc_x86_op_preg(SCC_X86_REG_RDX); + break; case 2: - return reg_operand(SCC_X86_REG_R8); + *out = scc_x86_op_preg(SCC_X86_REG_R8); + break; case 3: - return reg_operand(SCC_X86_REG_R9); + *out = scc_x86_op_preg(SCC_X86_REG_R9); + break; default: - return (scc_mir_operand_t){.kind = SCC_MIR_OP_STACK_SLOT, - .stack_slot = -val->data.arg}; + *out = scc_x86_op_slot(-val->data.arg); + break; } } @@ -197,7 +173,7 @@ 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; if (ret_val.kind != SCC_LIR_INSTR_KIND_NONE) { - scc_x86_emit_move(isel, reg_operand(SCC_X86_REG_RAX), + scc_x86_emit_move(isel, scc_x86_op_preg(SCC_X86_REG_RAX), scc_x86_lir_val_to_mir_op(isel, &ret_val), 8); } emit_ret(isel); @@ -214,40 +190,7 @@ void scc_win_pc_x64_abi_lowering(scc_abi_lowering_t *abi_lowering) { abi_lowering->lower_va_end = nullptr; } -static const int reg_pool[] = { - SCC_X86_REG_R8, SCC_X86_REG_R9, SCC_X86_REG_R10, SCC_X86_REG_R11, - SCC_X86_REG_R12, SCC_X86_REG_R13, SCC_X86_REG_R14, SCC_X86_REG_R15}; -static uint32_t reg_mask = 0; // 1 表示已占用 - -static int acquire_reg(void *ctx) { - for (int i = 0; i < SCC_ARRLEN(reg_pool); i++) - if (!(reg_mask & (1u << i))) { - reg_mask |= (1u << i); - return reg_pool[i]; - } - UNREACHABLE(); // 可改为溢出逻辑 -} - -static void release_reg(void *ctx, int preg) { - for (int i = 0; i < SCC_ARRLEN(reg_pool); i++) - if (reg_pool[i] == preg) { - reg_mask &= ~(1u << i); - return; - } -} - -static void mark_reg_used(void *ctx, int preg) { - for (int i = 0; i < SCC_ARRLEN(reg_pool); i++) - if (reg_pool[i] == preg) { - reg_mask |= (1u << i); - return; - } -} -static void clean_mark_regs(void *ctx) { reg_mask = 0; } - void scc_win_pc_x64_reg_alloc_fill(scc_reg_alloc_op_t *ops) { - ops->acquire_reg = acquire_reg; - ops->release_reg = release_reg; - ops->mark_reg_used = mark_reg_used; - ops->clean_mark_regs = clean_mark_regs; + (void)ops; + // 寄存器池已在 scc_reg_alloc_fill_arch_x86 中注册 } diff --git a/libs/ir2mcode/src/scc_ir2mcode.c b/libs/ir2mcode/src/scc_ir2mcode.c index fd81588..b18cc33 100644 --- a/libs/ir2mcode/src/scc_ir2mcode.c +++ b/libs/ir2mcode/src/scc_ir2mcode.c @@ -2,52 +2,30 @@ #include #include +#include #include #include #include -void mir_x86_to_mcode(scc_mcode_t *mcode, const scc_mir_instr_t *ins) { +void mir_x86_to_mcode(scc_mcode_t *mcode, const scc_mir_x86_instr_t *_ins) { + scc_x86_instr_t *ins = (void *)_ins; + if (ins->opcode < 0 || ins->opcode >= SCC_X86_IFORM_COUNT) { + return; + } scc_x86_operand_value_t ops[8] = {0}; - for (int i = 0; i < ins->num_operands; i += 1) { - switch (ins->operands[i].kind) { - case SCC_MIR_OP_VREG: + for (int i = 0; i < ins->num_operands; i++) { + if (scc_x86_op_is_vreg(&ins->operands[i])) Panic("can't convert vreg to mcode"); - break; - case SCC_MIR_OP_PREG: - ops[i].kind = SCC_X86_OPR_REG; - ops[i].reg = ins->operands[i].preg; - break; - case SCC_MIR_OP_STACK_SLOT: - Panic("can't convert mem to mcode"); - break; - case SCC_MIR_OP_STACK_OFFSET: - // TODO - ops[i].kind = SCC_X86_OPR_MEM; - ops[i].mem.base = SCC_X86_REG_RSP; - ops[i].mem.index = SCC_X86_REG_INVALID; - ops[i].mem.scale = 1; - ops[i].mem.disp = -ins->operands[i].stack_offset; // 注意符号 - break; - case SCC_MIR_OP_IMM: - ops[i].kind = SCC_X86_OPR_IMM; - ops[i].imm = ins->operands[i].imm; - break; - case SCC_MIR_OP_SYMBOL: - case SCC_MIR_OP_BLOCK: - ops[i].kind = SCC_X86_OPR_RELBR; - ops[i].imm = 0; - break; - default: - Panic("unsupported operand kind"); - }; + if (scc_x86_op_is_slot(&ins->operands[i])) + Panic("can't convert unresolved slot to mcode"); + ops[i] = ins->operands[i]; } scc_x86_encode_inst(mcode, ins->opcode, ops); } void scc_ir2mcode_emit_instr(scc_mcode_t *mcode, const scc_mir_instr_t *mir_instr) { - // TODO - mir_x86_to_mcode(mcode, mir_instr); + mir_x86_to_mcode(mcode, (const scc_mir_x86_instr_t *)mir_instr); } void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) { @@ -59,9 +37,11 @@ void scc_ir2mcode(scc_mcode_t *mcode, const scc_mir_module_t *mir_module) { 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); - scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb); + const scc_mir_x86_instr_vec_t *instrs = + SCC_MIR_BBLOCK_VALUES_PTR(bb); scc_vec_foreach(*instrs, i) { - const scc_mir_instr_t *ins = &scc_vec_at(*instrs, i); + const scc_mir_instr_t *ins = + scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i); scc_ir2mcode_emit_instr(mcode, ins); } } diff --git a/libs/ir2mcode/src/scc_ir2sccf.c b/libs/ir2mcode/src/scc_ir2sccf.c index ba98af4..27cdb09 100644 --- a/libs/ir2mcode/src/scc_ir2sccf.c +++ b/libs/ir2mcode/src/scc_ir2sccf.c @@ -88,9 +88,10 @@ void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) { 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); - scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb); + 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_at(*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, ins); }