From f387aecc03a0e218001f0b00d5125a5d4f8d9583 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Fri, 1 Aug 2025 02:47:40 +0800 Subject: [PATCH] =?UTF-8?q?[backend-IRC]=E8=BF=9B=E4=B8=80=E6=AD=A5?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E5=AF=84=E5=AD=98=E5=99=A8=E5=88=86=E9=85=8D?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RISCv64/Handler/CalleeSavedHandler.cpp | 98 ++----- .../Handler/PrologueEpilogueInsertion.cpp | 277 ++++++++++++------ src/backend/RISCv64/RISCv64Backend.cpp | 41 ++- src/backend/RISCv64/RISCv64LLIR.cpp | 118 +++++++- src/backend/RISCv64/RISCv64RegAlloc.cpp | 2 +- src/include/backend/RISCv64/RISCv64LLIR.h | 3 +- 6 files changed, 360 insertions(+), 179 deletions(-) diff --git a/src/backend/RISCv64/Handler/CalleeSavedHandler.cpp b/src/backend/RISCv64/Handler/CalleeSavedHandler.cpp index b4cbc83..4ab73ea 100644 --- a/src/backend/RISCv64/Handler/CalleeSavedHandler.cpp +++ b/src/backend/RISCv64/Handler/CalleeSavedHandler.cpp @@ -8,10 +8,6 @@ namespace sysy { char CalleeSavedHandler::ID = 0; -static bool is_fp_reg(PhysicalReg reg) { - return reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31; -} - bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) { // This pass works on MachineFunction level, not IR level return false; @@ -23,81 +19,33 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) { if (used_callee_saved.empty()) { frame_info.callee_saved_size = 0; + frame_info.callee_saved_regs_to_store.clear(); return; } - // 1. 计算大小并排序,以便确定地生成代码 - frame_info.callee_saved_size = used_callee_saved.size() * 8; // 每个寄存器占8字节 - std::vector sorted_regs(used_callee_saved.begin(), used_callee_saved.end()); - std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){ return static_cast(a) < static_cast(b); }); - frame_info.callee_saved_regs_to_store = sorted_regs; // 保存排序后的列表 - - // 2. 在函数序言中插入保存指令 - MachineBasicBlock* entry_block = mfunc->getBlocks().front().get(); - auto& entry_instrs = entry_block->getInstructions(); - auto insert_pos = entry_instrs.begin(); - // 确保插入在任何栈分配指令之后,但在其他代码之前。 - // PrologueEpilogueInsertionPass 会处理最终顺序,这里我们先插入。 - - std::vector> save_instrs; - int current_offset = -16; // 栈布局: [ra, s0] 在最顶层,然后是callee-saved - - for (PhysicalReg reg : sorted_regs) { - // s0/fp 已经在序言中由 PrologueEpilogueInsertionPass 特殊处理,这里跳过 - if (reg == PhysicalReg::S0) continue; - - current_offset -= 8; - RVOpcodes save_op = is_fp_reg(reg) ? RVOpcodes::FSD : RVOpcodes::SD; - - auto save_instr = std::make_unique(save_op); - save_instr->addOperand(std::make_unique(reg)); - save_instr->addOperand(std::make_unique( - std::make_unique(PhysicalReg::SP), // 基址为 SP - std::make_unique(0) // 偏移量将在PEI中修正 - )); - save_instrs.push_back(std::move(save_instr)); + // 1. 计算被调用者保存寄存器所需的总空间大小 + // s0 总是由 PEI Pass 单独处理,这里不计入大小,但要确保它在列表中 + int size = 0; + std::set regs_to_save = used_callee_saved; + if (regs_to_save.count(PhysicalReg::S0)) { + regs_to_save.erase(PhysicalReg::S0); } + size = regs_to_save.size() * 8; // 每个寄存器占8字节 (64-bit) + frame_info.callee_saved_size = size; - if (!save_instrs.empty()) { - // 在序言的开头插入保存指令(PEI会后续调整它们的偏移) - entry_instrs.insert(insert_pos, - std::make_move_iterator(save_instrs.begin()), - std::make_move_iterator(save_instrs.end())); - } + // 2. 创建一个有序的、需要保存的寄存器列表,以便后续 Pass 确定地生成代码 + // s0 不应包含在此列表中,因为它由 PEI Pass 特殊处理 + std::vector sorted_regs(regs_to_save.begin(), regs_to_save.end()); + std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){ + return static_cast(a) < static_cast(b); + }); + frame_info.callee_saved_regs_to_store = sorted_regs; - // 3. 在函数结尾(ret之前)插入恢复指令 - for (auto& mbb : mfunc->getBlocks()) { - for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) { - if ((*it)->getOpcode() == RVOpcodes::RET) { - std::vector> restore_instrs; - current_offset = -16; - - // 以相反的顺序恢复寄存器 - for (auto reg_it = sorted_regs.rbegin(); reg_it != sorted_regs.rend(); ++reg_it) { - PhysicalReg reg = *reg_it; - if (reg == PhysicalReg::S0) continue; - - current_offset -= 8; - RVOpcodes restore_op = is_fp_reg(reg) ? RVOpcodes::FLD : RVOpcodes::LD; - - auto restore_instr = std::make_unique(restore_op); - restore_instr->addOperand(std::make_unique(reg)); - restore_instr->addOperand(std::make_unique( - std::make_unique(PhysicalReg::SP), - std::make_unique(0) // 偏移量同样由PEI修正 - )); - restore_instrs.push_back(std::move(restore_instr)); - } - - if (!restore_instrs.empty()) { - mbb->getInstructions().insert(it, - std::make_move_iterator(restore_instrs.begin()), - std::make_move_iterator(restore_instrs.end())); - } - goto next_block_label; - } - } - next_block_label:; - } + // 3. [关键修正] 更新栈帧总大小。 + // 这是初步计算,PEI Pass 会进行最终的对齐。 + frame_info.total_size = frame_info.locals_size + + frame_info.spill_size + + frame_info.callee_saved_size; } -} // namespace sysy \ No newline at end of file + +} // namespace sysy diff --git a/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp b/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp index 05532b7..86e3b30 100644 --- a/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp +++ b/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp @@ -1,6 +1,8 @@ #include "PrologueEpilogueInsertion.h" #include "RISCv64ISel.h" #include +#include +#include namespace sysy { @@ -8,7 +10,7 @@ char PrologueEpilogueInsertionPass::ID = 0; void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) { StackFrameInfo& frame_info = mfunc->getFrameInfo(); - + // 1. 删除 KEEPALIVE 伪指令 for (auto& mbb : mfunc->getBlocks()) { auto& instrs = mbb->getInstructions(); @@ -21,115 +23,200 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) instrs.end() ); } - - // 2. 计算最终的栈帧总大小 - // 总大小 = [ra, s0] + [被调用者保存寄存器] + [局部变量] + [溢出槽] + [调用其他函数的参数区] - // 假设调用参数区大小为0,因为它是在call指令周围动态分配和释放的 + + // 2. 计算最终的、对齐后的栈帧总大小 int total_stack_size = 16 + frame_info.callee_saved_size + frame_info.locals_size + frame_info.spill_size; - int aligned_stack_size = (total_stack_size + 15) & ~15; // 16字节对齐 + int aligned_stack_size = (total_stack_size + 15) & ~15; frame_info.total_size = aligned_stack_size; - // 只有在需要分配栈空间时才生成序言/尾声 - if (aligned_stack_size > 0) { - // --- 3. 插入序言 --- - MachineBasicBlock* entry_block = mfunc->getBlocks().front().get(); - auto& entry_instrs = entry_block->getInstructions(); - std::vector> prologue_instrs; + if (aligned_stack_size == 0) { + return; + } + + // --- 关键修正逻辑: 修正所有局部变量(即alloca)的偏移量 --- + // 这是最关键的一步,它解决了栈帧区域重叠的问题。 + // 在 EliminateFrameIndicesPass 运行时,它不知道 CalleeSavedHandler 后来会识别出 s1, s2 + // 并为其分配栈空间。因此,EliminateFrameIndicesPass 计算的偏移量是错误的。 + // 在这里,我们将偏移量向低地址方向整体移动,为 callee-saved 寄存器和溢出槽腾出空间。 + int callee_saved_and_spill_size = frame_info.callee_saved_size + frame_info.spill_size; + if (callee_saved_and_spill_size > 0) { + // 遍历所有局部变量的偏移量 Map,并进行修正 + for (auto& pair : mfunc->getFrameInfo().alloca_offsets) { + int old_offset = pair.second; // 初始偏移量(例如 -24) + int new_offset = old_offset - callee_saved_and_spill_size; + pair.second = new_offset; // 更新为修正后的偏移量 + } - // a. addi sp, sp, -aligned_stack_size - auto alloc_stack = std::make_unique(RVOpcodes::ADDI); - alloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); - alloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); - alloc_stack->addOperand(std::make_unique(-aligned_stack_size)); - prologue_instrs.push_back(std::move(alloc_stack)); - - // b. sd ra, (aligned_stack_size - 8)(sp) - auto save_ra = std::make_unique(RVOpcodes::SD); - save_ra->addOperand(std::make_unique(PhysicalReg::RA)); - save_ra->addOperand(std::make_unique( - std::make_unique(PhysicalReg::SP), - std::make_unique(aligned_stack_size - 8) - )); - prologue_instrs.push_back(std::move(save_ra)); - - // c. sd s0, (aligned_stack_size - 16)(sp) - auto save_fp = std::make_unique(RVOpcodes::SD); - save_fp->addOperand(std::make_unique(PhysicalReg::S0)); - save_fp->addOperand(std::make_unique( - std::make_unique(PhysicalReg::SP), - std::make_unique(aligned_stack_size - 16) - )); - prologue_instrs.push_back(std::move(save_fp)); - - // d. addi s0, sp, aligned_stack_size - auto set_fp = std::make_unique(RVOpcodes::ADDI); - set_fp->addOperand(std::make_unique(PhysicalReg::S0)); - set_fp->addOperand(std::make_unique(PhysicalReg::SP)); - set_fp->addOperand(std::make_unique(aligned_stack_size)); - prologue_instrs.push_back(std::move(set_fp)); - - // 将序言指令插入到函数入口 - entry_instrs.insert(entry_instrs.begin(), - std::make_move_iterator(prologue_instrs.begin()), - std::make_move_iterator(prologue_instrs.end())); - - // --- 4. 插入尾声 --- + // 重新遍历函数中的所有指令,用修正后的偏移量替换旧的立即数 for (auto& mbb : mfunc->getBlocks()) { - for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) { - if ((*it)->getOpcode() == RVOpcodes::RET) { - std::vector> epilogue_instrs; + for (auto& instr : mbb->getInstructions()) { + // 我们只修正那些使用立即数作为偏移量的内存访问指令 + if (instr->getOpcode() == RVOpcodes::ADDI) { + // ADDI 指令可能有 `addi rd, s0, offset` 的形式 + // 操作数是 [rd, s0, offset],我们需要检查第2个操作数(s0)并修改第3个(offset) + if (instr->getOperands().size() > 2) { + if (auto reg_op = dynamic_cast(instr->getOperands()[1].get())) { + if (reg_op->getPReg() == PhysicalReg::S0) { + if (auto imm_op = dynamic_cast(instr->getOperands()[2].get())) { + // ImmOperand 是不可变的, 所以我们创建一个新的来替换它 + int64_t old_imm = imm_op->getValue(); + instr->getOperands()[2] = std::make_unique(old_imm - callee_saved_and_spill_size); + } + } + } + } + } else if (instr->getOpcode() == RVOpcodes::LD || instr->getOpcode() == RVOpcodes::SD || + instr->getOpcode() == RVOpcodes::FLW || instr->getOpcode() == RVOpcodes::FSW || + instr->getOpcode() == RVOpcodes::FLD || instr->getOpcode() == RVOpcodes::FSD) { + // Load/Store 指令的操作数是 [rd, MemOperand] + // 我们需要检查 MemOperand 的基址寄存器是否为 s0 + if (instr->getOperands().size() > 1) { + if (auto mem_op = dynamic_cast(instr->getOperands()[1].get())) { + if (mem_op->getBase() && mem_op->getBase()->getPReg() == PhysicalReg::S0) { + // MemOperand 和 ImmOperand 都是不可变的, 我们必须重新构建整个 MemOperand + RegOperand* base_reg_op = mem_op->getBase(); + ImmOperand* offset_op = mem_op->getOffset(); - // a. ld ra - auto restore_ra = std::make_unique(RVOpcodes::LD); - restore_ra->addOperand(std::make_unique(PhysicalReg::RA)); - restore_ra->addOperand(std::make_unique( - std::make_unique(PhysicalReg::SP), - std::make_unique(aligned_stack_size - 8) - )); - epilogue_instrs.push_back(std::move(restore_ra)); + if (base_reg_op && offset_op) { + int64_t old_offset = offset_op->getValue(); + int64_t new_offset = old_offset - callee_saved_and_spill_size; - // b. ld s0 - auto restore_fp = std::make_unique(RVOpcodes::LD); - restore_fp->addOperand(std::make_unique(PhysicalReg::S0)); - restore_fp->addOperand(std::make_unique( - std::make_unique(PhysicalReg::SP), - std::make_unique(aligned_stack_size - 16) - )); - epilogue_instrs.push_back(std::move(restore_fp)); - - // c. addi sp, sp, aligned_stack_size - auto dealloc_stack = std::make_unique(RVOpcodes::ADDI); - dealloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); - dealloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); - dealloc_stack->addOperand(std::make_unique(aligned_stack_size)); - epilogue_instrs.push_back(std::move(dealloc_stack)); - - mbb->getInstructions().insert(it, - std::make_move_iterator(epilogue_instrs.begin()), - std::make_move_iterator(epilogue_instrs.end())); - it++; // 跳过刚插入的指令和原有的RET - goto next_block; + // 重新创建基址寄存器操作数 (必须处理虚拟/物理寄存器) + std::unique_ptr new_base; + if (base_reg_op->isVirtual()) { + new_base = std::make_unique(base_reg_op->getVRegNum()); + } else { + new_base = std::make_unique(base_reg_op->getPReg()); + } + + // 创建新的偏移立即数操作数 + auto new_offset_imm = std::make_unique(new_offset); + + // 用新创建的 MemOperand 替换旧的 + instr->getOperands()[1] = std::make_unique(std::move(new_base), std::move(new_offset_imm)); + } + } + } + } } } - next_block:; } } - // --- 5. [新增] 修正所有基于S0的内存访问偏移量 --- - // CalleeSaved, Alloca, Spill 的偏移量都是相对于S0的负向偏移 + // --- 3. 插入完整的序言 --- + MachineBasicBlock* entry_block = mfunc->getBlocks().front().get(); + auto& entry_instrs = entry_block->getInstructions(); + std::vector> prologue_instrs; + + // a. addi sp, sp, -aligned_stack_size + auto alloc_stack = std::make_unique(RVOpcodes::ADDI); + alloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); + alloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); + alloc_stack->addOperand(std::make_unique(-aligned_stack_size)); + prologue_instrs.push_back(std::move(alloc_stack)); + + // b. sd ra, (aligned_stack_size - 8)(sp) + auto save_ra = std::make_unique(RVOpcodes::SD); + save_ra->addOperand(std::make_unique(PhysicalReg::RA)); + save_ra->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique(aligned_stack_size - 8) + )); + prologue_instrs.push_back(std::move(save_ra)); + + // c. sd s0, (aligned_stack_size - 16)(sp) + auto save_fp = std::make_unique(RVOpcodes::SD); + save_fp->addOperand(std::make_unique(PhysicalReg::S0)); + save_fp->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique(aligned_stack_size - 16) + )); + prologue_instrs.push_back(std::move(save_fp)); + + // d. 保存所有其他的被调用者保存寄存器,并记录它们的偏移量 + std::map callee_saved_offsets; + int current_offset = aligned_stack_size - 16; + for (PhysicalReg reg : frame_info.callee_saved_regs_to_store) { + current_offset -= 8; + callee_saved_offsets[reg] = current_offset; // 记录偏移量 + RVOpcodes save_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FSD : RVOpcodes::SD; + + auto save_reg = std::make_unique(save_op); + save_reg->addOperand(std::make_unique(reg)); + save_reg->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique(current_offset) + )); + prologue_instrs.push_back(std::move(save_reg)); + } + + // e. addi s0, sp, aligned_stack_size + auto set_fp = std::make_unique(RVOpcodes::ADDI); + set_fp->addOperand(std::make_unique(PhysicalReg::S0)); + set_fp->addOperand(std::make_unique(PhysicalReg::SP)); + set_fp->addOperand(std::make_unique(aligned_stack_size)); + prologue_instrs.push_back(std::move(set_fp)); + + entry_instrs.insert(entry_instrs.begin(), + std::make_move_iterator(prologue_instrs.begin()), + std::make_move_iterator(prologue_instrs.end())); + + // --- 4. 插入完整的尾声 --- for (auto& mbb : mfunc->getBlocks()) { - for (auto& instr : mbb->getInstructions()) { - if (instr->getOperands().empty() || instr->getOperands().back()->getKind() != MachineOperand::KIND_MEM) { - continue; + for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) { + if ((*it)->getOpcode() == RVOpcodes::RET) { + std::vector> epilogue_instrs; + + // a. [关键修正] 恢复所有其他的被调用者保存寄存器 (以相反顺序) + const auto& regs_to_restore = frame_info.callee_saved_regs_to_store; + for (auto reg_it = regs_to_restore.rbegin(); reg_it != regs_to_restore.rend(); ++reg_it) { + PhysicalReg reg = *reg_it; + int offset = callee_saved_offsets.at(reg); // 使用之前记录的正确偏移量 + RVOpcodes restore_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FLD : RVOpcodes::LD; + + auto restore_reg = std::make_unique(restore_op); + restore_reg->addOperand(std::make_unique(reg)); + restore_reg->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique(offset) + )); + epilogue_instrs.push_back(std::move(restore_reg)); + } + + // b. ld ra + auto restore_ra = std::make_unique(RVOpcodes::LD); + restore_ra->addOperand(std::make_unique(PhysicalReg::RA)); + restore_ra->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique(aligned_stack_size - 8) + )); + epilogue_instrs.push_back(std::move(restore_ra)); + + // c. ld s0 + auto restore_fp = std::make_unique(RVOpcodes::LD); + restore_fp->addOperand(std::make_unique(PhysicalReg::S0)); + restore_fp->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique(aligned_stack_size - 16) + )); + epilogue_instrs.push_back(std::move(restore_fp)); + + // d. addi sp, sp, aligned_stack_size + auto dealloc_stack = std::make_unique(RVOpcodes::ADDI); + dealloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); + dealloc_stack->addOperand(std::make_unique(PhysicalReg::SP)); + dealloc_stack->addOperand(std::make_unique(aligned_stack_size)); + epilogue_instrs.push_back(std::move(dealloc_stack)); + + mbb->getInstructions().insert(it, + std::make_move_iterator(epilogue_instrs.begin()), + std::make_move_iterator(epilogue_instrs.end())); + + goto next_block; } - auto mem_op = static_cast(instr->getOperands().back().get()); - if (mem_op->getBase()->isVirtual() || mem_op->getBase()->getPReg() != PhysicalReg::S0) { - continue; - } - // 此时所有基于S0的偏移量都是负数,无需再次调整 - // 之前的RegAlloc/CalleeSavedHandler已经计算好了正确的相对于S0的偏移 } + next_block:; } } -} // namespace sysy \ No newline at end of file +} // namespace sysy diff --git a/src/backend/RISCv64/RISCv64Backend.cpp b/src/backend/RISCv64/RISCv64Backend.cpp index 3841eec..477fe42 100644 --- a/src/backend/RISCv64/RISCv64Backend.cpp +++ b/src/backend/RISCv64/RISCv64Backend.cpp @@ -116,41 +116,70 @@ std::string RISCv64CodeGen::function_gen(Function* func) { // 第一次调试打印输出 std::stringstream ss_after_isel; + RISCv64AsmPrinter printer_isel(mfunc.get()); + printer_isel.run(ss_after_isel, true); + // if (DEBUG) { + // std::cout << ss_after_isel.str(); + // } + // DEBUG = 1; + // DEEPDEBUG = 1; if (DEBUG) { - RISCv64AsmPrinter printer_isel(mfunc.get()); - printer_isel.run(ss_after_isel, true); - std::cout << ss_after_isel.str(); + std::cerr << "====== Intermediate Representation after Instruction Selection ======\n" + << ss_after_isel.str(); } - + // DEBUG = 0; + // DEEPDEBUG = 0; // [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移) // 这个Pass必须在寄存器分配之前运行 EliminateFrameIndicesPass efi_pass; efi_pass.runOnMachineFunction(mfunc.get()); + if (DEBUG) { + std::cerr << "====== stack info after eliminate frame indices ======\n"; + mfunc->dumpStackFrameInfo(std::cerr); + } + // // 阶段 2: 指令调度 (Instruction Scheduling) // PreRA_Scheduler scheduler; // scheduler.runOnMachineFunction(mfunc.get()); + DEBUG = 0; + DEEPDEBUG = 0; // 阶段 3: 物理寄存器分配 (Register Allocation) RISCv64RegAlloc reg_alloc(mfunc.get()); reg_alloc.run(); + // DEBUG = 1; + // DEEPDEBUG = 1; + if (DEBUG) { + std::cerr << "====== stack info after reg alloc ======\n"; + mfunc->dumpStackFrameInfo(std::cerr); + } + // 阶段 3.1: 处理被调用者保存寄存器 CalleeSavedHandler callee_handler; callee_handler.runOnMachineFunction(mfunc.get()); + if (DEBUG) { + std::cerr << "====== stack info after callee handler ======\n"; + mfunc->dumpStackFrameInfo(std::cerr); + } + // // 阶段 4: 窥孔优化 (Peephole Optimization) // PeepholeOptimizer peephole; // peephole.runOnMachineFunction(mfunc.get()); // 阶段 5: 局部指令调度 (Local Scheduling) - PostRA_Scheduler local_scheduler; - local_scheduler.runOnMachineFunction(mfunc.get()); + // PostRA_Scheduler local_scheduler; + // local_scheduler.runOnMachineFunction(mfunc.get()); // 阶段 3.2: 插入序言和尾声 PrologueEpilogueInsertionPass pei_pass; pei_pass.runOnMachineFunction(mfunc.get()); + DEBUG = 0; + DEEPDEBUG = 0; + // 阶段 3.3: 大立即数合法化 LegalizeImmediatesPass legalizer; legalizer.runOnMachineFunction(mfunc.get()); diff --git a/src/backend/RISCv64/RISCv64LLIR.cpp b/src/backend/RISCv64/RISCv64LLIR.cpp index 3816ad1..0a09d37 100644 --- a/src/backend/RISCv64/RISCv64LLIR.cpp +++ b/src/backend/RISCv64/RISCv64LLIR.cpp @@ -1,6 +1,122 @@ #include "RISCv64LLIR.h" #include +#include // 用于 std::ostream 和 std::cerr +#include // 用于 std::string namespace sysy { -} \ No newline at end of file +// 辅助函数:将 PhysicalReg 枚举转换为可读的字符串 +std::string regToString(PhysicalReg reg) { + switch (reg) { + case PhysicalReg::ZERO: return "x0"; case PhysicalReg::RA: return "ra"; + case PhysicalReg::SP: return "sp"; case PhysicalReg::GP: return "gp"; + case PhysicalReg::TP: return "tp"; case PhysicalReg::T0: return "t0"; + case PhysicalReg::T1: return "t1"; case PhysicalReg::T2: return "t2"; + case PhysicalReg::S0: return "s0"; case PhysicalReg::S1: return "s1"; + case PhysicalReg::A0: return "a0"; case PhysicalReg::A1: return "a1"; + case PhysicalReg::A2: return "a2"; case PhysicalReg::A3: return "a3"; + case PhysicalReg::A4: return "a4"; case PhysicalReg::A5: return "a5"; + case PhysicalReg::A6: return "a6"; case PhysicalReg::A7: return "a7"; + case PhysicalReg::S2: return "s2"; case PhysicalReg::S3: return "s3"; + case PhysicalReg::S4: return "s4"; case PhysicalReg::S5: return "s5"; + case PhysicalReg::S6: return "s6"; case PhysicalReg::S7: return "s7"; + case PhysicalReg::S8: return "s8"; case PhysicalReg::S9: return "s9"; + case PhysicalReg::S10: return "s10"; case PhysicalReg::S11: return "s11"; + case PhysicalReg::T3: return "t3"; case PhysicalReg::T4: return "t4"; + case PhysicalReg::T5: return "t5"; case PhysicalReg::T6: return "t6"; + case PhysicalReg::F0: return "f0"; case PhysicalReg::F1: return "f1"; + case PhysicalReg::F2: return "f2"; case PhysicalReg::F3: return "f3"; + case PhysicalReg::F4: return "f4"; case PhysicalReg::F5: return "f5"; + case PhysicalReg::F6: return "f6"; case PhysicalReg::F7: return "f7"; + case PhysicalReg::F8: return "f8"; case PhysicalReg::F9: return "f9"; + case PhysicalReg::F10: return "f10"; case PhysicalReg::F11: return "f11"; + case PhysicalReg::F12: return "f12"; case PhysicalReg::F13: return "f13"; + case PhysicalReg::F14: return "f14"; case PhysicalReg::F15: return "f15"; + case PhysicalReg::F16: return "f16"; case PhysicalReg::F17: return "f17"; + case PhysicalReg::F18: return "f18"; case PhysicalReg::F19: return "f19"; + case PhysicalReg::F20: return "f20"; case PhysicalReg::F21: return "f21"; + case PhysicalReg::F22: return "f22"; case PhysicalReg::F23: return "f23"; + case PhysicalReg::F24: return "f24"; case PhysicalReg::F25: return "f25"; + case PhysicalReg::F26: return "f26"; case PhysicalReg::F27: return "f27"; + case PhysicalReg::F28: return "f28"; case PhysicalReg::F29: return "f29"; + case PhysicalReg::F30: return "f30"; case PhysicalReg::F31: return "f31"; + default: return "UNKNOWN_REG"; + } +} + +// [新增] 打印栈帧信息的完整实现 +void MachineFunction::dumpStackFrameInfo(std::ostream& os) const { + const StackFrameInfo& info = frame_info; + + os << "--- Stack Frame Info for function '" << getName() << "' ---\n"; + + // 打印尺寸信息 + os << " Sizes:\n"; + os << " Total Size: " << info.total_size << " bytes\n"; + os << " Locals Size: " << info.locals_size << " bytes\n"; + os << " Spill Size: " << info.spill_size << " bytes\n"; + os << " Callee-Saved Size: " << info.callee_saved_size << " bytes\n"; + os << "\n"; + + // 打印 Alloca 变量的偏移量 + os << " Alloca Offsets (vreg -> offset from FP):\n"; + if (info.alloca_offsets.empty()) { + os << " (None)\n"; + } else { + for (const auto& pair : info.alloca_offsets) { + os << " %vreg" << pair.first << " -> " << pair.second << "\n"; + } + } + os << "\n"; + + // 打印溢出变量的偏移量 + os << " Spill Offsets (vreg -> offset from FP):\n"; + if (info.spill_offsets.empty()) { + os << " (None)\n"; + } else { + for (const auto& pair : info.spill_offsets) { + os << " %vreg" << pair.first << " -> " << pair.second << "\n"; + } + } + os << "\n"; + + // 打印使用的被调用者保存寄存器 + os << " Used Callee-Saved Registers:\n"; + if (info.used_callee_saved_regs.empty()) { + os << " (None)\n"; + } else { + os << " { "; + for (const auto& reg : info.used_callee_saved_regs) { + os << regToString(reg) << " "; + } + os << "}\n"; + } + os << "\n"; + + // 打印需要保存/恢复的被调用者保存寄存器 (有序) + os << " Callee-Saved Registers to Store/Restore:\n"; + if (info.callee_saved_regs_to_store.empty()) { + os << " (None)\n"; + } else { + os << " [ "; + for (const auto& reg : info.callee_saved_regs_to_store) { + os << regToString(reg) << " "; + } + os << "]\n"; + } + os << "\n"; + + // 打印最终的寄存器分配结果 + os << " Final Register Allocation Map (vreg -> preg):\n"; + if (info.vreg_to_preg_map.empty()) { + os << " (None)\n"; + } else { + for (const auto& pair : info.vreg_to_preg_map) { + os << " %vreg" << pair.first << " -> " << regToString(pair.second) << "\n"; + } + } + + os << "---------------------------------------------------\n"; +} + +} diff --git a/src/backend/RISCv64/RISCv64RegAlloc.cpp b/src/backend/RISCv64/RISCv64RegAlloc.cpp index 64ff4ef..234bccf 100644 --- a/src/backend/RISCv64/RISCv64RegAlloc.cpp +++ b/src/backend/RISCv64/RISCv64RegAlloc.cpp @@ -1108,7 +1108,7 @@ void RISCv64RegAlloc::combine(unsigned u, unsigned v) { moveList[u] = moveList.at(v); } enableMoves({v}); - for (unsigned t : adjacent(v)) { + for (unsigned t : adjList.at(v)) { addEdge(t, u); decrementDegree(t); } diff --git a/src/include/backend/RISCv64/RISCv64LLIR.h b/src/include/backend/RISCv64/RISCv64LLIR.h index 2c2aec0..1931617 100644 --- a/src/include/backend/RISCv64/RISCv64LLIR.h +++ b/src/include/backend/RISCv64/RISCv64LLIR.h @@ -3,6 +3,7 @@ #include "IR.h" // 确保包含了您自己的IR头文件 #include +#include #include #include #include @@ -300,7 +301,7 @@ public: StackFrameInfo& getFrameInfo() { return frame_info; } const std::vector>& getBlocks() const { return blocks; } std::vector>& getBlocks() { return blocks; } - + void dumpStackFrameInfo(std::ostream& os = std::cerr) const; void addBlock(std::unique_ptr block) { blocks.push_back(std::move(block)); }