refactor(ast2ir): 提取模块访问函数并优化类型大小计算

- 添加 scc_ast2ir_mir_module 内联函数统一访问模块
- 替换所有直接访问 ctx->builder.cprog->module 的地方
- 移除重复的 scc_hir_type_size 函数实现
- 添加 scc_hir_module_type_size 函数到模块接口
- 更新所有类型大小计算调用使用新函数

feat(hir): 增强构建器安全性和全局变量处理

- 为 scc_hir_builder_integer 添加空指针检查断言
- 修复 scc_hir_builder_global_alloca 中全局变量类型设置
- 改进 scc_hir_builder_get_elem_ptr 处理空指针索引情况
- 重构字符串常量生成使用 get_elem_ptr 构建器函数

refactor(lir): 简化地址表达式表示并增强内置函数支持

- 移除复杂地址结构体 scc_lir_addr_t
- 简化 scc_lir_instr 结构体中的地址表示
- 移除 STORE_ADDR 操作码
- 添加 memcpy 和 memset 内置函数操作码
- 在符号元数据中使用联合体替代嵌套结构体

feat(hir2lir): 完善 HIR 到 LIR 转换中的内置函数处理

- 添加 ensure_vreg 辅助函数确保虚拟寄存器操作数
- 正确处理全局变量地址符号引用
- 优化 GET_ELEM_PTR 转换使用类型大小计算
- 完整实现所有内置函数(BUILTIN)的 LIR 转换
- 包括 memcpy、memset、va_start、va_arg、va_end、va_copy 等
This commit is contained in:
zzy
2026-05-22 15:15:18 +08:00
parent 41d060d7e7
commit d78b91894e
27 changed files with 1272 additions and 563 deletions

View File

@@ -19,8 +19,12 @@ void scc_isel_x86_64(scc_mir_module_t *mir_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,
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);
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);
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 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,
@@ -52,16 +56,18 @@ 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) \
#define add_instr_1(isel, iform, arg1, _size) \
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) \
#define add_instr_2(isel, iform, arg1, arg2, _size) \
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)

View File

@@ -9,8 +9,11 @@
#include <x86/scc_x86_reg.h>
typedef struct {
int opcode;
uint8_t num_operands;
union {
int opcode;
scc_x86_iform_t iform;
};
u8 num_operands;
scc_x86_operand_value_t operands[6];
scc_pos_t src_loc;
} scc_x86_instr_t;
@@ -29,13 +32,17 @@ typedef SCC_VEC(scc_mir_x86_instr_t) scc_mir_x86_instr_vec_t;
#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 cbool scc_x86_reg_is_vreg(scc_x86_reg_t reg) {
return reg >= SCC_X86_REG_COUNT;
}
static inline cbool scc_x86_op_is_vreg(const scc_x86_operand_value_t *op) {
return op->kind == SCC_X86_OPR_REG && scc_x86_reg_is_vreg(op->reg);
}
static inline int scc_x86_reg_get_vreg(scc_x86_reg_t reg) {
return (int)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;
return scc_x86_reg_get_vreg(op->reg);
}
static inline void scc_x86_op_set_preg(scc_x86_operand_value_t *op,
scc_x86_reg_t preg) {
@@ -53,6 +60,7 @@ static inline scc_x86_operand_value_t scc_x86_op_slot(int slot_id) {
o.mem.disp.displacement_bits = 0;
return o;
}
static inline bool scc_x86_op_is_slot(const scc_x86_operand_value_t *op) {
return op->kind == SCC_X86_OPR_MEM && op->mem.base == SCC_X86_REG_INVALID;
}

View File

@@ -9,6 +9,12 @@ typedef enum {
SCC_REG_ALLOC_OP_ACCESS_READWRITE = 2,
} scc_reg_op_access_t;
typedef struct {
const scc_mir_instr_t *instr;
int op_idx;
int op_sub_idx;
} scc_reg_alloc_iter_t;
// 后端回调表 —— 框架通过回调获取/修改指令,不感知具体布局
typedef struct scc_reg_alloc_op {
// ── 寄存器池 ──
@@ -18,25 +24,21 @@ typedef struct scc_reg_alloc_op {
void (*clean_mark_regs)(void *ctx);
// ── 指令信息 ──
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_alloc_iter_t iter;
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_end)(scc_reg_alloc_iter_t *iter);
// 读写属性与隐式寄存器
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_spill)(void *out, int preg, int slot, int size);
void (*emit_reload)(void *out, int preg, int slot, int size);
void (*emit_copy)(void *out, int dst_preg, int src_preg, int size);
} scc_reg_alloc_op_t;

View File

@@ -5,10 +5,8 @@
#include <scc_lir_module.h>
typedef SCC_VEC(char) scc_mir_instr_vec_t;
typedef struct {
} scc_mir_symbol_t;
typedef scc_lir_symbol_meta_t scc_mir_symbol_meta_t;
#define SCC_MIR_SYMBOL_META(symbol) ((scc_mir_symbol_meta_t *)(symbol)->meta)
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;

View File

@@ -9,7 +9,16 @@ 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_x86_instr_t *instr) {
static inline void scc_x86_dump_reg(scc_tree_dump_t *td,
const scc_x86_reg_t reg) {
if (scc_x86_reg_is_vreg(reg))
scc_tree_dump_append_fmt(td, "%%%d", scc_x86_reg_get_vreg(reg));
else
scc_tree_dump_append_fmt(td, "$%s", preg_name(reg));
}
void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func,
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, " ???");
@@ -26,24 +35,43 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) {
const scc_x86_operand_value_t *op = &instr->x86_instr.operands[i];
switch (op->kind) {
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));
scc_x86_dump_reg(td, op->reg);
break;
case SCC_X86_OPR_IMM:
scc_tree_dump_append_fmt(td, "%ld", op->imm0);
break;
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 %c %llu]",
op->mem.disp.displacement >= 0 ? '+' : '-',
op->mem.disp.displacement < 0 ? -op->mem.disp.displacement
: op->mem.disp.displacement);
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(func, slot_id);
if (slot == nullptr) {
scc_tree_dump_append_fmt(td, "[slot:%d<null>]", slot_id);
} else {
scc_tree_dump_append_fmt(td, "[slot:%d(of=%d,sz=%d,al=%d)]",
slot_id, slot->offset, slot->size,
slot->alignment);
}
} else {
scc_tree_dump_append(td, "(");
scc_x86_dump_reg(td, op->mem.base);
if (op->mem.index != SCC_X86_REG_INVALID) {
scc_tree_dump_append(td, "[");
scc_x86_dump_reg(td, op->mem.index);
scc_tree_dump_append(td, "]");
}
if (op->mem.scale != 1) {
scc_tree_dump_append_fmt(td, "(x%d)", op->mem.scale);
}
if (op->mem.disp.displacement != 0) {
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);
}
scc_tree_dump_append(td, ")");
}
break;
case SCC_X86_OPR_RELBR:
scc_tree_dump_append(td, "<relbr>");
@@ -62,8 +90,10 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_x86_instr_t *instr) {
}
break;
default:
scc_tree_dump_append(td, "<?>");
break;
}
scc_tree_dump_append_fmt(td, "(%zu)", op->size);
}
}
@@ -92,79 +122,54 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel,
op = scc_x86_op_imm(*(i64 *)&val->data.fimm);
break;
case SCC_LIR_INSTR_KIND_SYMBOL:
// 默认作为绝对地址立即数(后续可优化为 RIP 相对)
op = scc_x86_op_reloc_global_imm(val->data.symbol, 0);
op = scc_x86_op_reloc_global_relrip(val->data.symbol, 0);
break;
case SCC_LIR_INSTR_KIND_ARG:
Assert(isel->abi_lowering.lower_param);
isel->abi_lowering.lower_param(isel, val, &op);
break;
default:
UNREACHABLE();
Panic("unsupported lir instr kind %d", val->kind);
break;
}
return op;
}
static scc_x86_operand_value_t build_mem_op(scc_x86_64_isel_t *isel,
scc_x86_operand_value_t base,
scc_x86_operand_value_t index,
int scale, i64 offset) {
(void)isel;
scc_x86_operand_value_t mem_op;
mem_op.kind = SCC_X86_OPR_MEM;
// base 必须为寄存器
Assert(base.kind == SCC_X86_OPR_REG);
mem_op.mem.base = base.reg;
// index 可选
if (index.kind == SCC_X86_OPR_REG) {
mem_op.mem.index = index.reg;
mem_op.mem.scale = scale;
} else {
mem_op.mem.index = SCC_X86_REG_INVALID;
mem_op.mem.scale = 1;
}
mem_op.mem.disp.displacement = offset;
mem_op.mem.disp.displacement_bits = 0;
return mem_op;
}
// 虚拟临时寄存器分配(简单递增)
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_x86_operand_value_t dst,
scc_x86_operand_value_t src, u8 size) {
scc_x86_operand_kind_t dst_kind = dst.kind;
if (dst_kind == SCC_X86_OPR_RELOC) {
dst_kind = dst.reloc.kind;
}
scc_x86_operand_kind_t src_kind = src.kind;
if (src_kind == SCC_X86_OPR_RELOC) {
src_kind = src.reloc.kind;
}
if (dst_kind == SCC_X86_OPR_REG) {
if (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_X86_OPR_IMM && src.imm0 == 0) {
// 特殊:符号作为立即数地址
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMZ, dst, src);
} 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_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_X86_OPR_IMM) {
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_IMMZ, dst, src);
} 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_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 {
UNREACHABLE();
}
} else {
UNREACHABLE();
}
}
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);
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);
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, op0, op1, size);
} else {
UNREACHABLE();
}
@@ -213,6 +218,9 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op,
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;
bool is_imm = (src1.kind == SCC_X86_OPR_IMM);
scc_x86_iform_t iform;
@@ -240,7 +248,155 @@ static void emit_binary_op(scc_x86_64_isel_t *isel, scc_lir_op_t op,
default:
UNREACHABLE();
}
add_instr_2(isel, iform, dst, src1);
add_instr_2(isel, iform, dst, src1, size);
}
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);
}
}
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);
}
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);
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);
}
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);
}
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);
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);
}
static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst,
scc_x86_operand_value_t base,
scc_x86_operand_value_t index, int scale,
i64 offset) {
usize size = dst.size;
// 前置断言dst 必须是寄存器
Assert(dst.kind == SCC_X86_OPR_REG);
// scale 必须是 1,2,4,8 之一
Assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
// ---- 处理 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);
}
// ---- 处理 index * scale ----
scc_x86_operand_value_t scaled_index = index;
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);
index = index_tmp;
}
// ---- 计算 base + scaled_index ----
scc_x86_operand_value_t sum = base_reg;
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);
sum = dst;
}
add_instr_2(isel, SCC_X86_IFORM_ADD_GPRV_GPRV_03, sum, scaled_index,
size);
} else if (base_reg.kind == SCC_X86_OPR_REG) {
if (dst.reg != base_reg.reg)
scc_x86_emit_move(isel, dst, base_reg, 8);
sum = dst;
} else if (scaled_index.kind == SCC_X86_OPR_REG) {
scc_x86_emit_move(isel, dst, scaled_index, 8);
sum = dst;
} else {
// base 和 index 都无效 => 结果为 0
scc_x86_emit_move(isel, dst, scc_x86_op_imm(0), 8);
return;
}
// ---- 加上 offset ----
if (offset != 0) {
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);
} else if (sum.reg != dst.reg) {
scc_x86_emit_move(isel, dst, sum, 8);
}
}
static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
@@ -252,33 +408,31 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
u8 size = instr->size;
switch (instr->op) {
/* ---- 数据移动 ---- */
case SCC_LIR_MOV:
scc_x86_emit_move(isel, dst, src0, size);
break;
/* ---- 数据移动 ---- */
case SCC_LIR_LOAD:
// TODO check valid
scc_x86_emit_move(isel, dst, src0, size);
// src0 是地址可能是寄存器或内存操作数dst 是寄存器
scc_x86_emit_load(isel, dst, src0, size);
break;
case SCC_LIR_STORE:
// TODO check valid
scc_x86_emit_move(isel, src1, src0, size);
// src0 是要存储的值寄存器src1 是目标地址
scc_x86_emit_store(isel, src1, src0, size);
break;
case SCC_LIR_STORE_ADDR:
TODO();
case SCC_LIR_MOV:
// 纯粹的寄存器/立即数复制
scc_x86_emit_move(isel, dst, src0, size);
break;
case SCC_LIR_LOAD_ADDR:
add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src0);
// 计算地址,结果放入 dst寄存器
emit_load_addr(isel, dst, src0, src1, instr->metadata.addr.scale,
instr->metadata.addr.offset);
break;
/* ---- 一元运算 ---- */
case SCC_LIR_NEG:
add_instr_1(isel, SCC_X86_IFORM_NEG_GPRV, dst);
add_instr_1(isel, SCC_X86_IFORM_NEG_GPRV, dst, size);
break;
case SCC_LIR_NOT:
add_instr_1(isel, SCC_X86_IFORM_NOT_GPRV, dst);
add_instr_1(isel, SCC_X86_IFORM_NOT_GPRV, dst, size);
break;
/* ---- 算术/逻辑二元运算 ---- */
case SCC_LIR_ADD:
case SCC_LIR_SUB:
@@ -295,7 +449,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
scc_x86_emit_move(isel, op, src1, size);
src1 = op;
}
add_instr_2(isel, SCC_X86_IFORM_IMUL_GPRV_GPRV, dst, src1);
add_instr_2(isel, SCC_X86_IFORM_IMUL_GPRV_GPRV, dst, src1, size);
break;
case SCC_LIR_SHL:
@@ -318,7 +472,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, src1);
add_instr_2(isel, iform, dst, src1, size);
} else {
scc_x86_operand_value_t cl = scc_x86_op_preg(SCC_X86_REG_CL);
scc_x86_emit_move(isel, cl, src1, 1);
@@ -336,7 +490,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);
add_instr_2(isel, iform, dst, cl, size);
}
} break;
@@ -361,7 +515,7 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
(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);
add_instr_1(isel, div_if, src1, size);
if (instr->op == SCC_LIR_REM_S || instr->op == SCC_LIR_REM_U)
scc_x86_emit_move(isel, dst, rdx, size);
@@ -372,17 +526,17 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
/* ---- 比较指令 ---- */
case SCC_LIR_CMP: {
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);
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_IMMZ, src0, src1, size);
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);
add_instr_2(isel, SCC_X86_IFORM_CMP_GPRV_GPRV_3B, src0, src1, size);
else
UNREACHABLE();
scc_x86_iform_t setcc = cond_to_setcc(instr->metadata.cond);
add_instr_1(isel, setcc, dst);
add_instr_1(isel, setcc, dst, size);
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);
add_instr_2(isel, SCC_X86_IFORM_AND_GPRV_IMMZ, dst, one, size);
}
} break;
@@ -393,15 +547,15 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
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);
add_instr_1(isel, SCC_X86_IFORM_JNZ_RELBRZ, true_bb);
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, false_bb);
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);
} 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);
add_instr_1(isel, SCC_X86_IFORM_JMP_RELBRZ, jmp_bb, size);
} break;
/* ---- 栈分配 ---- */
@@ -412,10 +566,14 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
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;
x86instr.instr.data.alloc.size = instr->metadata.alloca.size_bytes;
x86instr.instr.data.alloc.align = instr->metadata.alloca.align_bytes;
scc_vec_push(isel->instrs, x86instr);
scc_mir_vreg_map2slot(isel->func, instr->to.data.reg, instr->size, 0);
scc_mir_vreg_map2slot(isel->func, instr->to.data.reg,
instr->metadata.alloca.size_bytes,
instr->metadata.alloca.align_bytes
? instr->metadata.alloca.align_bytes
: 8);
break;
}
@@ -429,12 +587,43 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) {
Assert(isel->abi_lowering.lower_call);
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);
} break;
case SCC_LIR_RET: {
Assert(isel->abi_lowering.lower_ret);
isel->abi_lowering.lower_ret(isel, instr);
} break;
case SCC_LIR_MEMCPY: {
scc_lir_val_t dest_val = instr->metadata.memcpy.dest;
scc_lir_val_t src_val = instr->metadata.memcpy.src;
// 将 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);
// 将 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_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);
add_instr_0(isel, SCC_X86_IFORM_REP_MOVSB);
} break;
default: {
UNREACHABLE();
Panic("unsupported instruction %d", instr->op);
} break;
}
}

View File

@@ -0,0 +1,161 @@
#include <arch/scc_x86_mir.h>
#include <scc_mir_module.h>
static bool same_x86_operand(const scc_x86_operand_value_t *a,
const scc_x86_operand_value_t *b) {
if (a->kind != b->kind)
return false;
switch (a->kind) {
case SCC_X86_OPR_REG:
return a->reg == b->reg;
case SCC_X86_OPR_MEM:
return a->mem.base == b->mem.base && a->mem.index == b->mem.index &&
a->mem.scale == b->mem.scale &&
a->mem.disp.displacement == b->mem.disp.displacement;
case SCC_X86_OPR_IMM:
return a->imm0 == b->imm0;
default:
return false;
}
}
static bool is_store_to_mem(const scc_mir_x86_instr_t *ins) {
int op = ins->x86_instr.opcode;
return op == SCC_X86_IFORM_MOV_MEMV_GPRV ||
op == SCC_X86_IFORM_MOV_MEMV_IMMZ;
}
static bool is_load_from_mem(const scc_mir_x86_instr_t *ins) {
int op = ins->x86_instr.opcode;
return op == SCC_X86_IFORM_MOV_GPRV_MEMV;
}
static bool is_reg_reg_move(const scc_mir_x86_instr_t *ins) {
int op = ins->x86_instr.opcode;
return op == SCC_X86_IFORM_MOV_GPRV_GPRV_8B;
}
void scc_x86_peephole_optimize(scc_mir_module_t *module) {
Assert(module != nullptr);
usize instr_size = module->instr_size;
// 遍历函数
scc_vec_foreach(module->cfg_module.funcs, i) {
if (i == 0)
continue;
scc_mir_func_t *func = &scc_vec_at(module->cfg_module.funcs, i);
// 遍历基本块
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);
Assert(bb != nullptr);
scc_mir_instr_vec_t *old_vec = SCC_MIR_BBLOCK_VALUES_PTR(bb);
if (scc_vec_size(*old_vec) == 0)
continue;
size_t old_count = scc_vec_size(*old_vec);
// 构建新向量
scc_mir_instr_vec_t new_vec;
scc_vec_init(new_vec);
for (size_t k = 0; k < old_count;) {
if (k + 1 >= old_count) {
// 剩余不足2条直接复制
void *ins_ptr =
scc_vec_sized_at_ptr(*old_vec, instr_size, k);
scc_vec_sized_push(new_vec, instr_size, ins_ptr,
instr_size);
k++;
continue;
}
scc_mir_x86_instr_t *i0 =
(scc_mir_x86_instr_t *)scc_vec_sized_at_ptr(*old_vec,
instr_size, k);
scc_mir_x86_instr_t *i1 =
(scc_mir_x86_instr_t *)scc_vec_sized_at_ptr(
*old_vec, instr_size, k + 1);
int op0 = i0->x86_instr.opcode;
int op1 = i1->x86_instr.opcode;
// 模式 A: store reg, mem 后紧跟 load mem, reg (同一 reg 和 mem)
if (is_store_to_mem(i0) && is_load_from_mem(i1) &&
i0->x86_instr.num_operands >= 2 &&
i1->x86_instr.num_operands >= 2) {
scc_x86_operand_value_t *store_dst =
&i0->x86_instr.operands[0]; // mem
scc_x86_operand_value_t *store_src =
&i0->x86_instr.operands[1]; // reg/imm
scc_x86_operand_value_t *load_dst =
&i1->x86_instr.operands[0]; // reg
scc_x86_operand_value_t *load_src =
&i1->x86_instr.operands[1]; // mem
if (store_src->kind == SCC_X86_OPR_REG &&
load_dst->kind == SCC_X86_OPR_REG &&
same_x86_operand(store_dst, load_src) &&
store_src->reg == load_dst->reg) {
// 两条指令相互抵消,都跳过
k += 2;
continue;
}
}
// 模式 B: load mem, reg 后紧跟 store reg, mem (同一 reg 和 mem)
if (is_load_from_mem(i0) && is_store_to_mem(i1) &&
i0->x86_instr.num_operands >= 2 &&
i1->x86_instr.num_operands >= 2) {
scc_x86_operand_value_t *load_dst =
&i0->x86_instr.operands[0]; // reg
scc_x86_operand_value_t *load_src =
&i0->x86_instr.operands[1]; // mem
scc_x86_operand_value_t *store_dst =
&i1->x86_instr.operands[0]; // mem
scc_x86_operand_value_t *store_src =
&i1->x86_instr.operands[1]; // reg
if (store_src->kind == SCC_X86_OPR_REG &&
load_dst->kind == SCC_X86_OPR_REG &&
same_x86_operand(load_src, store_dst) &&
load_dst->reg == store_src->reg) {
k += 2;
continue;
}
}
// 模式 C: mov r1, r2 后跟 mov r2, r1
if (is_reg_reg_move(i0) && is_reg_reg_move(i1) &&
i0->x86_instr.num_operands >= 2 &&
i1->x86_instr.num_operands >= 2) {
scc_x86_operand_value_t *dst0 = &i0->x86_instr.operands[0];
scc_x86_operand_value_t *src0 = &i0->x86_instr.operands[1];
scc_x86_operand_value_t *dst1 = &i1->x86_instr.operands[0];
scc_x86_operand_value_t *src1 = &i1->x86_instr.operands[1];
if (dst0->kind == SCC_X86_OPR_REG &&
src0->kind == SCC_X86_OPR_REG &&
dst1->kind == SCC_X86_OPR_REG &&
src1->kind == SCC_X86_OPR_REG &&
dst0->reg == src1->reg && src0->reg == dst1->reg) {
// 保留第一条,删除第二条
scc_vec_sized_push(new_vec, instr_size, i0, instr_size);
k += 2;
continue;
}
}
// 未匹配,保留当前指令
scc_vec_sized_push(new_vec, instr_size, i0, instr_size);
k++;
}
// 替换基本块的指令向量
scc_vec_free(*old_vec);
*old_vec = new_vec;
}
}
}

View File

@@ -4,71 +4,29 @@
#include <x86/scc_x86_iform.h>
#include <x86/scc_x86_reg.h>
/* ========== 指令访问回调 ========== */
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) {
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 = {scc_x86_op_slot(slot), scc_x86_op_preg(preg)}};
.x86_instr.operands = {val_slot, val_preg},
};
scc_vec_push(*vec, ins);
}
static void emit_reload(void *out, int preg, int slot) {
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 = {scc_x86_op_preg(preg), scc_x86_op_slot(slot)}};
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);
}
@@ -83,11 +41,7 @@ static void emit_copy(void *out, int dst_preg, int src_preg, int size) {
scc_vec_push(*vec, ins);
}
/* ========== 操作数读写属性 ========== */
static scc_reg_op_access_t get_operand_access(void *ctx, int opcode,
int op_idx) {
(void)ctx;
static scc_reg_op_access_t get_operand_access(int 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)
@@ -174,7 +128,111 @@ static void clean_mark_regs(void *ctx) {
reg_mask = 0;
}
/* ========== 注册全部 x86 回调 ========== */
static void x86_alloc_iter_begin(scc_reg_alloc_iter_t *iter) {
iter->op_idx = 0;
iter->op_sub_idx = 0;
}
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;
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);
*out_size = op->size;
if (op->kind == SCC_X86_OPR_REG) {
if (iter->op_sub_idx == 0 && scc_x86_op_is_vreg(op)) {
*out_vreg = scc_x86_op_get_vreg(op);
*out_access = base_access;
iter->op_sub_idx++;
return true;
}
iter->op_idx++;
iter->op_sub_idx = 0;
continue;
} else if (op->kind == SCC_X86_OPR_MEM) {
const scc_x86_mem_t *mem = &op->mem;
// 子索引 0: 基址寄存器
if (iter->op_sub_idx == 0) {
if (mem->base != SCC_X86_REG_INVALID &&
scc_x86_reg_is_vreg(mem->base)) {
*out_vreg = scc_x86_reg_get_vreg(mem->base);
*out_access =
SCC_REG_ALLOC_OP_ACCESS_READ; // 地址寄存器只读
iter->op_sub_idx++;
return true;
}
iter->op_sub_idx++;
}
// 子索引 1: 索引寄存器
if (iter->op_sub_idx == 1) {
if (mem->index != SCC_X86_REG_INVALID &&
scc_x86_reg_is_vreg(mem->index)) {
*out_vreg = scc_x86_reg_get_vreg(mem->index);
*out_access = SCC_REG_ALLOC_OP_ACCESS_READ;
iter->op_sub_idx++;
return true;
}
iter->op_sub_idx++;
}
// 没有更多子部分
iter->op_idx++;
iter->op_sub_idx = 0;
continue;
}
// 其他操作数类型立即数、slot 等)直接跳过
iter->op_idx++;
iter->op_sub_idx = 0;
}
return false;
}
static void x86_alloc_iter_replace_preg(scc_reg_alloc_iter_t *iter, int preg) {
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;
if (op_idx >= ins->x86_instr.num_operands)
return;
scc_x86_operand_value_t *op = &ins->x86_instr.operands[op_idx];
if (op->kind == SCC_X86_OPR_REG) {
// 普通寄存器操作数
scc_x86_op_set_preg(op, (scc_x86_reg_t)preg);
} else if (op->kind == SCC_X86_OPR_MEM) {
scc_x86_mem_t *mem = &op->mem;
if (sub_idx == 1) {
// 基址寄存器
mem->base = (scc_x86_reg_t)preg;
} else if (sub_idx == 2) {
// 索引寄存器
mem->index = (scc_x86_reg_t)preg;
}
}
}
static void x86_alloc_iter_replace_slot(scc_reg_alloc_iter_t *iter, int slot) {
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);
} else {
Panic("x86_alloc_iter_replace_slot: invalid op_idx");
}
}
static void x86_alloc_iter_end(scc_reg_alloc_iter_t *iter) {
(void)iter; // 无需清理
}
void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) {
ops->acquire_reg = acquire_reg;
@@ -182,19 +240,13 @@ void scc_reg_alloc_fill_arch_x86(scc_reg_alloc_op_t *ops) {
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->alloc_iter_begin = x86_alloc_iter_begin;
ops->alloc_iter_next = x86_alloc_iter_next;
ops->alloc_iter_replace_preg = x86_alloc_iter_replace_preg;
ops->alloc_iter_replace_slot = x86_alloc_iter_replace_slot;
ops->alloc_iter_end = x86_alloc_iter_end;
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;

View File

@@ -6,8 +6,11 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx,
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);
if (instr->opcode < 0) {
if (instr->opcode != SCC_MIR_PSEUDO_ALLOCA) {
scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size);
}
return;
}
@@ -17,69 +20,69 @@ static void alloc_instr(scc_reg_alloc_ctx_t *ctx,
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, opcode, &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);
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;
// 初始化迭代器
scc_reg_alloc_iter_t iter;
iter.instr = instr;
ops->alloc_iter_begin(&iter);
int vreg = ops->op_get_vreg(instr, op_i);
int vreg;
int size;
scc_reg_op_access_t access;
while (ops->alloc_iter_next(&iter, &vreg, &size, &access)) {
int id = 0;
int mapping = scc_mir_vreg_lookup(ctx->func, vreg, &id);
int preg = id, slot = id;
if (mapping == 1) {
// 已预着色
ops->mark_reg_used(ctx, preg);
ops->op_set_preg(instr, op_i, preg);
ops->alloc_iter_replace_preg(&iter, preg);
continue;
}
if (mapping == 0)
slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8);
slot = scc_mir_vreg_map2slot(ctx->func, vreg, size, 8);
preg = ops->acquire_reg(ctx);
scc_vec_push(allocated, 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)
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);
if (access == SCC_REG_ALLOC_OP_ACCESS_READ ||
access == SCC_REG_ALLOC_OP_ACCESS_READWRITE)
ops->emit_reload(&before, preg, slot, size);
if (access == SCC_REG_ALLOC_OP_ACCESS_WRITE ||
access == SCC_REG_ALLOC_OP_ACCESS_READWRITE)
ops->emit_spill(&after, preg, slot, size);
ops->op_set_preg(instr, op_i, preg);
ops->alloc_iter_replace_preg(&iter, preg);
}
ops->alloc_iter_end(&iter);
// 合并 before / instr / after
for (size_t i = 0; i < scc_vec_size(before); i++) {
void *p = scc_vec_sized_at_ptr(before, instr_size, i);
scc_vec_sized_push(*instr_vec, instr_size, p, instr_size);
}
scc_vec_sized_push(*instr_vec, instr_size, instr, instr_size);
for (size_t i = 0; i < scc_vec_size(after); i++) {
void *p = scc_vec_sized_at_ptr(after, instr_size, i);
scc_vec_sized_push(*instr_vec, instr_size, p, instr_size);
}
// 合并指令流
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);
ops->release_reg(ctx, *p);
for (const int *p = implicit_uses; *p != -1; p++)
ops->release_reg(ctx, *p);
scc_vec_free(before);
scc_vec_free(after);
scc_vec_foreach(allocated, l)
ops->release_reg(ctx, scc_vec_at(allocated, l));
for (size_t i = 0; i < scc_vec_size(allocated); i++)
ops->release_reg(ctx, scc_vec_at(allocated, i));
scc_vec_free(allocated);
}
@@ -99,7 +102,6 @@ void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module) {
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);
@@ -114,4 +116,4 @@ void scc_reg_alloc(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module) {
*old_instrs = new_instrs;
}
}
}
}

View File

@@ -1,8 +1,10 @@
#include <arch/scc_x86_mir.h>
#include <scc_mir_dump.h>
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) {
void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func,
const scc_mir_x86_instr_t *instr);
void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func,
const scc_mir_bblock_t *bb) {
Assert(ctx != nullptr && bb != nullptr);
scc_tree_dump_t *td = ctx->dump_ctx;
@@ -27,7 +29,7 @@ void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) {
break;
}
} else {
scc_x86_instr_dump(td, (void *)instr);
scc_x86_instr_dump(td, func, (void *)instr);
}
}
}
@@ -44,7 +46,7 @@ void scc_mir_dump_func(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func) {
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
const scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&ctx->mir_module->cfg_module, id);
scc_mir_dump_bblock(ctx, bb);
scc_mir_dump_bblock(ctx, func, bb);
}
}

View File

@@ -65,6 +65,9 @@ void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) {
return;
}
void scc_x86_peephole_optimize(scc_mir_module_t * module);
// scc_x86_peephole_optimize(mir_module);
scc_frame_layout_t frame_layout_ctx = {0};
scc_win_pc_x64_frame_alloc_init(&frame_layout_ctx);
scc_frame_layout(&frame_layout_ctx, mir_module);

View File

@@ -155,7 +155,7 @@ static void lower_call(void *userdata, const scc_lir_instr_t *instr) {
add_instr_1(isel,
op.kind == SCC_X86_OPR_REG ? SCC_X86_IFORM_PUSH_GPRV_50
: SCC_X86_IFORM_PUSH_IMMZ,
op);
op, 8);
break;
}
}