diff --git a/libs/ir/mir/include/arch/x86_64_isel.h b/libs/ir/mir/include/arch/x86_64_isel.h index 4618fff..955b4f1 100644 --- a/libs/ir/mir/include/arch/x86_64_isel.h +++ b/libs/ir/mir/include/arch/x86_64_isel.h @@ -12,11 +12,14 @@ typedef struct scc_x86_64_isel { scc_mir_instr_vec_t instrs; - scc_lir_func_meta_t *func_meta; - + 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); } diff --git a/libs/ir/mir/include/arch/x86_64_reg_alloc.h b/libs/ir/mir/include/arch/x86_64_reg_alloc.h new file mode 100644 index 0000000..a65aaa0 --- /dev/null +++ b/libs/ir/mir/include/arch/x86_64_reg_alloc.h @@ -0,0 +1,8 @@ +#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_frame_layout.h b/libs/ir/mir/include/core_pass/scc_frame_layout.h index f00d700..59c6535 100644 --- a/libs/ir/mir/include/core_pass/scc_frame_layout.h +++ b/libs/ir/mir/include/core_pass/scc_frame_layout.h @@ -1,4 +1,12 @@ #ifndef __SCC_FRAME_LAYOUT_H__ #define __SCC_FRAME_LAYOUT_H__ +#include "../scc_mir_module.h" + +typedef struct scc_frame_layout { + scc_mir_func_t *func; +} scc_frame_layout_t; + +void scc_frame_layout(scc_frame_layout_t *ctx, scc_mir_module_t *module); + #endif /* __SCC_FRAME_LAYOUT_H__ */ diff --git a/libs/ir/mir/include/core_pass/scc_reg_alloc.h b/libs/ir/mir/include/core_pass/scc_reg_alloc.h index 2795c8e..b75f9ec 100644 --- a/libs/ir/mir/include/core_pass/scc_reg_alloc.h +++ b/libs/ir/mir/include/core_pass/scc_reg_alloc.h @@ -10,8 +10,6 @@ typedef enum { } scc_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 @@ -26,7 +24,7 @@ typedef struct scc_reg_alloc_op { // 显式标记某个寄存器已占用 / 未占用(用于隐式寄存器、固定分配等) void (*mark_reg_used)(void *ctx, int preg); - void (*mark_reg_unused)(void *ctx, int preg); + void (*clean_mark_regs)(void *ctx); // ---- 指令信息查询(只读) ---- scc_op_access_t (*get_operand_access)(void *ctx, int opcode, int op_idx); @@ -35,8 +33,8 @@ typedef struct scc_reg_alloc_op { } scc_reg_alloc_op_t; typedef struct scc_reg_alloc_ctx { - const scc_reg_alloc_op_t *ops; - scc_mir_func_meta_t *func_meta; + scc_reg_alloc_op_t ops; + scc_mir_func_t *func; scc_mir_instr_vec_t *instrs; } scc_reg_alloc_ctx_t; diff --git a/libs/ir/mir/include/scc_mir.h b/libs/ir/mir/include/scc_mir.h index cccdae7..003c80b 100644 --- a/libs/ir/mir/include/scc_mir.h +++ b/libs/ir/mir/include/scc_mir.h @@ -59,14 +59,24 @@ typedef struct scc_mir_func_meta { // 栈帧信息 (由 FrameLayout Pass 填充) int frame_size; int stack_alignment; + int vregs_count; // 寄存器分配信息 scc_mir_stack_slot_vec_t stack_slots; - scc_hashtable_t vreg2preg; // vreg -> phys reg,-1 表示溢出 - scc_hashtable_t vreg2slot; // vreg -> stack slot index + // vreg -> phys reg and stack slot index + // positive means stack slot index + // negative means physic register + scc_hashtable_t vreg2physic; } scc_mir_func_meta_t; #define SCC_MIR_FUNC_META(func) ((scc_mir_func_meta_t *)(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); + #endif /* __SCC_MIR_H__ */ diff --git a/libs/ir/mir/include/scc_mir_pass.h b/libs/ir/mir/include/scc_mir_pass.h index 811338e..e44780f 100644 --- a/libs/ir/mir/include/scc_mir_pass.h +++ b/libs/ir/mir/include/scc_mir_pass.h @@ -19,10 +19,10 @@ typedef enum { /** Pass 运行阶段 (用于自动排序) */ typedef enum { - SCC_MIR_STAGE_ANY, // 无特殊阶段要求 - SCC_MIR_STAGE_PRE_REGALLOC, // 寄存器分配前 - SCC_MIR_STAGE_REGALLOC, // 寄存器分配本身 - SCC_MIR_STAGE_POST_REGALLOC // 寄存器分配后 + SCC_MIR_STAGE_ANY, // 无特殊阶段要求 + SCC_MIR_STAGE_REGALLOC, // 寄存器分配本身 + SCC_MIR_STAGE_FRAME_LAYOUT, // 帧布局 + SCC_MIR_STAGE_PROLOGUE_EPILOGUE, // 函数头尾处理 } scc_mir_pass_stage_t; void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage); diff --git a/libs/ir/mir/include/target/scc_win64.h b/libs/ir/mir/include/target/scc_win64.h new file mode 100644 index 0000000..9525af6 --- /dev/null +++ b/libs/ir/mir/include/target/scc_win64.h @@ -0,0 +1,9 @@ +#ifndef __SCC_WIN64_H__ +#define __SCC_WIN64_H__ + +#include "../arch/x86_64_isel.h" +#include "../core_pass/scc_reg_alloc.h" +void scc_win_pc_x64_abi_lowering(scc_abi_lowering_t *abi_lowering); +void scc_reg_alloc_fill_win_x64(scc_reg_alloc_op_t *ops); + +#endif diff --git a/libs/ir/mir/src/arch/x86_64_isel.c b/libs/ir/mir/src/arch/x86_64_isel.c index cd0c8c2..0d40eea 100644 --- a/libs/ir/mir/src/arch/x86_64_isel.c +++ b/libs/ir/mir/src/arch/x86_64_isel.c @@ -22,7 +22,7 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_instr_t *instr) { scc_mir_operand_t *op = &instr->operands[i]; switch (op->kind) { case SCC_MIR_OP_VREG: - scc_tree_dump_append_fmt(td, "$%d", op->vreg); + scc_tree_dump_append_fmt(td, "%%%d", op->vreg); break; case SCC_MIR_OP_PREG: scc_tree_dump_append_fmt(td, "$%s", preg_name(op->preg)); @@ -84,7 +84,7 @@ 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 = isel->func_meta->vregs_count++}; + .vreg = scc_mir_alloc_vreg(isel->func)}; } void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_mir_operand_t dst, @@ -222,13 +222,13 @@ static void emit_spill_store(scc_x86_64_isel_t *isel, int vreg, int offset) { 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 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); @@ -414,12 +414,13 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { /* ---- 栈分配 ---- */ case SCC_LIR_ALLOCA: // emit_alloca(isel, dst, instr->metadata.alloca.size_bytes); - add_instr_2(isel, (scc_x86_iform_t)SCC_MIR_PSUEDO_ALLOCA, - scc_x86_lir_val_to_mir_op(isel, &instr->to), + 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); break; /* ---- 其他(占位) ---- */ @@ -442,17 +443,9 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { } static void sel_func(const scc_lir_module_t *lir_module, - const scc_lir_func_t *func) { - scc_x86_64_isel_t isel; - - void scc_win_pc_x64_abi_lowering(scc_abi_lowering_t * abi_lowering); - // TODO target got real abi_lowering - isel.abi_lowering = (scc_abi_lowering_t){0}; - scc_win_pc_x64_abi_lowering(&isel.abi_lowering); - - isel.func_meta = SCC_LIR_FUNC_META(func); + const scc_lir_func_t *func, scc_x86_64_isel_t *isel) { scc_vec_foreach(func->bblocks, i) { - scc_vec_init(isel.instrs); + scc_vec_init(isel->instrs); scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i); scc_cfg_bblock_t *bb = @@ -460,16 +453,18 @@ static void sel_func(const scc_lir_module_t *lir_module, scc_lir_instr_vec_t *instrs = SCC_LIR_BBLOCK_VALUES(bb); scc_vec_foreach(*instrs, i) { const scc_lir_instr_t *ins = &scc_vec_at(*instrs, i); - sel_mir(&isel, ins); + sel_mir(isel, ins); } - bb->values = *(scc_cfg_value_vec_t *)&isel.instrs; - scc_vec_init(isel.instrs); + bb->values = *(scc_cfg_value_vec_t *)&isel->instrs; + scc_vec_init(isel->instrs); } } void scc_isel_x86_64(scc_mir_module_t *mir_module, - const scc_lir_module_t *lir_module) { + const scc_lir_module_t *lir_module, + scc_x86_64_isel_t *isel) { + scc_vec_foreach(lir_module->cfg_module.funcs, i) { if (i == 0) continue; @@ -479,8 +474,12 @@ 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); - scc_vec_push(mir_module->func_metas, func_meta); - sel_func(lir_module, func); + // FIXME + func_meta->vregs_count = SCC_LIR_FUNC_META(func)->vregs_count; func->meta = func_meta; + + isel->func = func; + scc_vec_push(mir_module->func_metas, func_meta); + sel_func(lir_module, func, isel); } } diff --git a/libs/ir/mir/src/arch/x86_64_reg_alloc.c b/libs/ir/mir/src/arch/x86_64_reg_alloc.c index 72cf737..fbe24dd 100644 --- a/libs/ir/mir/src/arch/x86_64_reg_alloc.c +++ b/libs/ir/mir/src/arch/x86_64_reg_alloc.c @@ -1,5 +1,5 @@ #include -#include +#include static void x86_emit_spill(scc_mir_instr_vec_t *ctx, int preg, int slot) { scc_mir_instr_t ins = { @@ -74,13 +74,10 @@ static void x86_get_implicit_regs(void *vctx, int opcode, const int **uses, } } -/* 组装 hooks 表 */ -scc_reg_alloc_op_t x86_reg_alloc_hooks = { - .emit_spill = x86_emit_spill, - .emit_reload = x86_emit_reload, - .emit_copy = x86_emit_copy, - .acquire_reg = x86_acquire_temp_reg, - .release_reg = x86_release_temp_reg, - .get_operand_access = x86_get_operand_access, - .get_implicit_regs = x86_get_implicit_regs, -}; \ No newline at end of file +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/frame_layout.c b/libs/ir/mir/src/reg_alloc/frame_layout.c new file mode 100644 index 0000000..b6ee21c --- /dev/null +++ b/libs/ir/mir/src/reg_alloc/frame_layout.c @@ -0,0 +1,3 @@ +#include + +void scc_frame_layout(scc_frame_layout_t *ctx, scc_mir_module_t *module) {} diff --git a/libs/ir/mir/src/reg_alloc/reg_alloc.c b/libs/ir/mir/src/reg_alloc/reg_alloc.c index 2287983..e9da1f3 100644 --- a/libs/ir/mir/src/reg_alloc/reg_alloc.c +++ b/libs/ir/mir/src/reg_alloc/reg_alloc.c @@ -2,66 +2,181 @@ #include #include -static int ensure_slot(scc_reg_alloc_ctx_t *ctx, int vreg) { - void *key = (void *)(usize)vreg; - void *val = scc_hashtable_get(&ctx->func_meta->vreg2slot, key); - if (val != NULL) - return (int)(usize)val; - int new_slot = scc_vec_size(ctx->func_meta->stack_slots) + 1; // 1-based - scc_mir_stack_slot_t s = { - .slot_id = new_slot, .size = 8, .alignment = 8, .offset = 0}; - scc_vec_push(ctx->func_meta->stack_slots, s); - scc_hashtable_set(&ctx->func_meta->vreg2slot, key, (void *)(usize)new_slot); - return new_slot; -} +// 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; - scc_mir_instr_vec_t before_instrs; - scc_vec_init(before_instrs); - scc_mir_instr_vec_t after_instrs; - scc_vec_init(after_instrs); + const scc_reg_alloc_op_t *ops = &ctx->ops; + scc_mir_instr_vec_t before, after; + scc_vec_init(before); + scc_vec_init(after); - for (int i = 0; i < instr->num_operands; i += 1) { - if (instr->operands[i].kind != SCC_MIR_OP_VREG) { + // 隐式寄存器标记 + 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); + + // 指令内 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) continue; + + int vreg = op->vreg; + + // 查询当前 vreg 的映射(可能已经被之前的分配改为 MEM 等,但我们只需要 + // slot) + scc_mir_vreg_op(ctx->func, vreg, op); + int slot; + if (op->kind == SCC_MIR_OP_VREG) { + // 还没有 slot → 分配一个 + slot = scc_mir_vreg_map2slot(ctx->func, vreg, 8, 8); + } else { + // 已经是 MEM,直接用它的 slot + Assert(op->kind == SCC_MIR_OP_MEM); + slot = op->stack_slot; } - int vreg = instr->operands[i].vreg; - scc_op_access_t op_access = - ops->get_operand_access(ctx, instr->opcode, i); - int slot = ensure_slot(ctx, vreg); - + // 在本指令内查找是否已为这个 vreg 分配了 preg int preg = -1; - // if (implicit_uses && implicit_uses[0] != -1) - // preg = implicit_uses[0]; - // else - preg = ops->acquire_reg(ctx); - - if (op_access == SCC_REG_ALLOC_OP_ACCESS_READ || - op_access == SCC_REG_ALLOC_OP_ACCESS_READWRITE) { - ops->emit_reload(&before_instrs, preg, slot); + for (int k = 0; k < local_cnt; k++) { + if (local_vreg[k] == vreg) { + preg = local_preg[k]; + break; + } } - instr->operands[i].kind = SCC_MIR_OP_PREG; - instr->operands[i].preg = preg; - if (op_access == SCC_REG_ALLOC_OP_ACCESS_WRITE || - op_access == SCC_REG_ALLOC_OP_ACCESS_READWRITE) { - ops->emit_spill(&after_instrs, preg, slot); + 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++; } - ops->release_reg(ctx, preg); + // 读写属性 + scc_op_access_t acc = ops->get_operand_access(ctx, instr->opcode, i); + + // reload: slot → preg + if (acc == SCC_REG_ALLOC_OP_ACCESS_READ || + 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) { + ops->emit_spill(&after, preg, slot); + } + + // 替换操作数 + op->kind = SCC_MIR_OP_PREG; + op->preg = preg; } - scc_vec_foreach(before_instrs, i) { - scc_vec_push(*instr_vec, scc_vec_at(before_instrs, i)); - } + // 释放本指令分配的临时寄存器 + 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); - // TODO reverse it - scc_vec_foreach(after_instrs, i) { - scc_vec_push(*instr_vec, scc_vec_at(after_instrs, i)); - } + scc_vec_foreach(after, i) scc_vec_push(*instr_vec, scc_vec_at(after, i)); + + // 隐式寄存器清理 + 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); + scc_vec_free(allocated_pregs); } /* 对一个基本块执行分配 */ @@ -77,10 +192,6 @@ static void alloc_bb(scc_reg_alloc_ctx_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_vec_push(new_instrs, ins); - continue; - } alloc_instr(ctx, &new_instrs, &ins); } @@ -91,18 +202,29 @@ static void alloc_bb(scc_reg_alloc_ctx_t *ctx, scc_mir_module_t *module, /* 对一个函数运行分配 */ 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_meta = SCC_MIR_FUNC_META(func); + 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); } - ctx->func_meta = nullptr; } /* 公开入口 */ 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); + scc_vec_foreach(module->cfg_module.funcs, i) { if (i == 0) continue; diff --git a/libs/ir/mir/src/scc_lir2mir.c b/libs/ir/mir/src/scc_lir2mir.c index ec96cce..dcbcea4 100644 --- a/libs/ir/mir/src/scc_lir2mir.c +++ b/libs/ir/mir/src/scc_lir2mir.c @@ -1,12 +1,13 @@ +#include #include - -extern void scc_isel_x86_64(scc_mir_module_t *mir_module, - const scc_lir_module_t *lir_module); +#include void scc_lir2mir(scc_mir_module_t *mir_module, const scc_lir_module_t *lir_module) { // FIXME hack cfg module mir_module->cfg_module = lir_module->cfg_module; - // TODO using target ABI choice it - scc_isel_x86_64(mir_module, lir_module); + + scc_x86_64_isel_t isel; + scc_win_pc_x64_abi_lowering(&isel.abi_lowering); + scc_isel_x86_64(mir_module, lir_module, &isel); } diff --git a/libs/ir/mir/src/scc_mir.c b/libs/ir/mir/src/scc_mir.c index f4116be..5ed64d1 100644 --- a/libs/ir/mir/src/scc_mir.c +++ b/libs/ir/mir/src/scc_mir.c @@ -1,9 +1,64 @@ -#include "scc_mir.h" +#include 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; scc_vec_init(func_meta->stack_slots); - scc_hashtable_usize_init(&func_meta->vreg2preg); - scc_hashtable_usize_init(&func_meta->vreg2slot); + + // For null stack slot + scc_vec_push(func_meta->stack_slots, (scc_mir_stack_slot_t){0}); + scc_hashtable_usize_init(&func_meta->vreg2physic); +} + +int scc_mir_alloc_vreg(scc_mir_func_t *func) { + scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(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_MEM; + 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 = + (isize)scc_hashtable_get(&meta->vreg2physic, (void *)(usize)vreg); + if (val != 0) { + Panic("vreg %d already mapped", vreg); + return; + } + scc_hashtable_set(&meta->vreg2physic, (void *)(usize)vreg, + (void *)(usize)(isize)-preg); +} + +int scc_mir_vreg_map2slot(scc_mir_func_t *func, int vreg, int size, int align) { + scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); + isize val = + (isize)scc_hashtable_get(&meta->vreg2physic, (void *)(usize)vreg); + if (val != 0) { + Panic("vreg %d already mapped", vreg); + return 0; + } + int new_slot = scc_vec_size(meta->stack_slots); + scc_mir_stack_slot_t s = { + .slot_id = new_slot, .size = size, .alignment = align, .offset = 0}; + scc_vec_push(meta->stack_slots, s); + scc_hashtable_set(&meta->vreg2physic, (void *)(usize)vreg, + (void *)(usize)new_slot); + return new_slot; } diff --git a/libs/ir/mir/src/scc_mir_dump.c b/libs/ir/mir/src/scc_mir_dump.c index f2be6ef..d0c5b0c 100644 --- a/libs/ir/mir/src/scc_mir_dump.c +++ b/libs/ir/mir/src/scc_mir_dump.c @@ -16,6 +16,8 @@ void scc_mir_dump_instr(scc_mir_dump_ctx_t *ctx, const scc_mir_instr_t *ins) { 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_MEM) { + scc_tree_dump_append_fmt(td, " [%d]", ins->operands[0].stack_slot); } else { scc_tree_dump_append(td, ""); } diff --git a/libs/ir/mir/src/scc_mir_pass.c b/libs/ir/mir/src/scc_mir_pass.c index ac4464e..809d275 100644 --- a/libs/ir/mir/src/scc_mir_pass.c +++ b/libs/ir/mir/src/scc_mir_pass.c @@ -1,11 +1,28 @@ +#include +#include + +#include #include + #include #include -extern scc_reg_alloc_op_t x86_reg_alloc_hooks; - 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_meta = nullptr, .instrs = nullptr, .ops = &x86_reg_alloc_hooks}; + .func = nullptr, .instrs = nullptr, .ops = {0}}; + scc_reg_alloc_fill_arch_x86(®_alloc_ctx.ops); + scc_reg_alloc_fill_win_x64(®_alloc_ctx.ops); + scc_reg_alloc(®_alloc_ctx, mir_module); + if (stage == SCC_MIR_STAGE_REGALLOC) { + return; + } + + if (stage == SCC_MIR_STAGE_FRAME_LAYOUT) { + return; + } + + if (stage == SCC_MIR_STAGE_PROLOGUE_EPILOGUE) { + return; + } } diff --git a/libs/ir/mir/src/target/win64_abi.c b/libs/ir/mir/src/target/win64_abi.c index c76d51d..70c3eae 100644 --- a/libs/ir/mir/src/target/win64_abi.c +++ b/libs/ir/mir/src/target/win64_abi.c @@ -4,6 +4,7 @@ #include #include #include +#include static const int WIN64_DEFAULT_ALIGN = 8; static const int WIN64_STACK_ALIGN = 16; @@ -199,6 +200,44 @@ 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_reg_alloc_fill_win_x64(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 scc_win_pc_x64_prolog_epilog(scc_prolog_epilog_t *prolog_epilog) { prolog_epilog->prolog = prologue; prolog_epilog->epilog = epilogue; diff --git a/src/main.c b/src/main.c index df71c19..26f86d2 100644 --- a/src/main.c +++ b/src/main.c @@ -281,10 +281,10 @@ sstream_drop: scc_mir_pass(&mir_module, SCC_MIR_STAGE_REGALLOC); goto mir_dump; case SCC_EMIT_STAGE_MIR_PASS_FLAME_LAYOUT: - scc_mir_pass(&mir_module, SCC_MIR_STAGE_POST_REGALLOC); + scc_mir_pass(&mir_module, SCC_MIR_STAGE_FRAME_LAYOUT); goto mir_dump; case SCC_EMIT_STAGE_MIR_PASS_PROLOG_EPILOG: - scc_mir_pass(&mir_module, SCC_MIR_STAGE_POST_REGALLOC); + scc_mir_pass(&mir_module, SCC_MIR_STAGE_PROLOGUE_EPILOGUE); goto mir_dump; break; default: