Merge branch 'backend' into midend

This commit is contained in:
Lixuanwang
2025-07-29 16:37:11 +08:00
12 changed files with 419 additions and 60 deletions

View File

@@ -37,6 +37,8 @@ add_executable(sysyc
PreRA_Scheduler.cpp
PostRA_Scheduler.cpp
CalleeSavedHandler.cpp
LegalizeImmediates.cpp
PrologueEpilogueInsertion.cpp
RISCv64LLIR.cpp
)

View File

@@ -12,7 +12,7 @@ bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
}
void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
// 【最终方案】: 此 Pass 负责分析、分配栈空间并插入 callee-saved 寄存器的保存/恢复指令。
// 此 Pass 负责分析、分配栈空间并插入 callee-saved 寄存器的保存/恢复指令。
// 它通过与 FrameInfo 协作,确保为 callee-saved 寄存器分配的空间与局部变量/溢出槽的空间不冲突。
// 这样做可以使生成的 sd/ld 指令能被后续的优化 Pass (如 PostRA-Scheduler) 处理。
@@ -83,7 +83,7 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
current_offset -= 8;
}
// 5. 【已修复】在函数结尾ret之前插入恢复指令使用反向遍历来避免迭代器失效
// 5. 在函数结尾ret之前插入恢复指令使用反向遍历来避免迭代器失效
for (auto& mbb : mfunc->getBlocks()) {
// 使用手动控制的反向循环
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {

168
src/LegalizeImmediates.cpp Normal file
View File

@@ -0,0 +1,168 @@
#include "LegalizeImmediates.h"
#include "RISCv64ISel.h" // 需要包含它以调用 getNewVReg()
#include "RISCv64AsmPrinter.h"
#include <vector>
#include <iostream>
// 声明外部调试控制变量
extern int DEBUG;
extern int DEEPDEBUG;
namespace sysy {
char LegalizeImmediatesPass::ID = 0;
// 辅助函数检查一个立即数是否在RISC-V的12位有符号范围内
static bool isLegalImmediate(int64_t imm) {
return imm >= -2048 && imm <= 2047;
}
void LegalizeImmediatesPass::runOnMachineFunction(MachineFunction* mfunc) {
if (DEBUG) {
std::cerr << "===== Running Legalize Immediates Pass on function: " << mfunc->getName() << " =====\n";
}
// 定义我们保留的、用于暂存的物理寄存器
const PhysicalReg TEMP_REG = PhysicalReg::T5;
// 创建一个临时的AsmPrinter用于打印指令方便调试
RISCv64AsmPrinter temp_printer(mfunc);
if (DEEPDEBUG) {
temp_printer.setStream(std::cerr);
}
for (auto& mbb : mfunc->getBlocks()) {
if (DEEPDEBUG) {
std::cerr << "--- Processing Basic Block: " << mbb->getName() << " ---\n";
}
// 创建一个新的指令列表,用于存放合法化后的指令
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
if (DEEPDEBUG) {
std::cerr << " Checking: ";
// 打印指令时末尾会带换行符,所以这里不用 std::endl
temp_printer.printInstruction(instr_ptr.get(), true);
}
bool legalized = false; // 标记当前指令是否已被展开处理
switch (instr_ptr->getOpcode()) {
case RVOpcodes::ADDI:
case RVOpcodes::ADDIW: {
auto& operands = instr_ptr->getOperands();
auto imm_op = static_cast<ImmOperand*>(operands.back().get());
if (!isLegalImmediate(imm_op->getValue())) {
if (DEEPDEBUG) {
std::cerr << " >> ILLEGAL immediate (" << imm_op->getValue() << "). Expanding...\n";
}
// 立即数超出范围,需要展开
auto rd_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[0].get()));
auto rs1_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[1].get()));
// 1. li t5, immediate
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(TEMP_REG));
li->addOperand(std::make_unique<ImmOperand>(imm_op->getValue()));
// 2. add/addw rd, rs1, t5
auto new_op = (instr_ptr->getOpcode() == RVOpcodes::ADDI) ? RVOpcodes::ADD : RVOpcodes::ADDW;
auto add = std::make_unique<MachineInstr>(new_op);
add->addOperand(std::move(rd_op));
add->addOperand(std::move(rs1_op));
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
if (DEEPDEBUG) {
std::cerr << " New sequence:\n ";
temp_printer.printInstruction(li.get(), true);
std::cerr << " ";
temp_printer.printInstruction(add.get(), true);
}
new_instructions.push_back(std::move(li));
new_instructions.push_back(std::move(add));
legalized = true;
}
break;
}
// 处理所有内存加载/存储指令
case RVOpcodes::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD:
case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU:
case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD: {
auto& operands = instr_ptr->getOperands();
auto mem_op = static_cast<MemOperand*>(operands.back().get());
auto offset_op = mem_op->getOffset();
if (!isLegalImmediate(offset_op->getValue())) {
if (DEEPDEBUG) {
std::cerr << " >> ILLEGAL immediate offset (" << offset_op->getValue() << "). Expanding...\n";
}
// 偏移量超出范围,需要展开
auto data_reg_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[0].get()));
auto base_reg_op = std::make_unique<RegOperand>(*mem_op->getBase());
// 1. li t5, offset
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(TEMP_REG));
li->addOperand(std::make_unique<ImmOperand>(offset_op->getValue()));
// 2. add t5, base_reg, t5 (计算最终地址结果也放在t5)
auto add = std::make_unique<MachineInstr>(RVOpcodes::ADD);
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
add->addOperand(std::move(base_reg_op));
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
// 3. lw/sw data_reg, 0(t5)
auto mem_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
mem_instr->addOperand(std::move(data_reg_op));
mem_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(TEMP_REG),
std::make_unique<ImmOperand>(0)
));
if (DEEPDEBUG) {
std::cerr << " New sequence:\n ";
temp_printer.printInstruction(li.get(), true);
std::cerr << " ";
temp_printer.printInstruction(add.get(), true);
std::cerr << " ";
temp_printer.printInstruction(mem_instr.get(), true);
}
new_instructions.push_back(std::move(li));
new_instructions.push_back(std::move(add));
new_instructions.push_back(std::move(mem_instr));
legalized = true;
}
break;
}
default:
// 其他指令不需要处理
break;
}
if (!legalized) {
if (DEEPDEBUG) {
std::cerr << " -- Immediate is legal. Skipping.\n";
}
// 如果当前指令不需要合法化,直接将其移动到新列表中
new_instructions.push_back(std::move(instr_ptr));
}
}
// 用新的、已合法化的指令列表替换旧的列表
mbb->getInstructions() = std::move(new_instructions);
}
if (DEBUG) {
std::cerr << "===== Finished Legalize Immediates Pass =====\n\n";
}
}
} // namespace sysy

View File

@@ -0,0 +1,118 @@
#include "PrologueEpilogueInsertion.h"
namespace sysy {
char PrologueEpilogueInsertionPass::ID = 0;
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
StackFrameInfo& frame_info = mfunc->getFrameInfo();
// 完全遵循 AsmPrinter 中的计算逻辑
int total_stack_size = frame_info.locals_size +
frame_info.spill_size +
frame_info.callee_saved_size +
16; // 为 ra 和 s0 固定的16字节
int aligned_stack_size = (total_stack_size + 15) & ~15;
frame_info.total_size = aligned_stack_size;
// 只有在需要分配栈空间时才生成指令
if (aligned_stack_size > 0) {
// --- 1. 插入序言 ---
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
auto& entry_instrs = entry_block->getInstructions();
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));
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));
// 2. 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));
// 3. 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));
// 4. 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));
// 确定插入点(在函数名标签之后)
auto insert_pos = entry_instrs.begin();
// [重要] 这里我们不再需要跳过LABEL因为AsmPrinter将不再打印函数名标签
// 第一个基本块的标签就是函数入口
// 一次性将所有序言指令插入
if (!prologue_instrs.empty()) {
entry_instrs.insert(insert_pos,
std::make_move_iterator(prologue_instrs.begin()),
std::make_move_iterator(prologue_instrs.end()));
}
// --- 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)
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));
// 2. ld s0, (aligned_stack_size - 16)(sp)
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));
// 3. 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));
if (!epilogue_instrs.empty()) {
mbb->getInstructions().insert(it,
std::make_move_iterator(epilogue_instrs.begin()),
std::make_move_iterator(epilogue_instrs.end()));
}
// 处理完一个基本块中的RET后迭代器已失效需跳出
goto next_block;
}
}
next_block:;
}
}
}
} // namespace sysy

View File

@@ -22,52 +22,12 @@ void RISCv64AsmPrinter::run(std::ostream& os, bool debug) {
OS = &os;
*OS << ".globl " << MFunc->getName() << "\n";
*OS << MFunc->getName() << ":\n";
printPrologue();
for (auto& mbb : MFunc->getBlocks()) {
printBasicBlock(mbb.get(), debug);
}
}
// 在 RISCv64AsmPrinter.cpp 文件中
void RISCv64AsmPrinter::printPrologue() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
// 计算总栈帧大小。
// 包含三部分:局部变量区、寄存器溢出区、以及为被调用者保存(callee-saved)寄存器预留的区域。
// 最后再加上为保存 ra 和 s0 固定的16字节。
int total_stack_size = frame_info.locals_size +
frame_info.spill_size +
frame_info.callee_saved_size +
16;
// 保持栈指针16字节对齐
int aligned_stack_size = (total_stack_size + 15) & ~15;
frame_info.total_size = aligned_stack_size; // 更新最终的栈大小
// 只有在需要分配栈空间时才生成指令
if (aligned_stack_size > 0) {
// 1. 一次性分配整个栈帧
*OS << " addi sp, sp, -" << aligned_stack_size << "\n";
// 2. 在新的栈顶附近保存 ra 和 s0
*OS << " sd ra, " << (aligned_stack_size - 8) << "(sp)\n";
*OS << " sd s0, " << (aligned_stack_size - 16) << "(sp)\n";
// 3. 设置新的帧指针 s0使其指向栈帧的底部高地址
*OS << " addi s0, sp, " << aligned_stack_size << "\n";
}
}
void RISCv64AsmPrinter::printEpilogue() {
int aligned_stack_size = MFunc->getFrameInfo().total_size;
if (aligned_stack_size > 0) {
*OS << " ld ra, " << (aligned_stack_size - 8) << "(sp)\n";
*OS << " ld s0, " << (aligned_stack_size - 16) << "(sp)\n";
*OS << " addi sp, sp, " << aligned_stack_size << "\n";
}
}
void RISCv64AsmPrinter::printBasicBlock(MachineBasicBlock* mbb, bool debug) {
if (!mbb->getName().empty()) {
*OS << mbb->getName() << ":\n";
@@ -79,9 +39,6 @@ void RISCv64AsmPrinter::printBasicBlock(MachineBasicBlock* mbb, bool debug) {
void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
auto opcode = instr->getOpcode();
if (opcode == RVOpcodes::RET) {
printEpilogue();
}
if (opcode == RVOpcodes::LABEL) {
// 标签直接打印,不加缩进

View File

@@ -2,7 +2,7 @@
#include "RISCv64ISel.h"
#include "RISCv64RegAlloc.h"
#include "RISCv64AsmPrinter.h"
#include "RISCv64Passes.h" // 包含优化Pass的头文件
#include "RISCv64Passes.h"
#include <sstream>
namespace sysy {
@@ -107,6 +107,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
// 第一次调试打印输出
std::stringstream ss1;
RISCv64AsmPrinter printer1(mfunc.get());
printer1.run(ss1, true);
@@ -119,7 +120,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
// 阶段 3.5: 处理被调用者保存寄存器
// 阶段 3.1: 处理被调用者保存寄存器
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
@@ -131,6 +132,14 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
PostRA_Scheduler local_scheduler;
local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
// 阶段 3.3: 清理产生的大立即数
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());

View File

@@ -52,8 +52,18 @@ std::unique_ptr<MachineFunction> RISCv64ISel::runOnFunction(Function* func) {
// 指令选择主流程
void RISCv64ISel::select() {
// 遍历基本块为它们创建对应的MachineBasicBlock
bool is_first_block = true;
for (const auto& bb_ptr : F->getBasicBlocks()) {
auto mbb = std::make_unique<MachineBasicBlock>(bb_ptr->getName(), MFunc.get());
std::string mbb_name;
if (is_first_block) {
// 对于函数的第一个基本块,其标签必须与函数名完全相同
mbb_name = F->getName();
is_first_block = false;
} else {
// 对于后续的基本块继续使用它们在IR中的原始名称
mbb_name = bb_ptr->getName();
}
auto mbb = std::make_unique<MachineBasicBlock>(mbb_name, MFunc.get());
bb_map[bb_ptr.get()] = mbb.get();
MFunc->addBlock(std::move(mbb));
}

View File

@@ -1,6 +1,7 @@
#include "RISCv64RegAlloc.h"
#include "RISCv64ISel.h"
#include "RISCv64AsmPrinter.h" // For DEBUG output
#include "LegalizeImmediates.h"
#include <algorithm>
#include <vector>
#include <iostream> // For DEBUG output
@@ -10,6 +11,17 @@ namespace sysy {
RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
allocable_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, /*PhysicalReg::T5,*/PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7,
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3,
PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
};
// 创建一个包含所有通用整数寄存器的临时列表
const std::vector<PhysicalReg> all_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
@@ -21,7 +33,7 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
// 映射物理寄存器到特殊的虚拟寄存器ID用于干扰图中的物理寄存器节点
// 确保这些特殊ID不会与vreg_counter生成的常规虚拟寄存器ID冲突
for (PhysicalReg preg : allocable_int_regs) {
for (PhysicalReg preg : all_int_regs) {
preg_to_vreg_id_map[preg] = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID) + static_cast<unsigned>(preg);
}
}
@@ -32,6 +44,8 @@ void RISCv64RegAlloc::run() {
handleCallingConvention();
// 阶段 2: 消除帧索引(为局部变量和栈参数分配栈偏移)
eliminateFrameIndices();
// 调试输出当前的LLIR状态
{ // 使用大括号创建一个局部作用域避免printer变量泄露
if (DEBUG) {
std::cerr << "\n===== LLIR after eliminateFrameIndices for function: "
@@ -46,6 +60,7 @@ void RISCv64RegAlloc::run() {
std::cerr << "===== End of LLIR =====\n\n";
}
}
// 阶段 3: 活跃性分析
analyzeLiveness();
// 阶段 4: 构建干扰图包含CALL指令对调用者保存寄存器的影响
@@ -592,6 +607,7 @@ void RISCv64RegAlloc::buildInterferenceGraph() {
// 因此,所有调用者保存的物理寄存器都与 CALL 指令的 live_out 中的所有变量冲突。
const std::vector<PhysicalReg>& caller_saved_regs = getCallerSavedIntRegs();
for (PhysicalReg cs_reg : caller_saved_regs) {
if (preg_to_vreg_id_map.count(cs_reg)) {
unsigned cs_vreg_id = preg_to_vreg_id_map.at(cs_reg); // 获取物理寄存器对应的特殊vreg ID
// 将这个物理寄存器节点与 CALL 指令的 live_out 中的所有虚拟寄存器添加干扰边。
@@ -605,6 +621,14 @@ void RISCv64RegAlloc::buildInterferenceGraph() {
interference_graph[live_vreg_out].insert(cs_vreg_id);
}
}
} else {
// 如果物理寄存器没有对应的特殊虚拟寄存器ID可能是因为它不是调用者保存的寄存器。
// 这种情况通常不应该发生,但我们可以在这里添加一个警告或错误处理。
if (DEEPDEBUG) {
std::cerr << "Warning: Physical register " << static_cast<int>(cs_reg)
<< " does not have a corresponding special vreg ID.\n";
}
}
}
}
if (DEEPDEBUG) std::cerr << " ----------------\n";

View File

@@ -0,0 +1,36 @@
#ifndef SYSY_LEGALIZE_IMMEDIATES_H
#define SYSY_LEGALIZE_IMMEDIATES_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
// MachineFunction 的前向声明在这里是可选的,因为 RISCv64LLIR.h 已经定义了它
// class MachineFunction;
/**
* @class LegalizeImmediatesPass
* @brief 一个用于“合法化”机器指令的Pass。
*
* 这个Pass的主要职责是遍历所有机器指令查找那些包含了超出
* 目标架构RISC-V编码范围的大立即数immediate的指令
* 并将它们展开成一个等价的、只包含合法立即数的指令序列。
*
* 它在指令选择之后、寄存器分配之前运行,确保进入后续阶段的
* 所有指令都符合硬件约束。
*/
class LegalizeImmediatesPass : public Pass {
public:
static char ID;
LegalizeImmediatesPass() : Pass("legalize-immediates", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // SYSY_LEGALIZE_IMMEDIATES_H

View File

@@ -0,0 +1,35 @@
#ifndef SYSY_PROLOGUE_EPILOGUE_INSERTION_H
#define SYSY_PROLOGUE_EPILOGUE_INSERTION_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
class MachineFunction;
/**
* @class PrologueEpilogueInsertionPass
* @brief 在函数中插入序言和尾声的机器指令。
*
* 这个Pass在所有栈帧大小计算完毕后包括局部变量、溢出槽、被调用者保存寄存器
* 在寄存器分配之后运行。它的职责是:
* 1. 根据 StackFrameInfo 中的最终栈大小,生成用于分配和释放栈帧的指令 (addi sp, sp, +/-size)。
* 2. 生成用于保存和恢复返回地址(ra)和旧帧指针(s0)的指令。
* 3. 将这些指令作为 MachineInstr 对象插入到 MachineFunction 的入口块和所有返回块中。
* 4. 这个Pass可能会生成带有大立即数的指令需要后续的 LegalizeImmediatesPass 来处理。
*/
class PrologueEpilogueInsertionPass : public Pass {
public:
static char ID;
PrologueEpilogueInsertionPass() : Pass("prologue-epilogue-insertion", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // SYSY_PROLOGUE_EPILOGUE_INSERTION_H

View File

@@ -20,8 +20,6 @@ public:
void setStream(std::ostream& os) { OS = &os; }
private:
// 打印各个部分
void printPrologue();
void printEpilogue();
void printBasicBlock(MachineBasicBlock* mbb, bool debug = false);
// 辅助函数

View File

@@ -6,6 +6,8 @@
#include "PreRA_Scheduler.h"
#include "PostRA_Scheduler.h"
#include "CalleeSavedHandler.h"
#include "LegalizeImmediates.h"
#include "PrologueEpilogueInsertion.h"
#include "Pass.h"
namespace sysy {