[backend]修复了多参数传递的问题

This commit is contained in:
Lixuanwang
2025-07-30 17:58:39 +08:00
parent 877a0f5dc2
commit 1fb5cd398d
4 changed files with 99 additions and 19 deletions

View File

@@ -1,4 +1,6 @@
#include "PrologueEpilogueInsertion.h"
#include "RISCv64ISel.h"
#include "RISCv64RegAlloc.h" // 需要访问RegAlloc的结果
namespace sysy {
@@ -6,7 +8,13 @@ char PrologueEpilogueInsertionPass::ID = 0;
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
StackFrameInfo& frame_info = mfunc->getFrameInfo();
Function* F = mfunc->getFunc();
RISCv64ISel* isel = mfunc->getISel();
// [关键] 获取寄存器分配的结果 (vreg -> preg 的映射)
// RegAlloc Pass 必须已经运行过
auto& vreg_to_preg_map = frame_info.vreg_to_preg_map;
// 完全遵循 AsmPrinter 中的计算逻辑
int total_stack_size = frame_info.locals_size +
frame_info.spill_size +
@@ -24,7 +32,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
// 严格按照 AsmPrinter 的打印顺序来创建和组织指令
// 1. addi sp, sp, -aligned_stack_size
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
@@ -57,10 +64,63 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
prologue_instrs.push_back(std::move(set_fp));
// 确定插入点(在函数名标签之后)
// --- [正确逻辑] 在s0设置完毕后使用物理寄存器加载栈参数 ---
if (F && isel) {
// 定义暂存寄存器
const PhysicalReg INT_SCRATCH_REG = PhysicalReg::T5;
const PhysicalReg FP_SCRATCH_REG = PhysicalReg::F7;
int arg_idx = 0;
for (Argument* arg : F->getArguments()) {
if (arg_idx >= 8) {
unsigned vreg = isel->getVReg(arg);
// 确认RegAlloc已经为这个vreg计算了偏移量并且分配了物理寄存器
if (frame_info.alloca_offsets.count(vreg) && vreg_to_preg_map.count(vreg)) {
int offset = frame_info.alloca_offsets.at(vreg);
PhysicalReg dest_preg = vreg_to_preg_map.at(vreg);
Type* arg_type = arg->getType();
// 根据类型执行不同的加载序列
if (arg_type->isFloat()) {
// 1. flw ft7, offset(s0)
auto load_arg = std::make_unique<MachineInstr>(RVOpcodes::FLW);
load_arg->addOperand(std::make_unique<RegOperand>(FP_SCRATCH_REG));
load_arg->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
));
prologue_instrs.push_back(std::move(load_arg));
// 2. fmv.s dest_preg, ft7
auto move_arg = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
move_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
move_arg->addOperand(std::make_unique<RegOperand>(FP_SCRATCH_REG));
prologue_instrs.push_back(std::move(move_arg));
} else {
// 确定是加载32位(lw)还是64位(ld)
RVOpcodes load_op = arg_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
// 1. lw/ld t5, offset(s0)
auto load_arg = std::make_unique<MachineInstr>(load_op);
load_arg->addOperand(std::make_unique<RegOperand>(INT_SCRATCH_REG));
load_arg->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
));
prologue_instrs.push_back(std::move(load_arg));
// 2. mv dest_preg, t5
auto move_arg = std::make_unique<MachineInstr>(RVOpcodes::MV);
move_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
move_arg->addOperand(std::make_unique<RegOperand>(INT_SCRATCH_REG));
prologue_instrs.push_back(std::move(move_arg));
}
}
}
arg_idx++;
}
}
// 确定插入点
auto insert_pos = entry_instrs.begin();
// [重要] 这里我们不再需要跳过LABEL因为AsmPrinter将不再打印函数名标签
// 第一个基本块的标签就是函数入口
// 一次性将所有序言指令插入
if (!prologue_instrs.empty()) {
@@ -69,14 +129,13 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::make_move_iterator(prologue_instrs.end()));
}
// --- 2. 插入尾声 ---
// --- 2. 插入尾声 (此部分逻辑保持不变) ---
for (auto& mbb : mfunc->getBlocks()) {
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
if ((*it)->getOpcode() == RVOpcodes::RET) {
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
// 同样严格按照 AsmPrinter 的打印顺序
// 1. ld ra, (aligned_stack_size - 8)(sp)
// 1. ld ra
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
restore_ra->addOperand(std::make_unique<MemOperand>(
@@ -85,7 +144,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
));
epilogue_instrs.push_back(std::move(restore_ra));
// 2. ld s0, (aligned_stack_size - 16)(sp)
// 2. ld s0
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
restore_fp->addOperand(std::make_unique<MemOperand>(
@@ -106,7 +165,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::make_move_iterator(epilogue_instrs.begin()),
std::make_move_iterator(epilogue_instrs.end()));
}
// 处理完一个基本块中的RET后迭代器已失效需跳出
goto next_block;
}
}