[backend] it works 1.0
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
#include "RISCv32Backend.h"
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
const std::vector<RISCv32CodeGen::PhysicalReg> RISCv32CodeGen::allocable_regs = {
|
||||
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
|
||||
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
|
||||
@@ -33,16 +35,16 @@ std::string RISCv32CodeGen::code_gen() {
|
||||
std::string RISCv32CodeGen::module_gen() {
|
||||
std::stringstream ss;
|
||||
// 生成全局变量(数据段)
|
||||
for (auto global : *module->getGlobalValues()) {
|
||||
for (const auto& global : *module->getGlobalValues()) {
|
||||
ss << ".data\n";
|
||||
ss << ".globl " << global->getName() << "\n";
|
||||
ss << global->getName() << ":\n";
|
||||
ss << ".globl " << global.second->getName() << "\n";
|
||||
ss << global.second->getName() << ":\n";
|
||||
ss << " .word 0\n"; // 假设初始化为0
|
||||
}
|
||||
// 生成函数
|
||||
ss << ".text\n";
|
||||
for (auto func : *module->getFunctions()) {
|
||||
ss << function_gen(func);
|
||||
for (const auto& func : *module->getFunctions()) {
|
||||
ss << function_gen(func.second);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
@@ -52,17 +54,17 @@ std::string RISCv32CodeGen::function_gen(Function* func) {
|
||||
// 函数标签
|
||||
ss << ".globl " << func->getName() << "\n";
|
||||
ss << func->getName() << ":\n";
|
||||
// 序言:保存ra,分配堆栈
|
||||
bool is_leaf = true; // 简单假设,实际需检查是否调用其他函数
|
||||
ss << " addi sp, sp, -16\n"; // 分配堆栈空间
|
||||
ss << " sw ra, 12(sp)\n"; // 保存返回地址
|
||||
// 序言:保存 ra,分配堆栈
|
||||
bool is_leaf = true; // 简化假设
|
||||
ss << " addi sp, sp, -16\n";
|
||||
ss << " sw ra, 12(sp)\n";
|
||||
// 寄存器分配
|
||||
auto alloc = register_allocation(func);
|
||||
// 生成基本块代码
|
||||
for (auto bb : func->getBasicBlocks()) {
|
||||
ss << basicBlock_gen(bb, alloc);
|
||||
for (const auto& bb : func->getBasicBlocks()) {
|
||||
ss << basicBlock_gen(bb.get(), alloc);
|
||||
}
|
||||
// 结尾:恢复ra,释放堆栈
|
||||
// 结尾:恢复 ra,释放堆栈
|
||||
ss << " lw ra, 12(sp)\n";
|
||||
ss << " addi sp, sp, 16\n";
|
||||
ss << " ret\n";
|
||||
@@ -72,23 +74,28 @@ std::string RISCv32CodeGen::function_gen(Function* func) {
|
||||
std::string RISCv32CodeGen::basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc) {
|
||||
std::stringstream ss;
|
||||
ss << bb->getName() << ":\n";
|
||||
for (auto inst : bb->getInstructions()) {
|
||||
auto riscv_insts = instruction_gen(inst);
|
||||
for (const auto& inst : bb->getInstructions()) {
|
||||
auto riscv_insts = instruction_gen(inst.get());
|
||||
for (const auto& riscv_inst : riscv_insts) {
|
||||
ss << " " << riscv_inst.opcode;
|
||||
for (size_t i = 0; i < riscv_inst.operands.size(); ++i) {
|
||||
if (i > 0) ss << ", ";
|
||||
if (riscv_inst.operands[i].kind == Operand::Reg) {
|
||||
auto it = alloc.reg_map.find((Value*)riscv_inst.operands[i].value.c_str());
|
||||
if (riscv_inst.operands[i].kind == Operand::Kind::Reg) {
|
||||
auto it = alloc.reg_map.find(riscv_inst.operands[i].value);
|
||||
if (it != alloc.reg_map.end()) {
|
||||
ss << reg_to_string(it->second);
|
||||
} else {
|
||||
// 溢出到堆栈
|
||||
auto stack_it = alloc.stack_map.find((Value*)riscv_inst.operands[i].value.c_str());
|
||||
ss << "[sp+" << stack_it->second << "]";
|
||||
auto stack_it = alloc.stack_map.find(riscv_inst.operands[i].value);
|
||||
if (stack_it != alloc.stack_map.end()) {
|
||||
ss << stack_it->second << "(sp)";
|
||||
} else {
|
||||
ss << "%" << riscv_inst.operands[i].value->getName();
|
||||
}
|
||||
}
|
||||
} else if (riscv_inst.operands[i].kind == Operand::Kind::Imm) {
|
||||
ss << riscv_inst.operands[i].label;
|
||||
} else {
|
||||
ss << riscv_inst.operands[i].value;
|
||||
ss << riscv_inst.operands[i].label;
|
||||
}
|
||||
}
|
||||
ss << "\n";
|
||||
@@ -101,69 +108,50 @@ std::vector<RISCv32CodeGen::RISCv32Inst> RISCv32CodeGen::instruction_gen(Instruc
|
||||
std::vector<RISCv32Inst> insts;
|
||||
if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
|
||||
std::string opcode;
|
||||
if (bin->getOpcode() == BinaryInst::Add) opcode = "add";
|
||||
else if (bin->getOpcode() == BinaryInst::Sub) opcode = "sub";
|
||||
else if (bin->getOpcode() == BinaryInst::Mul) opcode = "mul";
|
||||
else return insts; // 未实现其他操作
|
||||
if (bin->getKind() == BinaryInst::kAdd) opcode = "add";
|
||||
else if (bin->getKind() == BinaryInst::kSub) opcode = "sub";
|
||||
else if (bin->getKind() == BinaryInst::kMul) opcode = "mul";
|
||||
else return insts; // 其他操作未实现
|
||||
insts.emplace_back(opcode, std::vector<Operand>{
|
||||
{Operand::Reg, std::string((const char*)bin->getResult())},
|
||||
{Operand::Reg, std::string((const char*)bin->getLHS())},
|
||||
{Operand::Reg, std::string((const char*)bin->getRHS())}
|
||||
{Operand::Kind::Reg, bin},
|
||||
{Operand::Kind::Reg, bin->getLhs()},
|
||||
{Operand::Kind::Reg, bin->getRhs()}
|
||||
});
|
||||
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
|
||||
insts.emplace_back("lw", std::vector<Operand>{
|
||||
{Operand::Reg, std::string((const char*)load->getResult())},
|
||||
{Operand::Label, load->getPointer()->getName()}
|
||||
{Operand::Kind::Reg, load},
|
||||
{Operand::Kind::Label, load->getPointer()->getName()}
|
||||
});
|
||||
} else if (auto store = dynamic_cast<StoreInst*>(inst)) {
|
||||
insts.emplace_back("sw", std::vector<Operand>{
|
||||
{Operand::Reg, std::string((const char*)store->getValue())},
|
||||
{Operand::Label, store->getPointer()->getName()}
|
||||
{Operand::Kind::Reg, store->getValue()},
|
||||
{Operand::Kind::Label, store->getPointer()->getName()}
|
||||
});
|
||||
} // 其他指令类型待实现
|
||||
}
|
||||
return insts;
|
||||
}
|
||||
|
||||
void RISCv32CodeGen::eliminate_phi(Function* func) {
|
||||
// 简单实现:假设CopyInst存在
|
||||
for (auto bb : func->getBasicBlocks()) {
|
||||
for (auto inst : bb->getInstructions()) {
|
||||
if (/* inst is PhiInst */) {
|
||||
// 插入CopyInst到前驱块
|
||||
// 移除phi指令
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: 实现 phi 指令消除
|
||||
}
|
||||
|
||||
std::map<Instruction*, std::set<Value*>> RISCv32CodeGen::liveness_analysis(Function* func) {
|
||||
std::map<Instruction*, std::set<Value*>> live_sets;
|
||||
// 简单实现:需实际计算活跃性
|
||||
// TODO: 实现活跃性分析
|
||||
return live_sets;
|
||||
}
|
||||
|
||||
std::map<Value*, std::set<Value*>> RISCv32CodeGen::build_interference_graph(
|
||||
const std::map<Instruction*, std::set<Value*>>& live_sets) {
|
||||
std::map<Value*, std::set<Value*>> graph;
|
||||
// 简单实现:需实际构建干扰图
|
||||
// TODO: 实现干扰图构建
|
||||
return graph;
|
||||
}
|
||||
|
||||
RISCv32CodeGen::RegAllocResult RISCv32CodeGen::register_allocation(Function* func) {
|
||||
RegAllocResult result;
|
||||
eliminate_phi(func);
|
||||
auto live_sets = liveness_analysis(func);
|
||||
auto graph = build_interference_graph(live_sets);
|
||||
// 图着色算法
|
||||
std::vector<Value*> stack;
|
||||
std::map<Value*, int> degrees;
|
||||
for (const auto& pair : graph) {
|
||||
degrees[pair.first] = pair.second.size();
|
||||
if (degrees[pair.first] < allocable_regs.size()) {
|
||||
stack.push_back(pair.first);
|
||||
}
|
||||
}
|
||||
// 简单实现:需完成图着色和溢出处理
|
||||
// TODO: 实现寄存器分配
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@@ -8,10 +8,11 @@
|
||||
#include <set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class RISCv32CodeGen {
|
||||
public:
|
||||
explicit RISCv32CodeGen(Module* mod) : module(mod) {}
|
||||
std::string code_gen(); // 生成整个模块的汇编代码
|
||||
std::string code_gen(); // 生成模块的汇编代码
|
||||
|
||||
private:
|
||||
Module* module;
|
||||
@@ -27,11 +28,13 @@ private:
|
||||
struct Operand {
|
||||
enum class Kind { Reg, Imm, Label };
|
||||
Kind kind;
|
||||
std::string value; // 寄存器名、立即数或标签
|
||||
Operand(Kind k, const std::string& v) : kind(k), value(v) {}
|
||||
Value* value; // 用于寄存器
|
||||
std::string label; // 用于标签或立即数
|
||||
Operand(Kind k, Value* v) : kind(k), value(v), label("") {}
|
||||
Operand(Kind k, const std::string& l) : kind(k), value(nullptr), label(l) {}
|
||||
};
|
||||
|
||||
// RISC-V指令
|
||||
// RISC-V 指令
|
||||
struct RISCv32Inst {
|
||||
std::string opcode;
|
||||
std::vector<Operand> operands;
|
||||
@@ -59,5 +62,6 @@ private:
|
||||
std::string reg_to_string(PhysicalReg reg);
|
||||
};
|
||||
|
||||
#endif // RISCV32_BACKEND_H
|
||||
}
|
||||
} // namespace sysy
|
||||
|
||||
#endif // RISCV32_BACKEND_H
|
||||
@@ -9,6 +9,7 @@ using namespace antlr4;
|
||||
#include "ASTPrinter.h"
|
||||
#include "Backend.h"
|
||||
#include "SysYIRGenerator.h"
|
||||
#include "RISCv32Backend.h"
|
||||
using namespace sysy;
|
||||
|
||||
static string argStopAfter;
|
||||
@@ -80,19 +81,20 @@ int main(int argc, char **argv) {
|
||||
SysYIRGenerator generator;
|
||||
generator.visitCompUnit(moduleAST);
|
||||
if (argStopAfter == "ir") {
|
||||
SysYIRGenerator generator;
|
||||
generator.visitCompUnit(moduleAST);
|
||||
auto moduleIR = generator.get();
|
||||
moduleIR->print(cout);
|
||||
return EXIT_SUCCESS;
|
||||
auto module = generator.get();
|
||||
module->print(cout);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// generate assembly
|
||||
RISCv32CodeGen codegen(moduleIR);
|
||||
auto module = generator.get();
|
||||
sysy::RISCv32CodeGen codegen(module);
|
||||
string asmCode = codegen.code_gen();
|
||||
cout << asmCode << endl;
|
||||
if (argStopAfter == "asm")
|
||||
if (argStopAfter == "asm") {
|
||||
cout << asmCode << endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user