diff --git a/src/RISCv64RegAlloc.cpp b/src/RISCv64RegAlloc.cpp index 5edcf98..4110df4 100644 --- a/src/RISCv64RegAlloc.cpp +++ b/src/RISCv64RegAlloc.cpp @@ -18,6 +18,7 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) { } void RISCv64RegAlloc::run() { + handleCallingConvention(); eliminateFrameIndices(); analyzeLiveness(); buildInterferenceGraph(); @@ -25,16 +26,67 @@ void RISCv64RegAlloc::run() { rewriteFunction(); } +/** + * @brief 处理调用约定,预先为函数参数分配物理寄存器。 + */ +void RISCv64RegAlloc::handleCallingConvention() { + Function* F = MFunc->getFunc(); + RISCv64ISel* isel = MFunc->getISel(); + + // 获取函数的Argument对象列表 + if (F) { + auto& args = F->getArguments(); + + // RISC-V RV64G调用约定:前8个整型/指针参数通过 a0-a7 传递 + int arg_idx = 0; + // 遍历 AllocaInst* 列表 + for (Argument* arg : args) { + if (arg_idx >= 8) { + break; + } + + // 1. 获取该 Argument 对象对应的虚拟寄存器 + unsigned vreg = isel->getVReg(arg); + + // 2. 根据参数索引,确定对应的物理寄存器 (a0, a1, ...) + auto preg = static_cast(static_cast(PhysicalReg::A0) + arg_idx); + + // 3. 在 color_map 中,将 vreg "预着色" 为对应的物理寄存器 + color_map[vreg] = preg; + + arg_idx++; + } + } +} + void RISCv64RegAlloc::eliminateFrameIndices() { StackFrameInfo& frame_info = MFunc->getFrameInfo(); - // 初始偏移量,为保存ra和s0留出空间。可以根据你的函数序言调整。 - // 假设序言是 addi sp, sp, -stack_size; sd ra, stack_size-8(sp); sd s0, stack_size-16(sp); - int current_offset = 16; + // 初始偏移量,为保存ra和s0留出空间。 + // 假设序言是 addi sp, sp, -stack_size; sd ra, stack_size-8(sp); sd s0, stack_size-16(sp); + int current_offset = 16; Function* F = MFunc->getFunc(); RISCv64ISel* isel = MFunc->getISel(); + + // 在处理局部变量前,首先为栈参数计算偏移量。 + if (F) { + int arg_idx = 0; + for (Argument* arg : F->getArguments()) { + // 我们只关心第8个索引及之后的参数(即第9个参数开始) + if (arg_idx >= 8) { + // 计算偏移量:第一个栈参数(idx=8)在0(s0),第二个(idx=9)在8(s0),以此类推。 + int offset = (arg_idx - 8) * 8; + unsigned vreg = isel->getVReg(arg); - // --- MODIFICATION START: 动态计算栈帧大小 --- + // 将这个vreg和它的栈偏移存入map。 + // 我们可以复用alloca_offsets,因为它们都代表“vreg到栈偏移”的映射。 + frame_info.alloca_offsets[vreg] = offset; + } + arg_idx++; + } + } + + // 处理局部变量 // 遍历AllocaInst来计算局部变量所需的总空间 for (auto& bb : F->getBasicBlocks()) { for (auto& inst : bb->getInstructions()) { @@ -49,12 +101,12 @@ void RISCv64RegAlloc::eliminateFrameIndices() { current_offset += size; unsigned alloca_vreg = isel->getVReg(alloca); + // 局部变量使用相对于s0的负向偏移 frame_info.alloca_offsets[alloca_vreg] = -current_offset; } } } frame_info.locals_size = current_offset; - // --- MODIFICATION END --- // 遍历所有机器指令,将伪指令展开为真实指令 for (auto& mbb : MFunc->getBlocks()) { @@ -325,13 +377,17 @@ void RISCv64RegAlloc::buildInterferenceGraph() { void RISCv64RegAlloc::colorGraph() { std::vector sorted_vregs; for (auto const& [vreg, neighbors] : interference_graph) { - sorted_vregs.push_back(vreg); + if (color_map.find(vreg) == color_map.end()) { + sorted_vregs.push_back(vreg); + } } + // 排序 std::sort(sorted_vregs.begin(), sorted_vregs.end(), [&](unsigned a, unsigned b) { return interference_graph[a].size() > interference_graph[b].size(); }); + // 着色 for (unsigned vreg : sorted_vregs) { std::set used_colors; for (unsigned neighbor : interference_graph.at(vreg)) { diff --git a/src/include/RISCv64RegAlloc.h b/src/include/RISCv64RegAlloc.h index 724ad1c..a571790 100644 --- a/src/include/RISCv64RegAlloc.h +++ b/src/include/RISCv64RegAlloc.h @@ -34,6 +34,9 @@ private: // 辅助函数,获取指令的Use/Def集合 void getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def); + // 辅助函数,处理调用约定 + void handleCallingConvention(); + MachineFunction* MFunc; // 活跃性分析结果