[backend-IRC]进一步构建寄存器分配逻辑
This commit is contained in:
@@ -8,10 +8,6 @@ namespace sysy {
|
|||||||
|
|
||||||
char CalleeSavedHandler::ID = 0;
|
char CalleeSavedHandler::ID = 0;
|
||||||
|
|
||||||
static bool is_fp_reg(PhysicalReg reg) {
|
|
||||||
return reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
|
bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||||
// This pass works on MachineFunction level, not IR level
|
// This pass works on MachineFunction level, not IR level
|
||||||
return false;
|
return false;
|
||||||
@@ -23,81 +19,33 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
|||||||
|
|
||||||
if (used_callee_saved.empty()) {
|
if (used_callee_saved.empty()) {
|
||||||
frame_info.callee_saved_size = 0;
|
frame_info.callee_saved_size = 0;
|
||||||
|
frame_info.callee_saved_regs_to_store.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 计算大小并排序,以便确定地生成代码
|
// 1. 计算被调用者保存寄存器所需的总空间大小
|
||||||
frame_info.callee_saved_size = used_callee_saved.size() * 8; // 每个寄存器占8字节
|
// s0 总是由 PEI Pass 单独处理,这里不计入大小,但要确保它在列表中
|
||||||
std::vector<PhysicalReg> sorted_regs(used_callee_saved.begin(), used_callee_saved.end());
|
int size = 0;
|
||||||
std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){ return static_cast<int>(a) < static_cast<int>(b); });
|
std::set<PhysicalReg> regs_to_save = used_callee_saved;
|
||||||
frame_info.callee_saved_regs_to_store = sorted_regs; // 保存排序后的列表
|
if (regs_to_save.count(PhysicalReg::S0)) {
|
||||||
|
regs_to_save.erase(PhysicalReg::S0);
|
||||||
// 2. 在函数序言中插入保存指令
|
|
||||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
|
||||||
auto& entry_instrs = entry_block->getInstructions();
|
|
||||||
auto insert_pos = entry_instrs.begin();
|
|
||||||
// 确保插入在任何栈分配指令之后,但在其他代码之前。
|
|
||||||
// PrologueEpilogueInsertionPass 会处理最终顺序,这里我们先插入。
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<MachineInstr>> save_instrs;
|
|
||||||
int current_offset = -16; // 栈布局: [ra, s0] 在最顶层,然后是callee-saved
|
|
||||||
|
|
||||||
for (PhysicalReg reg : sorted_regs) {
|
|
||||||
// s0/fp 已经在序言中由 PrologueEpilogueInsertionPass 特殊处理,这里跳过
|
|
||||||
if (reg == PhysicalReg::S0) continue;
|
|
||||||
|
|
||||||
current_offset -= 8;
|
|
||||||
RVOpcodes save_op = is_fp_reg(reg) ? RVOpcodes::FSD : RVOpcodes::SD;
|
|
||||||
|
|
||||||
auto save_instr = std::make_unique<MachineInstr>(save_op);
|
|
||||||
save_instr->addOperand(std::make_unique<RegOperand>(reg));
|
|
||||||
save_instr->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::SP), // 基址为 SP
|
|
||||||
std::make_unique<ImmOperand>(0) // 偏移量将在PEI中修正
|
|
||||||
));
|
|
||||||
save_instrs.push_back(std::move(save_instr));
|
|
||||||
}
|
}
|
||||||
|
size = regs_to_save.size() * 8; // 每个寄存器占8字节 (64-bit)
|
||||||
|
frame_info.callee_saved_size = size;
|
||||||
|
|
||||||
if (!save_instrs.empty()) {
|
// 2. 创建一个有序的、需要保存的寄存器列表,以便后续 Pass 确定地生成代码
|
||||||
// 在序言的开头插入保存指令(PEI会后续调整它们的偏移)
|
// s0 不应包含在此列表中,因为它由 PEI Pass 特殊处理
|
||||||
entry_instrs.insert(insert_pos,
|
std::vector<PhysicalReg> sorted_regs(regs_to_save.begin(), regs_to_save.end());
|
||||||
std::make_move_iterator(save_instrs.begin()),
|
std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){
|
||||||
std::make_move_iterator(save_instrs.end()));
|
return static_cast<int>(a) < static_cast<int>(b);
|
||||||
}
|
});
|
||||||
|
frame_info.callee_saved_regs_to_store = sorted_regs;
|
||||||
|
|
||||||
// 3. 在函数结尾(ret之前)插入恢复指令
|
// 3. [关键修正] 更新栈帧总大小。
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
// 这是初步计算,PEI Pass 会进行最终的对齐。
|
||||||
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
frame_info.total_size = frame_info.locals_size +
|
||||||
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
frame_info.spill_size +
|
||||||
std::vector<std::unique_ptr<MachineInstr>> restore_instrs;
|
frame_info.callee_saved_size;
|
||||||
current_offset = -16;
|
|
||||||
|
|
||||||
// 以相反的顺序恢复寄存器
|
|
||||||
for (auto reg_it = sorted_regs.rbegin(); reg_it != sorted_regs.rend(); ++reg_it) {
|
|
||||||
PhysicalReg reg = *reg_it;
|
|
||||||
if (reg == PhysicalReg::S0) continue;
|
|
||||||
|
|
||||||
current_offset -= 8;
|
|
||||||
RVOpcodes restore_op = is_fp_reg(reg) ? RVOpcodes::FLD : RVOpcodes::LD;
|
|
||||||
|
|
||||||
auto restore_instr = std::make_unique<MachineInstr>(restore_op);
|
|
||||||
restore_instr->addOperand(std::make_unique<RegOperand>(reg));
|
|
||||||
restore_instr->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::SP),
|
|
||||||
std::make_unique<ImmOperand>(0) // 偏移量同样由PEI修正
|
|
||||||
));
|
|
||||||
restore_instrs.push_back(std::move(restore_instr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!restore_instrs.empty()) {
|
|
||||||
mbb->getInstructions().insert(it,
|
|
||||||
std::make_move_iterator(restore_instrs.begin()),
|
|
||||||
std::make_move_iterator(restore_instrs.end()));
|
|
||||||
}
|
|
||||||
goto next_block_label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next_block_label:;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sysy
|
} // namespace sysy
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "PrologueEpilogueInsertion.h"
|
#include "PrologueEpilogueInsertion.h"
|
||||||
#include "RISCv64ISel.h"
|
#include "RISCv64ISel.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
@@ -22,113 +24,198 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 计算最终的栈帧总大小
|
// 2. 计算最终的、对齐后的栈帧总大小
|
||||||
// 总大小 = [ra, s0] + [被调用者保存寄存器] + [局部变量] + [溢出槽] + [调用其他函数的参数区]
|
|
||||||
// 假设调用参数区大小为0,因为它是在call指令周围动态分配和释放的
|
|
||||||
int total_stack_size = 16 + frame_info.callee_saved_size + frame_info.locals_size + frame_info.spill_size;
|
int total_stack_size = 16 + frame_info.callee_saved_size + frame_info.locals_size + frame_info.spill_size;
|
||||||
int aligned_stack_size = (total_stack_size + 15) & ~15; // 16字节对齐
|
int aligned_stack_size = (total_stack_size + 15) & ~15;
|
||||||
frame_info.total_size = aligned_stack_size;
|
frame_info.total_size = aligned_stack_size;
|
||||||
|
|
||||||
// 只有在需要分配栈空间时才生成序言/尾声
|
if (aligned_stack_size == 0) {
|
||||||
if (aligned_stack_size > 0) {
|
return;
|
||||||
// --- 3. 插入序言 ---
|
}
|
||||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
|
||||||
auto& entry_instrs = entry_block->getInstructions();
|
|
||||||
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
|
|
||||||
|
|
||||||
// a. addi sp, sp, -aligned_stack_size
|
// --- 关键修正逻辑: 修正所有局部变量(即alloca)的偏移量 ---
|
||||||
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
// 这是最关键的一步,它解决了栈帧区域重叠的问题。
|
||||||
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
// 在 EliminateFrameIndicesPass 运行时,它不知道 CalleeSavedHandler 后来会识别出 s1, s2
|
||||||
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
// 并为其分配栈空间。因此,EliminateFrameIndicesPass 计算的偏移量是错误的。
|
||||||
alloc_stack->addOperand(std::make_unique<ImmOperand>(-aligned_stack_size));
|
// 在这里,我们将偏移量向低地址方向整体移动,为 callee-saved 寄存器和溢出槽腾出空间。
|
||||||
prologue_instrs.push_back(std::move(alloc_stack));
|
int callee_saved_and_spill_size = frame_info.callee_saved_size + frame_info.spill_size;
|
||||||
|
if (callee_saved_and_spill_size > 0) {
|
||||||
|
// 遍历所有局部变量的偏移量 Map,并进行修正
|
||||||
|
for (auto& pair : mfunc->getFrameInfo().alloca_offsets) {
|
||||||
|
int old_offset = pair.second; // 初始偏移量(例如 -24)
|
||||||
|
int new_offset = old_offset - callee_saved_and_spill_size;
|
||||||
|
pair.second = new_offset; // 更新为修正后的偏移量
|
||||||
|
}
|
||||||
|
|
||||||
// b. sd ra, (aligned_stack_size - 8)(sp)
|
// 重新遍历函数中的所有指令,用修正后的偏移量替换旧的立即数
|
||||||
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
|
||||||
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
|
||||||
save_ra->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::SP),
|
|
||||||
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
|
||||||
));
|
|
||||||
prologue_instrs.push_back(std::move(save_ra));
|
|
||||||
|
|
||||||
// c. sd s0, (aligned_stack_size - 16)(sp)
|
|
||||||
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
|
||||||
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
|
||||||
save_fp->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::SP),
|
|
||||||
std::make_unique<ImmOperand>(aligned_stack_size - 16)
|
|
||||||
));
|
|
||||||
prologue_instrs.push_back(std::move(save_fp));
|
|
||||||
|
|
||||||
// d. addi s0, sp, aligned_stack_size
|
|
||||||
auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
|
||||||
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
|
||||||
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
|
||||||
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
|
||||||
prologue_instrs.push_back(std::move(set_fp));
|
|
||||||
|
|
||||||
// 将序言指令插入到函数入口
|
|
||||||
entry_instrs.insert(entry_instrs.begin(),
|
|
||||||
std::make_move_iterator(prologue_instrs.begin()),
|
|
||||||
std::make_move_iterator(prologue_instrs.end()));
|
|
||||||
|
|
||||||
// --- 4. 插入尾声 ---
|
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
for (auto& mbb : mfunc->getBlocks()) {
|
||||||
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
for (auto& instr : mbb->getInstructions()) {
|
||||||
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
// 我们只修正那些使用立即数作为偏移量的内存访问指令
|
||||||
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
|
if (instr->getOpcode() == RVOpcodes::ADDI) {
|
||||||
|
// ADDI 指令可能有 `addi rd, s0, offset` 的形式
|
||||||
|
// 操作数是 [rd, s0, offset],我们需要检查第2个操作数(s0)并修改第3个(offset)
|
||||||
|
if (instr->getOperands().size() > 2) {
|
||||||
|
if (auto reg_op = dynamic_cast<RegOperand*>(instr->getOperands()[1].get())) {
|
||||||
|
if (reg_op->getPReg() == PhysicalReg::S0) {
|
||||||
|
if (auto imm_op = dynamic_cast<ImmOperand*>(instr->getOperands()[2].get())) {
|
||||||
|
// ImmOperand 是不可变的, 所以我们创建一个新的来替换它
|
||||||
|
int64_t old_imm = imm_op->getValue();
|
||||||
|
instr->getOperands()[2] = std::make_unique<ImmOperand>(old_imm - callee_saved_and_spill_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (instr->getOpcode() == RVOpcodes::LD || instr->getOpcode() == RVOpcodes::SD ||
|
||||||
|
instr->getOpcode() == RVOpcodes::FLW || instr->getOpcode() == RVOpcodes::FSW ||
|
||||||
|
instr->getOpcode() == RVOpcodes::FLD || instr->getOpcode() == RVOpcodes::FSD) {
|
||||||
|
// Load/Store 指令的操作数是 [rd, MemOperand]
|
||||||
|
// 我们需要检查 MemOperand 的基址寄存器是否为 s0
|
||||||
|
if (instr->getOperands().size() > 1) {
|
||||||
|
if (auto mem_op = dynamic_cast<MemOperand*>(instr->getOperands()[1].get())) {
|
||||||
|
if (mem_op->getBase() && mem_op->getBase()->getPReg() == PhysicalReg::S0) {
|
||||||
|
// MemOperand 和 ImmOperand 都是不可变的, 我们必须重新构建整个 MemOperand
|
||||||
|
RegOperand* base_reg_op = mem_op->getBase();
|
||||||
|
ImmOperand* offset_op = mem_op->getOffset();
|
||||||
|
|
||||||
// a. ld ra
|
if (base_reg_op && offset_op) {
|
||||||
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
int64_t old_offset = offset_op->getValue();
|
||||||
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
int64_t new_offset = old_offset - callee_saved_and_spill_size;
|
||||||
restore_ra->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::SP),
|
|
||||||
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
|
||||||
));
|
|
||||||
epilogue_instrs.push_back(std::move(restore_ra));
|
|
||||||
|
|
||||||
// b. ld s0
|
// 重新创建基址寄存器操作数 (必须处理虚拟/物理寄存器)
|
||||||
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
std::unique_ptr<RegOperand> new_base;
|
||||||
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
if (base_reg_op->isVirtual()) {
|
||||||
restore_fp->addOperand(std::make_unique<MemOperand>(
|
new_base = std::make_unique<RegOperand>(base_reg_op->getVRegNum());
|
||||||
std::make_unique<RegOperand>(PhysicalReg::SP),
|
} else {
|
||||||
std::make_unique<ImmOperand>(aligned_stack_size - 16)
|
new_base = std::make_unique<RegOperand>(base_reg_op->getPReg());
|
||||||
));
|
}
|
||||||
epilogue_instrs.push_back(std::move(restore_fp));
|
|
||||||
|
|
||||||
// c. addi sp, sp, aligned_stack_size
|
// 创建新的偏移立即数操作数
|
||||||
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
auto new_offset_imm = std::make_unique<ImmOperand>(new_offset);
|
||||||
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
|
||||||
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
|
||||||
dealloc_stack->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
|
||||||
epilogue_instrs.push_back(std::move(dealloc_stack));
|
|
||||||
|
|
||||||
mbb->getInstructions().insert(it,
|
// 用新创建的 MemOperand 替换旧的
|
||||||
std::make_move_iterator(epilogue_instrs.begin()),
|
instr->getOperands()[1] = std::make_unique<MemOperand>(std::move(new_base), std::move(new_offset_imm));
|
||||||
std::make_move_iterator(epilogue_instrs.end()));
|
}
|
||||||
it++; // 跳过刚插入的指令和原有的RET
|
}
|
||||||
goto next_block;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next_block:;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 5. [新增] 修正所有基于S0的内存访问偏移量 ---
|
// --- 3. 插入完整的序言 ---
|
||||||
// CalleeSaved, Alloca, Spill 的偏移量都是相对于S0的负向偏移
|
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
||||||
|
auto& entry_instrs = entry_block->getInstructions();
|
||||||
|
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
|
||||||
|
|
||||||
|
// a. addi sp, sp, -aligned_stack_size
|
||||||
|
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));
|
||||||
|
alloc_stack->addOperand(std::make_unique<ImmOperand>(-aligned_stack_size));
|
||||||
|
prologue_instrs.push_back(std::move(alloc_stack));
|
||||||
|
|
||||||
|
// b. sd ra, (aligned_stack_size - 8)(sp)
|
||||||
|
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
||||||
|
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
||||||
|
save_ra->addOperand(std::make_unique<MemOperand>(
|
||||||
|
std::make_unique<RegOperand>(PhysicalReg::SP),
|
||||||
|
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
||||||
|
));
|
||||||
|
prologue_instrs.push_back(std::move(save_ra));
|
||||||
|
|
||||||
|
// c. sd s0, (aligned_stack_size - 16)(sp)
|
||||||
|
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
||||||
|
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||||
|
save_fp->addOperand(std::make_unique<MemOperand>(
|
||||||
|
std::make_unique<RegOperand>(PhysicalReg::SP),
|
||||||
|
std::make_unique<ImmOperand>(aligned_stack_size - 16)
|
||||||
|
));
|
||||||
|
prologue_instrs.push_back(std::move(save_fp));
|
||||||
|
|
||||||
|
// d. 保存所有其他的被调用者保存寄存器,并记录它们的偏移量
|
||||||
|
std::map<PhysicalReg, int> callee_saved_offsets;
|
||||||
|
int current_offset = aligned_stack_size - 16;
|
||||||
|
for (PhysicalReg reg : frame_info.callee_saved_regs_to_store) {
|
||||||
|
current_offset -= 8;
|
||||||
|
callee_saved_offsets[reg] = current_offset; // 记录偏移量
|
||||||
|
RVOpcodes save_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FSD : RVOpcodes::SD;
|
||||||
|
|
||||||
|
auto save_reg = std::make_unique<MachineInstr>(save_op);
|
||||||
|
save_reg->addOperand(std::make_unique<RegOperand>(reg));
|
||||||
|
save_reg->addOperand(std::make_unique<MemOperand>(
|
||||||
|
std::make_unique<RegOperand>(PhysicalReg::SP),
|
||||||
|
std::make_unique<ImmOperand>(current_offset)
|
||||||
|
));
|
||||||
|
prologue_instrs.push_back(std::move(save_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
// e. addi s0, sp, aligned_stack_size
|
||||||
|
auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||||
|
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||||
|
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||||
|
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
||||||
|
prologue_instrs.push_back(std::move(set_fp));
|
||||||
|
|
||||||
|
entry_instrs.insert(entry_instrs.begin(),
|
||||||
|
std::make_move_iterator(prologue_instrs.begin()),
|
||||||
|
std::make_move_iterator(prologue_instrs.end()));
|
||||||
|
|
||||||
|
// --- 4. 插入完整的尾声 ---
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
for (auto& mbb : mfunc->getBlocks()) {
|
||||||
for (auto& instr : mbb->getInstructions()) {
|
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
||||||
if (instr->getOperands().empty() || instr->getOperands().back()->getKind() != MachineOperand::KIND_MEM) {
|
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
||||||
continue;
|
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
|
||||||
|
|
||||||
|
// a. [关键修正] 恢复所有其他的被调用者保存寄存器 (以相反顺序)
|
||||||
|
const auto& regs_to_restore = frame_info.callee_saved_regs_to_store;
|
||||||
|
for (auto reg_it = regs_to_restore.rbegin(); reg_it != regs_to_restore.rend(); ++reg_it) {
|
||||||
|
PhysicalReg reg = *reg_it;
|
||||||
|
int offset = callee_saved_offsets.at(reg); // 使用之前记录的正确偏移量
|
||||||
|
RVOpcodes restore_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FLD : RVOpcodes::LD;
|
||||||
|
|
||||||
|
auto restore_reg = std::make_unique<MachineInstr>(restore_op);
|
||||||
|
restore_reg->addOperand(std::make_unique<RegOperand>(reg));
|
||||||
|
restore_reg->addOperand(std::make_unique<MemOperand>(
|
||||||
|
std::make_unique<RegOperand>(PhysicalReg::SP),
|
||||||
|
std::make_unique<ImmOperand>(offset)
|
||||||
|
));
|
||||||
|
epilogue_instrs.push_back(std::move(restore_reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
// b. 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>(
|
||||||
|
std::make_unique<RegOperand>(PhysicalReg::SP),
|
||||||
|
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
||||||
|
));
|
||||||
|
epilogue_instrs.push_back(std::move(restore_ra));
|
||||||
|
|
||||||
|
// c. 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>(
|
||||||
|
std::make_unique<RegOperand>(PhysicalReg::SP),
|
||||||
|
std::make_unique<ImmOperand>(aligned_stack_size - 16)
|
||||||
|
));
|
||||||
|
epilogue_instrs.push_back(std::move(restore_fp));
|
||||||
|
|
||||||
|
// d. addi sp, sp, aligned_stack_size
|
||||||
|
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||||
|
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||||
|
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||||
|
dealloc_stack->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
||||||
|
epilogue_instrs.push_back(std::move(dealloc_stack));
|
||||||
|
|
||||||
|
mbb->getInstructions().insert(it,
|
||||||
|
std::make_move_iterator(epilogue_instrs.begin()),
|
||||||
|
std::make_move_iterator(epilogue_instrs.end()));
|
||||||
|
|
||||||
|
goto next_block;
|
||||||
}
|
}
|
||||||
auto mem_op = static_cast<MemOperand*>(instr->getOperands().back().get());
|
|
||||||
if (mem_op->getBase()->isVirtual() || mem_op->getBase()->getPReg() != PhysicalReg::S0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// 此时所有基于S0的偏移量都是负数,无需再次调整
|
|
||||||
// 之前的RegAlloc/CalleeSavedHandler已经计算好了正确的相对于S0的偏移
|
|
||||||
}
|
}
|
||||||
|
next_block:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,41 +116,70 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
|||||||
|
|
||||||
// 第一次调试打印输出
|
// 第一次调试打印输出
|
||||||
std::stringstream ss_after_isel;
|
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) {
|
if (DEBUG) {
|
||||||
RISCv64AsmPrinter printer_isel(mfunc.get());
|
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
|
||||||
printer_isel.run(ss_after_isel, true);
|
<< ss_after_isel.str();
|
||||||
std::cout << ss_after_isel.str();
|
|
||||||
}
|
}
|
||||||
|
// DEBUG = 0;
|
||||||
|
// DEEPDEBUG = 0;
|
||||||
// [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
|
// [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
|
||||||
// 这个Pass必须在寄存器分配之前运行
|
// 这个Pass必须在寄存器分配之前运行
|
||||||
EliminateFrameIndicesPass efi_pass;
|
EliminateFrameIndicesPass efi_pass;
|
||||||
efi_pass.runOnMachineFunction(mfunc.get());
|
efi_pass.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "====== stack info after eliminate frame indices ======\n";
|
||||||
|
mfunc->dumpStackFrameInfo(std::cerr);
|
||||||
|
}
|
||||||
|
|
||||||
// // 阶段 2: 指令调度 (Instruction Scheduling)
|
// // 阶段 2: 指令调度 (Instruction Scheduling)
|
||||||
// PreRA_Scheduler scheduler;
|
// PreRA_Scheduler scheduler;
|
||||||
// scheduler.runOnMachineFunction(mfunc.get());
|
// scheduler.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
|
DEBUG = 0;
|
||||||
|
DEEPDEBUG = 0;
|
||||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
||||||
RISCv64RegAlloc reg_alloc(mfunc.get());
|
RISCv64RegAlloc reg_alloc(mfunc.get());
|
||||||
reg_alloc.run();
|
reg_alloc.run();
|
||||||
|
|
||||||
|
// DEBUG = 1;
|
||||||
|
// DEEPDEBUG = 1;
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "====== stack info after reg alloc ======\n";
|
||||||
|
mfunc->dumpStackFrameInfo(std::cerr);
|
||||||
|
}
|
||||||
|
|
||||||
// 阶段 3.1: 处理被调用者保存寄存器
|
// 阶段 3.1: 处理被调用者保存寄存器
|
||||||
CalleeSavedHandler callee_handler;
|
CalleeSavedHandler callee_handler;
|
||||||
callee_handler.runOnMachineFunction(mfunc.get());
|
callee_handler.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "====== stack info after callee handler ======\n";
|
||||||
|
mfunc->dumpStackFrameInfo(std::cerr);
|
||||||
|
}
|
||||||
|
|
||||||
// // 阶段 4: 窥孔优化 (Peephole Optimization)
|
// // 阶段 4: 窥孔优化 (Peephole Optimization)
|
||||||
// PeepholeOptimizer peephole;
|
// PeepholeOptimizer peephole;
|
||||||
// peephole.runOnMachineFunction(mfunc.get());
|
// peephole.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
// 阶段 5: 局部指令调度 (Local Scheduling)
|
// 阶段 5: 局部指令调度 (Local Scheduling)
|
||||||
PostRA_Scheduler local_scheduler;
|
// PostRA_Scheduler local_scheduler;
|
||||||
local_scheduler.runOnMachineFunction(mfunc.get());
|
// local_scheduler.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
// 阶段 3.2: 插入序言和尾声
|
// 阶段 3.2: 插入序言和尾声
|
||||||
PrologueEpilogueInsertionPass pei_pass;
|
PrologueEpilogueInsertionPass pei_pass;
|
||||||
pei_pass.runOnMachineFunction(mfunc.get());
|
pei_pass.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
|
DEBUG = 0;
|
||||||
|
DEEPDEBUG = 0;
|
||||||
|
|
||||||
// 阶段 3.3: 大立即数合法化
|
// 阶段 3.3: 大立即数合法化
|
||||||
LegalizeImmediatesPass legalizer;
|
LegalizeImmediatesPass legalizer;
|
||||||
legalizer.runOnMachineFunction(mfunc.get());
|
legalizer.runOnMachineFunction(mfunc.get());
|
||||||
|
|||||||
@@ -1,6 +1,122 @@
|
|||||||
#include "RISCv64LLIR.h"
|
#include "RISCv64LLIR.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iostream> // 用于 std::ostream 和 std::cerr
|
||||||
|
#include <string> // 用于 std::string
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
|
// 辅助函数:将 PhysicalReg 枚举转换为可读的字符串
|
||||||
|
std::string regToString(PhysicalReg reg) {
|
||||||
|
switch (reg) {
|
||||||
|
case PhysicalReg::ZERO: return "x0"; case PhysicalReg::RA: return "ra";
|
||||||
|
case PhysicalReg::SP: return "sp"; case PhysicalReg::GP: return "gp";
|
||||||
|
case PhysicalReg::TP: return "tp"; case PhysicalReg::T0: return "t0";
|
||||||
|
case PhysicalReg::T1: return "t1"; case PhysicalReg::T2: return "t2";
|
||||||
|
case PhysicalReg::S0: return "s0"; case PhysicalReg::S1: return "s1";
|
||||||
|
case PhysicalReg::A0: return "a0"; case PhysicalReg::A1: return "a1";
|
||||||
|
case PhysicalReg::A2: return "a2"; case PhysicalReg::A3: return "a3";
|
||||||
|
case PhysicalReg::A4: return "a4"; case PhysicalReg::A5: return "a5";
|
||||||
|
case PhysicalReg::A6: return "a6"; case PhysicalReg::A7: return "a7";
|
||||||
|
case PhysicalReg::S2: return "s2"; case PhysicalReg::S3: return "s3";
|
||||||
|
case PhysicalReg::S4: return "s4"; case PhysicalReg::S5: return "s5";
|
||||||
|
case PhysicalReg::S6: return "s6"; case PhysicalReg::S7: return "s7";
|
||||||
|
case PhysicalReg::S8: return "s8"; case PhysicalReg::S9: return "s9";
|
||||||
|
case PhysicalReg::S10: return "s10"; case PhysicalReg::S11: return "s11";
|
||||||
|
case PhysicalReg::T3: return "t3"; case PhysicalReg::T4: return "t4";
|
||||||
|
case PhysicalReg::T5: return "t5"; case PhysicalReg::T6: return "t6";
|
||||||
|
case PhysicalReg::F0: return "f0"; case PhysicalReg::F1: return "f1";
|
||||||
|
case PhysicalReg::F2: return "f2"; case PhysicalReg::F3: return "f3";
|
||||||
|
case PhysicalReg::F4: return "f4"; case PhysicalReg::F5: return "f5";
|
||||||
|
case PhysicalReg::F6: return "f6"; case PhysicalReg::F7: return "f7";
|
||||||
|
case PhysicalReg::F8: return "f8"; case PhysicalReg::F9: return "f9";
|
||||||
|
case PhysicalReg::F10: return "f10"; case PhysicalReg::F11: return "f11";
|
||||||
|
case PhysicalReg::F12: return "f12"; case PhysicalReg::F13: return "f13";
|
||||||
|
case PhysicalReg::F14: return "f14"; case PhysicalReg::F15: return "f15";
|
||||||
|
case PhysicalReg::F16: return "f16"; case PhysicalReg::F17: return "f17";
|
||||||
|
case PhysicalReg::F18: return "f18"; case PhysicalReg::F19: return "f19";
|
||||||
|
case PhysicalReg::F20: return "f20"; case PhysicalReg::F21: return "f21";
|
||||||
|
case PhysicalReg::F22: return "f22"; case PhysicalReg::F23: return "f23";
|
||||||
|
case PhysicalReg::F24: return "f24"; case PhysicalReg::F25: return "f25";
|
||||||
|
case PhysicalReg::F26: return "f26"; case PhysicalReg::F27: return "f27";
|
||||||
|
case PhysicalReg::F28: return "f28"; case PhysicalReg::F29: return "f29";
|
||||||
|
case PhysicalReg::F30: return "f30"; case PhysicalReg::F31: return "f31";
|
||||||
|
default: return "UNKNOWN_REG";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// [新增] 打印栈帧信息的完整实现
|
||||||
|
void MachineFunction::dumpStackFrameInfo(std::ostream& os) const {
|
||||||
|
const StackFrameInfo& info = frame_info;
|
||||||
|
|
||||||
|
os << "--- Stack Frame Info for function '" << getName() << "' ---\n";
|
||||||
|
|
||||||
|
// 打印尺寸信息
|
||||||
|
os << " Sizes:\n";
|
||||||
|
os << " Total Size: " << info.total_size << " bytes\n";
|
||||||
|
os << " Locals Size: " << info.locals_size << " bytes\n";
|
||||||
|
os << " Spill Size: " << info.spill_size << " bytes\n";
|
||||||
|
os << " Callee-Saved Size: " << info.callee_saved_size << " bytes\n";
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印 Alloca 变量的偏移量
|
||||||
|
os << " Alloca Offsets (vreg -> offset from FP):\n";
|
||||||
|
if (info.alloca_offsets.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
for (const auto& pair : info.alloca_offsets) {
|
||||||
|
os << " %vreg" << pair.first << " -> " << pair.second << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印溢出变量的偏移量
|
||||||
|
os << " Spill Offsets (vreg -> offset from FP):\n";
|
||||||
|
if (info.spill_offsets.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
for (const auto& pair : info.spill_offsets) {
|
||||||
|
os << " %vreg" << pair.first << " -> " << pair.second << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印使用的被调用者保存寄存器
|
||||||
|
os << " Used Callee-Saved Registers:\n";
|
||||||
|
if (info.used_callee_saved_regs.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
os << " { ";
|
||||||
|
for (const auto& reg : info.used_callee_saved_regs) {
|
||||||
|
os << regToString(reg) << " ";
|
||||||
|
}
|
||||||
|
os << "}\n";
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印需要保存/恢复的被调用者保存寄存器 (有序)
|
||||||
|
os << " Callee-Saved Registers to Store/Restore:\n";
|
||||||
|
if (info.callee_saved_regs_to_store.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
os << " [ ";
|
||||||
|
for (const auto& reg : info.callee_saved_regs_to_store) {
|
||||||
|
os << regToString(reg) << " ";
|
||||||
|
}
|
||||||
|
os << "]\n";
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印最终的寄存器分配结果
|
||||||
|
os << " Final Register Allocation Map (vreg -> preg):\n";
|
||||||
|
if (info.vreg_to_preg_map.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
for (const auto& pair : info.vreg_to_preg_map) {
|
||||||
|
os << " %vreg" << pair.first << " -> " << regToString(pair.second) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
os << "---------------------------------------------------\n";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1108,7 +1108,7 @@ void RISCv64RegAlloc::combine(unsigned u, unsigned v) {
|
|||||||
moveList[u] = moveList.at(v);
|
moveList[u] = moveList.at(v);
|
||||||
}
|
}
|
||||||
enableMoves({v});
|
enableMoves({v});
|
||||||
for (unsigned t : adjacent(v)) {
|
for (unsigned t : adjList.at(v)) {
|
||||||
addEdge(t, u);
|
addEdge(t, u);
|
||||||
decrementDegree(t);
|
decrementDegree(t);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "IR.h" // 确保包含了您自己的IR头文件
|
#include "IR.h" // 确保包含了您自己的IR头文件
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -300,7 +301,7 @@ public:
|
|||||||
StackFrameInfo& getFrameInfo() { return frame_info; }
|
StackFrameInfo& getFrameInfo() { return frame_info; }
|
||||||
const std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() const { return blocks; }
|
const std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() const { return blocks; }
|
||||||
std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() { return blocks; }
|
std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() { return blocks; }
|
||||||
|
void dumpStackFrameInfo(std::ostream& os = std::cerr) const;
|
||||||
void addBlock(std::unique_ptr<MachineBasicBlock> block) {
|
void addBlock(std::unique_ptr<MachineBasicBlock> block) {
|
||||||
blocks.push_back(std::move(block));
|
blocks.push_back(std::move(block));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user