diff --git a/src/backend/RISCv64/RISCv64Backend.cpp b/src/backend/RISCv64/RISCv64Backend.cpp index 7e08102..e3deae3 100644 --- a/src/backend/RISCv64/RISCv64Backend.cpp +++ b/src/backend/RISCv64/RISCv64Backend.cpp @@ -1,10 +1,13 @@ #include "RISCv64Backend.h" #include "RISCv64ISel.h" #include "RISCv64RegAlloc.h" +#include "RISCv64LinearScan.h" // <--- 新增此行 #include "RISCv64AsmPrinter.h" #include "RISCv64Passes.h" #include - +#include // <--- 新增此行 +#include // <--- 新增此行 +#include // <--- 新增此行,用于打印超时警告 namespace sysy { // 顶层入口 @@ -193,7 +196,8 @@ std::string RISCv64CodeGen::module_gen() { } std::string RISCv64CodeGen::function_gen(Function* func) { - // === 完整的后端处理流水线 === + if (DEBUG) { + // === 完整的后端处理流水线 === // 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers) DEBUG = 0; @@ -206,9 +210,8 @@ 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) { std::cerr << "====== Intermediate Representation after Instruction Selection ======\n" << ss_after_isel.str(); @@ -232,13 +235,144 @@ std::string RISCv64CodeGen::function_gen(Function* func) { DivStrengthReduction div_strength_reduction; div_strength_reduction.runOnMachineFunction(mfunc.get()); - // 阶段 2.1: 指令调度 (Instruction Scheduling) - PreRA_Scheduler scheduler; - scheduler.runOnMachineFunction(mfunc.get()); + // // 阶段 2.1: 指令调度 (Instruction Scheduling) + // PreRA_Scheduler scheduler; + // scheduler.runOnMachineFunction(mfunc.get()); // 阶段 3: 物理寄存器分配 (Register Allocation) - RISCv64RegAlloc reg_alloc(mfunc.get()); - reg_alloc.run(); + + DEBUG = 1; + // DEEPERDEBUG = 1; + + // 阶段 3: 物理寄存器分配 (带超时回退机制) + + /* + * [临时修改] + * 为了优先测试线性扫描分配器,暂时注释掉图着色分配器及其超时逻辑。 + * 原始逻辑是:优先使用图着色,超时(20s)后回退到线性扫描。 + * 在线性扫描分配器测试稳定后,可以恢复此处的代码。 + */ + /* + // 首先尝试图着色分配器 + if (DEBUG) std::cerr << "Attempting Register Allocation with Graph Coloring...\n"; + RISCv64RegAlloc gc_alloc(mfunc.get()); + + // 异步执行图着色分配 + auto future = std::async(std::launch::async, [&gc_alloc]{ + gc_alloc.run(); + }); + + // 等待最多20秒 + auto status = future.wait_for(std::chrono::seconds(20)); + + if (status == std::future_status::timeout) { + // 超时,切换到线性扫描分配器 + std::cerr << "Warning: Graph coloring register allocation timed out for function '" + << func->getName() + << "'. Switching to Linear Scan allocator." + << std::endl; + + // 注意:由于无法安全地停止gc_alloc线程,我们只能放弃它的结果。 + // 在此项目中,我们假设超时后原mfunc状态未被严重破坏, + // 或者线性扫描会基于isel后的状态重新开始。 + // 为了安全,我们应该用一个新的mfunc或者重置mfunc状态, + // 但在这里我们简化处理,直接在同一个mfunc上运行线性扫描。 + + RISCv64LinearScan ls_alloc(mfunc.get()); + ls_alloc.run(); + + } else { + // 图着色成功完成 + if (DEBUG) std::cerr << "Graph Coloring allocation completed successfully.\n"; + // future.get()会重新抛出在线程中发生的任何异常 + future.get(); + } + */ + + // [临时修改] 直接调用线性扫描分配器进行测试 + std::cerr << "Info: Directly testing Register Allocation with Linear Scan...\n"; + RISCv64LinearScan ls_alloc(mfunc.get()); + ls_alloc.run(); + + // 阶段 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()); + + // 阶段 3.2: 插入序言和尾声 + PrologueEpilogueInsertionPass pei_pass; + pei_pass.runOnMachineFunction(mfunc.get()); + + DEBUG = 0; + DEEPDEBUG = 0; + // 阶段 3.3: 大立即数合法化 + LegalizeImmediatesPass legalizer; + legalizer.runOnMachineFunction(mfunc.get()); + + // 阶段 6: 代码发射 (Code Emission) + std::stringstream ss; + RISCv64AsmPrinter printer(mfunc.get()); + printer.run(ss); + + return ss.str(); + } else { + // === 完整的后端处理流水线 === + + // 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers) + RISCv64ISel isel; + std::unique_ptr mfunc = isel.runOnFunction(func); + + // 第一次调试打印输出 + std::stringstream ss_after_isel; + RISCv64AsmPrinter printer_isel(mfunc.get()); + printer_isel.run(ss_after_isel, true); + + if (DEBUG) { + std::cerr << "====== Intermediate Representation after Instruction Selection ======\n" + << ss_after_isel.str(); + } + + // 阶段 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); + std::stringstream ss_after_eli; + printer_isel.run(ss_after_eli, true); + std::cerr << "====== LLIR after eliminate frame indices ======\n" + << ss_after_eli.str(); + } + + // // 阶段 2: 除法强度削弱优化 (Division Strength Reduction) + // DivStrengthReduction div_strength_reduction; + // div_strength_reduction.runOnMachineFunction(mfunc.get()); + + // // 阶段 2.1: 指令调度 (Instruction Scheduling) + // PreRA_Scheduler scheduler; + // scheduler.runOnMachineFunction(mfunc.get()); + + // 阶段 3: 物理寄存器分配 (Register Allocation) + // RISCv64RegAlloc reg_alloc(mfunc.get()); + // reg_alloc.run(); + // [临时修改] 直接调用线性扫描分配器进行测试 + std::cerr << "Info: Directly testing Register Allocation with Linear Scan...\n"; + RISCv64LinearScan ls_alloc(mfunc.get()); + ls_alloc.run(); if (DEBUG) { std::cerr << "====== stack info after reg alloc ======\n"; @@ -254,9 +388,9 @@ std::string RISCv64CodeGen::function_gen(Function* func) { mfunc->dumpStackFrameInfo(std::cerr); } - // 阶段 4: 窥孔优化 (Peephole Optimization) - PeepholeOptimizer peephole; - peephole.runOnMachineFunction(mfunc.get()); + // // 阶段 4: 窥孔优化 (Peephole Optimization) + // PeepholeOptimizer peephole; + // peephole.runOnMachineFunction(mfunc.get()); // 阶段 5: 局部指令调度 (Local Scheduling) PostRA_Scheduler local_scheduler; @@ -276,7 +410,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) { printer.run(ss); return ss.str(); - + } } } // namespace sysy \ No newline at end of file