[backend]修复了多参数传递的问题
This commit is contained in:
@ -1,6 +1,8 @@
|
|||||||
#include "CalleeSavedHandler.h"
|
#include "CalleeSavedHandler.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <vector> //
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iterator> //
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
@ -77,9 +79,10 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
|||||||
std::sort(sorted_int_regs.begin(), sorted_int_regs.end());
|
std::sort(sorted_int_regs.begin(), sorted_int_regs.end());
|
||||||
std::sort(sorted_fp_regs.begin(), sorted_fp_regs.end());
|
std::sort(sorted_fp_regs.begin(), sorted_fp_regs.end());
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<MachineInstr>> save_instrs;
|
||||||
int current_offset = -16; // ra和s0已占用-8和-16,从-24开始分配
|
int current_offset = -16; // ra和s0已占用-8和-16,从-24开始分配
|
||||||
|
|
||||||
// 插入整数保存指令 (sd)
|
// 准备整数保存指令 (sd)
|
||||||
for (PhysicalReg reg : sorted_int_regs) {
|
for (PhysicalReg reg : sorted_int_regs) {
|
||||||
current_offset -= 8;
|
current_offset -= 8;
|
||||||
auto sd = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
auto sd = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
||||||
@ -88,10 +91,10 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
|||||||
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针 s0
|
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针 s0
|
||||||
std::make_unique<ImmOperand>(current_offset)
|
std::make_unique<ImmOperand>(current_offset)
|
||||||
));
|
));
|
||||||
entry_instrs.insert(insert_pos, std::move(sd));
|
save_instrs.push_back(std::move(sd));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 插入浮点保存指令 (fsd)
|
// 准备浮点保存指令 (fsd)
|
||||||
for (PhysicalReg reg : sorted_fp_regs) {
|
for (PhysicalReg reg : sorted_fp_regs) {
|
||||||
current_offset -= 8;
|
current_offset -= 8;
|
||||||
auto fsd = std::make_unique<MachineInstr>(RVOpcodes::FSD); // 使用浮点保存指令
|
auto fsd = std::make_unique<MachineInstr>(RVOpcodes::FSD); // 使用浮点保存指令
|
||||||
@ -100,16 +103,24 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
|||||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||||
std::make_unique<ImmOperand>(current_offset)
|
std::make_unique<ImmOperand>(current_offset)
|
||||||
));
|
));
|
||||||
entry_instrs.insert(insert_pos, std::move(fsd));
|
save_instrs.push_back(std::move(fsd));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 一次性插入所有保存指令
|
||||||
|
if (!save_instrs.empty()) {
|
||||||
|
entry_instrs.insert(insert_pos,
|
||||||
|
std::make_move_iterator(save_instrs.begin()),
|
||||||
|
std::make_move_iterator(save_instrs.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 在函数结尾(ret之前)插入恢复指令
|
// 4. 在函数结尾(ret之前)插入恢复指令
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
for (auto& mbb : mfunc->getBlocks()) {
|
||||||
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
||||||
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
||||||
|
std::vector<std::unique_ptr<MachineInstr>> restore_instrs;
|
||||||
current_offset = -16; // 重置偏移量用于恢复
|
current_offset = -16; // 重置偏移量用于恢复
|
||||||
|
|
||||||
// 恢复整数寄存器 (ld) - 以与保存时相同的顺序
|
// 准备恢复整数寄存器 (ld) - 以与保存时相同的顺序
|
||||||
for (PhysicalReg reg : sorted_int_regs) {
|
for (PhysicalReg reg : sorted_int_regs) {
|
||||||
current_offset -= 8;
|
current_offset -= 8;
|
||||||
auto ld = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
auto ld = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
||||||
@ -118,10 +129,10 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
|||||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||||
std::make_unique<ImmOperand>(current_offset)
|
std::make_unique<ImmOperand>(current_offset)
|
||||||
));
|
));
|
||||||
mbb->getInstructions().insert(it, std::move(ld));
|
restore_instrs.push_back(std::move(ld));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 恢复浮点寄存器 (fld)
|
// 准备恢复浮点寄存器 (fld)
|
||||||
for (PhysicalReg reg : sorted_fp_regs) {
|
for (PhysicalReg reg : sorted_fp_regs) {
|
||||||
current_offset -= 8;
|
current_offset -= 8;
|
||||||
auto fld = std::make_unique<MachineInstr>(RVOpcodes::FLD); // 使用浮点加载指令
|
auto fld = std::make_unique<MachineInstr>(RVOpcodes::FLD); // 使用浮点加载指令
|
||||||
@ -130,7 +141,14 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
|||||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||||
std::make_unique<ImmOperand>(current_offset)
|
std::make_unique<ImmOperand>(current_offset)
|
||||||
));
|
));
|
||||||
mbb->getInstructions().insert(it, std::move(fld));
|
restore_instrs.push_back(std::move(fld));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 一次性插入所有恢复指令
|
||||||
|
if (!restore_instrs.empty()) {
|
||||||
|
mbb->getInstructions().insert(it,
|
||||||
|
std::make_move_iterator(restore_instrs.begin()),
|
||||||
|
std::make_move_iterator(restore_instrs.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理完一个基本块的RET后,迭代器已失效,需跳出当前块的循环
|
// 处理完一个基本块的RET后,迭代器已失效,需跳出当前块的循环
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
#include "PrologueEpilogueInsertion.h"
|
#include "PrologueEpilogueInsertion.h"
|
||||||
|
#include "RISCv64ISel.h"
|
||||||
|
#include "RISCv64RegAlloc.h" // 需要访问RegAlloc的结果
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
@ -6,7 +8,13 @@ char PrologueEpilogueInsertionPass::ID = 0;
|
|||||||
|
|
||||||
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
|
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
|
||||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
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 中的计算逻辑
|
// 完全遵循 AsmPrinter 中的计算逻辑
|
||||||
int total_stack_size = frame_info.locals_size +
|
int total_stack_size = frame_info.locals_size +
|
||||||
frame_info.spill_size +
|
frame_info.spill_size +
|
||||||
@ -24,7 +32,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
|
|
||||||
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
|
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
|
||||||
|
|
||||||
// 严格按照 AsmPrinter 的打印顺序来创建和组织指令
|
|
||||||
// 1. addi sp, sp, -aligned_stack_size
|
// 1. addi sp, sp, -aligned_stack_size
|
||||||
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||||
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
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));
|
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
||||||
prologue_instrs.push_back(std::move(set_fp));
|
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();
|
auto insert_pos = entry_instrs.begin();
|
||||||
// [重要] 这里我们不再需要跳过LABEL,因为AsmPrinter将不再打印函数名标签
|
|
||||||
// 第一个基本块的标签就是函数入口
|
|
||||||
|
|
||||||
// 一次性将所有序言指令插入
|
// 一次性将所有序言指令插入
|
||||||
if (!prologue_instrs.empty()) {
|
if (!prologue_instrs.empty()) {
|
||||||
@ -69,14 +129,13 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
std::make_move_iterator(prologue_instrs.end()));
|
std::make_move_iterator(prologue_instrs.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 2. 插入尾声 ---
|
// --- 2. 插入尾声 (此部分逻辑保持不变) ---
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
for (auto& mbb : mfunc->getBlocks()) {
|
||||||
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
||||||
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
||||||
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
|
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
|
||||||
|
|
||||||
// 同样严格按照 AsmPrinter 的打印顺序
|
// 1. ld ra
|
||||||
// 1. ld ra, (aligned_stack_size - 8)(sp)
|
|
||||||
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
||||||
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
||||||
restore_ra->addOperand(std::make_unique<MemOperand>(
|
restore_ra->addOperand(std::make_unique<MemOperand>(
|
||||||
@ -85,7 +144,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
));
|
));
|
||||||
epilogue_instrs.push_back(std::move(restore_ra));
|
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);
|
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
||||||
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||||
restore_fp->addOperand(std::make_unique<MemOperand>(
|
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.begin()),
|
||||||
std::make_move_iterator(epilogue_instrs.end()));
|
std::make_move_iterator(epilogue_instrs.end()));
|
||||||
}
|
}
|
||||||
// 处理完一个基本块中的RET后,迭代器已失效,需跳出
|
|
||||||
goto next_block;
|
goto next_block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,10 @@ void RISCv64RegAlloc::run() {
|
|||||||
// 阶段 5: 图着色算法分配物理寄存器
|
// 阶段 5: 图着色算法分配物理寄存器
|
||||||
colorGraph();
|
colorGraph();
|
||||||
// 阶段 6: 重写函数(插入溢出/填充代码,替换虚拟寄存器为物理寄存器)
|
// 阶段 6: 重写函数(插入溢出/填充代码,替换虚拟寄存器为物理寄存器)
|
||||||
rewriteFunction();
|
rewriteFunction();
|
||||||
|
|
||||||
|
// 将最终的寄存器分配结果保存到MachineFunction的帧信息中,供后续Pass使用
|
||||||
|
MFunc->getFrameInfo().vreg_to_preg_map = this->color_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -794,7 +797,7 @@ void RISCv64RegAlloc::colorGraph() {
|
|||||||
for (unsigned vreg : sorted_vregs) {
|
for (unsigned vreg : sorted_vregs) {
|
||||||
std::set<PhysicalReg> used_colors;
|
std::set<PhysicalReg> used_colors;
|
||||||
for (unsigned neighbor_id : interference_graph.at(vreg)) {
|
for (unsigned neighbor_id : interference_graph.at(vreg)) {
|
||||||
// ... (收集邻居颜色的逻辑保持不变) ...
|
// 收集邻居颜色的逻辑保持不变
|
||||||
if (color_map.count(neighbor_id)) {
|
if (color_map.count(neighbor_id)) {
|
||||||
used_colors.insert(color_map.at(neighbor_id));
|
used_colors.insert(color_map.at(neighbor_id));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -279,6 +279,7 @@ struct StackFrameInfo {
|
|||||||
std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移>
|
std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移>
|
||||||
std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移>
|
std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移>
|
||||||
std::set<PhysicalReg> used_callee_saved_regs; // 使用的保存寄存器
|
std::set<PhysicalReg> used_callee_saved_regs; // 使用的保存寄存器
|
||||||
|
std::map<unsigned, PhysicalReg> vreg_to_preg_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 机器函数
|
// 机器函数
|
||||||
|
|||||||
Reference in New Issue
Block a user