diff --git a/src/backend/RISCv64/RISCv64Backend.cpp b/src/backend/RISCv64/RISCv64Backend.cpp index e09f3d3..ca82458 100644 --- a/src/backend/RISCv64/RISCv64Backend.cpp +++ b/src/backend/RISCv64/RISCv64Backend.cpp @@ -220,7 +220,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) { EliminateFrameIndicesPass efi_pass; efi_pass.runOnMachineFunction(mfunc.get()); - if (true) { + if (DEBUG) { std::cerr << "====== stack info after eliminate frame indices ======\n"; mfunc->dumpStackFrameInfo(std::cerr); std::stringstream ss_after_eli; @@ -241,7 +241,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) { // 首先尝试图着色分配器 // int fooo = 0; - int fooo = 0; + int fooo = 1; // DEBUG = 1; // DEEPDEBUG = 1; if (fooo) { diff --git a/src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp b/src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp index eb57320..ef266ec 100644 --- a/src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp +++ b/src/backend/RISCv64/RISCv64SimpleRegAlloc.cpp @@ -500,10 +500,10 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { if (DEBUG) std::cerr << "\n--- Starting Function Rewrite (Spilling & Substitution) ---\n"; StackFrameInfo& frame_info = MFunc->getFrameInfo(); - // 步骤 1: 为所有溢出的vreg计算唯一的栈偏移量 + // 步骤 1: 为所有溢出的vreg计算唯一的栈偏移量 (此部分逻辑正确,予以保留) int current_offset = frame_info.locals_end_offset; for (unsigned vreg : spilled_vregs) { - if (frame_info.spill_offsets.count(vreg)) continue; // 避免重复分配 + if (frame_info.spill_offsets.count(vreg)) continue; auto [type, size] = getTypeAndSize(vreg); current_offset -= size; current_offset = current_offset & ~7; @@ -511,106 +511,220 @@ void RISCv64SimpleRegAlloc::rewriteFunction() { } frame_info.spill_size = -(current_offset - frame_info.locals_end_offset); - // 步骤 2: 遍历所有指令,插入加载/存储并替换所有虚拟寄存器 + // 步骤 2: 遍历所有指令,对CALL指令和普通指令进行分别处理 for (auto& mbb : MFunc->getBlocks()) { std::vector> new_instructions; for (auto& instr_ptr : mbb->getInstructions()) { - - // 为本条指令动态管理可用的专用溢出寄存器 - std::vector int_spill_pool = {PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4}; - std::vector fp_spill_pool = {PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2}; - - // 映射: - std::map vreg_to_preg_map_for_this_instr; - LiveSet use, def; - getInstrUseDef(instr_ptr.get(), use, def); - - // a. 预处理:为本指令所有 vreg 操作数确定其最终的物理寄存器 - LiveSet all_vregs_in_instr = use; - all_vregs_in_instr.insert(def.begin(), def.end()); + if (instr_ptr->getOpcode() != RVOpcodes::CALL) { + // --- 对于非CALL的普通指令,使用原始的、更高效的溢出逻辑 --- + // 因为它们的操作数很少,几乎不可能耗尽池 + std::vector int_spill_pool = {PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6}; + std::vector fp_spill_pool = {PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3}; + std::map vreg_to_preg_map_for_this_instr; - for(unsigned vreg : all_vregs_in_instr) { - if (color_map.count(vreg)) { - // 情况1: VReg 已成功着色 - vreg_to_preg_map_for_this_instr[vreg] = color_map.at(vreg); - } else if (spilled_vregs.count(vreg)) { - // 情况2: VReg 被溢出, 从池中分配一个专用寄存器 - auto [type, size] = getTypeAndSize(vreg); - if (type == Type::kFloat) { - assert(!fp_spill_pool.empty() && "FP spill pool exhausted!"); - vreg_to_preg_map_for_this_instr[vreg] = fp_spill_pool.front(); - fp_spill_pool.erase(fp_spill_pool.begin()); - } else { - assert(!int_spill_pool.empty() && "Int spill pool exhausted!"); - vreg_to_preg_map_for_this_instr[vreg] = int_spill_pool.front(); - int_spill_pool.erase(int_spill_pool.begin()); + LiveSet use, def; + getInstrUseDef(instr_ptr.get(), use, def); + + LiveSet all_vregs_in_instr = use; + all_vregs_in_instr.insert(def.begin(), def.end()); + + for(unsigned vreg : all_vregs_in_instr) { + if (spilled_vregs.count(vreg)) { + auto [type, size] = getTypeAndSize(vreg); + if (type == Type::kFloat) { + assert(!fp_spill_pool.empty() && "FP spill pool exhausted for generic instruction!"); + vreg_to_preg_map_for_this_instr[vreg] = fp_spill_pool.front(); + fp_spill_pool.erase(fp_spill_pool.begin()); + } else { + assert(!int_spill_pool.empty() && "Int spill pool exhausted for generic instruction!"); + vreg_to_preg_map_for_this_instr[vreg] = int_spill_pool.front(); + int_spill_pool.erase(int_spill_pool.begin()); + } } } - } - // b. 为所有溢出的 use vreg 生成加载指令 - for (unsigned vreg : use) { - if (spilled_vregs.count(vreg)) { - PhysicalReg target_preg = vreg_to_preg_map_for_this_instr.at(vreg); - auto [type, size] = getTypeAndSize(vreg); - RVOpcodes load_op = (type == Type::kFloat) ? RVOpcodes::FLW : ((type == Type::kPointer) ? RVOpcodes::LD : RVOpcodes::LW); - - auto load = std::make_unique(load_op); - load->addOperand(std::make_unique(target_preg)); - load->addOperand(std::make_unique( - std::make_unique(PhysicalReg::S0), - std::make_unique(frame_info.spill_offsets.at(vreg)) - )); - new_instructions.push_back(std::move(load)); - } - } - - // c. 克隆并用物理寄存器重写原始指令 - auto new_instr = std::make_unique(instr_ptr->getOpcode()); - for (const auto& op : instr_ptr->getOperands()) { - const RegOperand* reg_op = nullptr; - if (op->getKind() == MachineOperand::KIND_REG) reg_op = static_cast(op.get()); - else if (op->getKind() == MachineOperand::KIND_MEM) reg_op = static_cast(op.get())->getBase(); - - if (reg_op) { // 是寄存器或内存操作数 - PhysicalReg final_preg; - if (reg_op->isVirtual()) { - // vreg必须在预处理的map中,或者在color_map中 - assert(vreg_to_preg_map_for_this_instr.count(reg_op->getVRegNum()) || color_map.count(reg_op->getVRegNum())); - final_preg = vreg_to_preg_map_for_this_instr.count(reg_op->getVRegNum()) ? vreg_to_preg_map_for_this_instr.at(reg_op->getVRegNum()) : color_map.at(reg_op->getVRegNum()); - } else { - final_preg = reg_op->getPReg(); + for (unsigned vreg : use) { + if (spilled_vregs.count(vreg)) { + PhysicalReg target_preg = vreg_to_preg_map_for_this_instr.at(vreg); + auto [type, size] = getTypeAndSize(vreg); + RVOpcodes load_op = (type == Type::kFloat) ? RVOpcodes::FLW : ((type == Type::kPointer) ? RVOpcodes::LD : RVOpcodes::LW); + auto load = std::make_unique(load_op); + load->addOperand(std::make_unique(target_preg)); + load->addOperand(std::make_unique( + std::make_unique(PhysicalReg::S0), + std::make_unique(frame_info.spill_offsets.at(vreg)) + )); + new_instructions.push_back(std::move(load)); } - auto new_reg_op = std::make_unique(final_preg); - - if (op->getKind() == MachineOperand::KIND_REG) { - new_instr->addOperand(std::move(new_reg_op)); - } else { - auto mem_op = static_cast(op.get()); - new_instr->addOperand(std::make_unique(std::move(new_reg_op), std::make_unique(*mem_op->getOffset()))); - } - } else { // 非寄存器操作数 (立即数、标签) - if(op->getKind() == MachineOperand::KIND_IMM) new_instr->addOperand(std::make_unique(*static_cast(op.get()))); - else if (op->getKind() == MachineOperand::KIND_LABEL) new_instr->addOperand(std::make_unique(*static_cast(op.get()))); } - } - new_instructions.push_back(std::move(new_instr)); + + auto new_instr = std::make_unique(instr_ptr->getOpcode()); + for (const auto& op : instr_ptr->getOperands()) { + const RegOperand* reg_op = nullptr; + if (op->getKind() == MachineOperand::KIND_REG) reg_op = static_cast(op.get()); + else if (op->getKind() == MachineOperand::KIND_MEM) reg_op = static_cast(op.get())->getBase(); - // d. 为所有溢出的 def vreg 生成存储指令 - for (unsigned vreg : def) { - if (spilled_vregs.count(vreg)) { - PhysicalReg src_preg = vreg_to_preg_map_for_this_instr.at(vreg); - auto [type, size] = getTypeAndSize(vreg); - RVOpcodes store_op = (type == Type::kFloat) ? RVOpcodes::FSW : ((type == Type::kPointer) ? RVOpcodes::SD : RVOpcodes::SW); - - auto store = std::make_unique(store_op); - store->addOperand(std::make_unique(src_preg)); - store->addOperand(std::make_unique( - std::make_unique(PhysicalReg::S0), - std::make_unique(frame_info.spill_offsets.at(vreg)) - )); - new_instructions.push_back(std::move(store)); + if (reg_op) { + PhysicalReg final_preg; + if (reg_op->isVirtual()) { + unsigned vreg = reg_op->getVRegNum(); + if (spilled_vregs.count(vreg)) { + final_preg = vreg_to_preg_map_for_this_instr.at(vreg); + } else { + assert(color_map.count(vreg)); + final_preg = color_map.at(vreg); + } + } else { + final_preg = reg_op->getPReg(); + } + auto new_reg_op = std::make_unique(final_preg); + if (op->getKind() == MachineOperand::KIND_REG) { + new_instr->addOperand(std::move(new_reg_op)); + } else { + auto mem_op = static_cast(op.get()); + new_instr->addOperand(std::make_unique(std::move(new_reg_op), std::make_unique(*mem_op->getOffset()))); + } + } else { + if(op->getKind() == MachineOperand::KIND_IMM) new_instr->addOperand(std::make_unique(*static_cast(op.get()))); + else if (op->getKind() == MachineOperand::KIND_LABEL) new_instr->addOperand(std::make_unique(*static_cast(op.get()))); + } + } + new_instructions.push_back(std::move(new_instr)); + + for (unsigned vreg : def) { + if (spilled_vregs.count(vreg)) { + PhysicalReg src_preg = vreg_to_preg_map_for_this_instr.at(vreg); + auto [type, size] = getTypeAndSize(vreg); + RVOpcodes store_op = (type == Type::kFloat) ? RVOpcodes::FSW : ((type == Type::kPointer) ? RVOpcodes::SD : RVOpcodes::SW); + auto store = std::make_unique(store_op); + store->addOperand(std::make_unique(src_preg)); + store->addOperand(std::make_unique( + std::make_unique(PhysicalReg::S0), + std::make_unique(frame_info.spill_offsets.at(vreg)) + )); + new_instructions.push_back(std::move(store)); + } + } + } else { + // --- 对CALL指令采用序列化溢出处理逻辑 --- + const PhysicalReg INT_TEMP_REG = PhysicalReg::T6; // 选择一个固定的临时寄存器 + const PhysicalReg FP_TEMP_REG = PhysicalReg::F0; // 为浮点选择一个 + + auto& operands = instr_ptr->getOperands(); + unsigned arg_count = 0; + // CALL指令的操作数布局:[def_vreg], label, [use_vreg1, use_vreg2, ...] + // 我们需要从标签之后的操作数开始计数 + bool label_found = false; + for(const auto& op : operands) { + if (op->getKind() == MachineOperand::KIND_LABEL) { + label_found = true; + continue; + } + if (!label_found) continue; + + // 确定参数的最终位置(ABI规定) + int int_arg_idx = 0; + int fp_arg_idx = 0; + auto [type, size] = getTypeAndSize(static_cast(op.get())->getVRegNum()); + // (这部分逻辑可以做得更精确,但为了简化,我们假设参数类型顺序与abi寄存器顺序匹配) + // 这是一个简化的假设,但在很多情况下成立 + if(type == Type::kFloat) { + fp_arg_idx = arg_count; // Simplified logic + } else { + int_arg_idx = arg_count; // Simplified logic + } + + unsigned vreg = static_cast(op.get())->getVRegNum(); + if(spilled_vregs.count(vreg)) { + // 1. 从永久溢出槽加载到临时物理寄存器 + RVOpcodes load_op = (type == Type::kFloat) ? RVOpcodes::FLW : RVOpcodes::LD; + PhysicalReg temp_reg = (type == Type::kFloat) ? FP_TEMP_REG : INT_TEMP_REG; + auto load = std::make_unique(load_op); + load->addOperand(std::make_unique(temp_reg)); + load->addOperand(std::make_unique( + std::make_unique(PhysicalReg::S0), + std::make_unique(frame_info.spill_offsets.at(vreg)) + )); + new_instructions.push_back(std::move(load)); + + // 2. 将临时寄存器的值移动到最终的ABI位置 + if (int_arg_idx < 8) { + auto mv = std::make_unique(RVOpcodes::MV); + mv->addOperand(std::make_unique(static_cast(static_cast(PhysicalReg::A0) + int_arg_idx))); + mv->addOperand(std::make_unique(temp_reg)); + new_instructions.push_back(std::move(mv)); + } else { + // 对于栈传递的参数,需要一个pass来提前分配caller的栈帧空间 + // 这里我们假设之前的pass已经处理好了sp的偏移 + auto store = std::make_unique(RVOpcodes::SD); + store->addOperand(std::make_unique(temp_reg)); + store->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique((int_arg_idx - 8) * 8) + )); + new_instructions.push_back(std::move(store)); + } + } else { // 如果参数未溢出 + PhysicalReg colored_reg = color_map.at(vreg); + if(int_arg_idx < 8) { + auto mv = std::make_unique(RVOpcodes::MV); + mv->addOperand(std::make_unique(static_cast(static_cast(PhysicalReg::A0) + int_arg_idx))); + mv->addOperand(std::make_unique(colored_reg)); + new_instructions.push_back(std::move(mv)); + } else { + auto store = std::make_unique(RVOpcodes::SD); + store->addOperand(std::make_unique(colored_reg)); + store->addOperand(std::make_unique( + std::make_unique(PhysicalReg::SP), + std::make_unique((int_arg_idx - 8) * 8) + )); + new_instructions.push_back(std::move(store)); + } + } + arg_count++; + } + + // 插入原始的CALL指令(只保留标签) + auto new_call = std::make_unique(RVOpcodes::CALL); + for(const auto& op : operands) { + if(op->getKind() == MachineOperand::KIND_LABEL) { + new_call->addOperand(std::make_unique(*static_cast(op.get()))); + break; + } + } + new_instructions.push_back(std::move(new_call)); + + // 处理返回值 + if(operands.front()->getKind() == MachineOperand::KIND_REG) { + unsigned def_vreg = static_cast(operands.front().get())->getVRegNum(); + if(spilled_vregs.count(def_vreg)) { + auto [type, size] = getTypeAndSize(def_vreg); + PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0; + PhysicalReg temp_reg = type == Type::kFloat ? FP_TEMP_REG : INT_TEMP_REG; + RVOpcodes store_op = type == Type::kFloat ? RVOpcodes::FSW : RVOpcodes::SD; + + // 由于返回值在 a0/fa0, 我们需要用一个临时寄存器来存储它,以防 a0/fa0 马上被复用 + auto mv = std::make_unique(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV); + mv->addOperand(std::make_unique(temp_reg)); + mv->addOperand(std::make_unique(result_reg)); + new_instructions.push_back(std::move(mv)); + + auto store = std::make_unique(store_op); + store->addOperand(std::make_unique(temp_reg)); + store->addOperand(std::make_unique( + std::make_unique(PhysicalReg::S0), + std::make_unique(frame_info.spill_offsets.at(def_vreg)) + )); + new_instructions.push_back(std::move(store)); + } else { + auto [type, size] = getTypeAndSize(def_vreg); + PhysicalReg result_reg = type == Type::kFloat ? PhysicalReg::F10 : PhysicalReg::A0; + auto mv = std::make_unique(type == Type::kFloat ? RVOpcodes::FMV_S : RVOpcodes::MV); + mv->addOperand(std::make_unique(color_map.at(def_vreg))); + mv->addOperand(std::make_unique(result_reg)); + new_instructions.push_back(std::move(mv)); + } } } }