[midend]重构了src目录
This commit is contained in:
151
src/backend/RISCv64/RISCv64Backend.cpp
Normal file
151
src/backend/RISCv64/RISCv64Backend.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "RISCv64Backend.h"
|
||||
#include "RISCv64ISel.h"
|
||||
#include "RISCv64RegAlloc.h"
|
||||
#include "RISCv64AsmPrinter.h"
|
||||
#include "RISCv64Passes.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 顶层入口
|
||||
std::string RISCv64CodeGen::code_gen() {
|
||||
return module_gen();
|
||||
}
|
||||
|
||||
// 模块级代码生成
|
||||
std::string RISCv64CodeGen::module_gen() {
|
||||
std::stringstream ss;
|
||||
|
||||
// --- [新逻辑] 步骤1:将全局变量分为.data和.bss两组 ---
|
||||
std::vector<GlobalValue*> data_globals;
|
||||
std::vector<GlobalValue*> bss_globals;
|
||||
|
||||
for (const auto& global_ptr : module->getGlobals()) {
|
||||
GlobalValue* global = global_ptr.get();
|
||||
const auto& init_values = global->getInitValues();
|
||||
|
||||
// 判断是否为大型零初始化数组,以便放入.bss段
|
||||
bool is_large_zero_array = false;
|
||||
// 规则:初始化列表只有一项,且该项是值为0的整数,且数量大于一个阈值(例如16)
|
||||
if (init_values.getValues().size() == 1) {
|
||||
if (auto const_val = dynamic_cast<ConstantValue*>(init_values.getValues()[0])) {
|
||||
if (const_val->isInt() && const_val->getInt() == 0 && init_values.getNumbers()[0] > 16) {
|
||||
is_large_zero_array = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_large_zero_array) {
|
||||
bss_globals.push_back(global);
|
||||
} else {
|
||||
data_globals.push_back(global);
|
||||
}
|
||||
}
|
||||
|
||||
// --- [新逻辑] 步骤2:生成 .bss 段的代码 ---
|
||||
if (!bss_globals.empty()) {
|
||||
ss << ".bss\n"; // 切换到 .bss 段
|
||||
for (GlobalValue* global : bss_globals) {
|
||||
// 获取数组总大小(元素个数 * 元素大小)
|
||||
// 在SysY中,我们假设元素都是4字节(int或float)
|
||||
unsigned count = global->getInitValues().getNumbers()[0];
|
||||
unsigned total_size = count * 4;
|
||||
|
||||
ss << " .align 3\n"; // 8字节对齐 (2^3)
|
||||
ss << ".globl " << global->getName() << "\n";
|
||||
ss << ".type " << global->getName() << ", @object\n";
|
||||
ss << ".size " << global->getName() << ", " << total_size << "\n";
|
||||
ss << global->getName() << ":\n";
|
||||
// 使用 .space 指令来预留指定大小的零填充空间
|
||||
ss << " .space " << total_size << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// --- [旧逻辑保留] 步骤3:生成 .data 段的代码 ---
|
||||
if (!data_globals.empty()) {
|
||||
ss << ".data\n"; // 切换到 .data 段
|
||||
for (GlobalValue* global : data_globals) {
|
||||
ss << ".globl " << global->getName() << "\n";
|
||||
ss << global->getName() << ":\n";
|
||||
const auto& init_values = global->getInitValues();
|
||||
// 使用您原有的逻辑来处理显式初始化的值
|
||||
for (size_t i = 0; i < init_values.getValues().size(); ++i) {
|
||||
auto val = init_values.getValues()[i];
|
||||
auto count = init_values.getNumbers()[i];
|
||||
if (auto constant = dynamic_cast<ConstantValue*>(val)) {
|
||||
for (unsigned j = 0; j < count; ++j) {
|
||||
if (constant->isInt()) {
|
||||
ss << " .word " << constant->getInt() << "\n";
|
||||
} else {
|
||||
float f = constant->getFloat();
|
||||
uint32_t float_bits = *(uint32_t*)&f;
|
||||
ss << " .word " << float_bits << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- 处理函数 (.text段) 的逻辑保持不变 ---
|
||||
if (!module->getFunctions().empty()) {
|
||||
ss << ".text\n";
|
||||
for (const auto& func_pair : module->getFunctions()) {
|
||||
if (func_pair.second.get()) {
|
||||
ss << function_gen(func_pair.second.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// function_gen 现在是包含具体优化名称的、完整的处理流水线
|
||||
std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
// === 完整的后端处理流水线 ===
|
||||
|
||||
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
||||
RISCv64ISel isel;
|
||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
||||
|
||||
// 第一次调试打印输出
|
||||
std::stringstream ss1;
|
||||
RISCv64AsmPrinter printer1(mfunc.get());
|
||||
printer1.run(ss1, true);
|
||||
|
||||
// 阶段 2: 指令调度 (Instruction Scheduling)
|
||||
PreRA_Scheduler scheduler;
|
||||
scheduler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
||||
RISCv64RegAlloc reg_alloc(mfunc.get());
|
||||
reg_alloc.run();
|
||||
|
||||
// 阶段 3.1: 处理被调用者保存寄存器
|
||||
CalleeSavedHandler callee_handler;
|
||||
callee_handler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 4: 窥孔优化 (Peephole Optimization)
|
||||
PeepholeOptimizer peephole;
|
||||
peephole.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 5: 局部指令调度 (Local Scheduling)
|
||||
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());
|
||||
printer.run(ss);
|
||||
if (DEBUG) ss << "\n" << ss1.str(); // 将指令选择阶段的结果也包含在最终输出中
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
Reference in New Issue
Block a user