Compare commits

...

1 Commits

2 changed files with 523 additions and 973 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,8 @@
#include <set> #include <set>
#include <memory> #include <memory>
#include <iostream> #include <iostream>
#include <functional> // For std::function #include <functional>
#include <stack>
namespace sysy { namespace sysy {
@ -18,18 +19,16 @@ public:
ZERO, RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6 ZERO, RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6
}; };
// Move DAGNode and RegAllocResult to public section
struct DAGNode { struct DAGNode {
enum NodeKind { CONSTANT, LOAD, STORE, BINARY, CALL, RETURN, BRANCH, ALLOCA_ADDR }; // Added ALLOCA_ADDR enum NodeKind { CONSTANT, LOAD, STORE, BINARY, CALL, RETURN, BRANCH, ALLOCA_ADDR };
NodeKind kind; NodeKind kind;
Value* value = nullptr; // For IR Value Value* value = nullptr;
std::string inst; // Generated RISC-V instruction(s) for this node std::string inst;
std::string result_vreg; // Virtual register assigned to this node's result std::string result_vreg;
std::vector<DAGNode*> operands; std::vector<DAGNode*> operands;
std::vector<DAGNode*> users; // For debugging and potentially optimizations std::vector<DAGNode*> users;
DAGNode(NodeKind k) : kind(k) {} DAGNode(NodeKind k) : kind(k) {}
// Debugging / helper
std::string getNodeKindString() const { std::string getNodeKindString() const {
switch (kind) { switch (kind) {
case CONSTANT: return "CONSTANT"; case CONSTANT: return "CONSTANT";
@ -46,9 +45,10 @@ public:
}; };
struct RegAllocResult { struct RegAllocResult {
std::map<std::string, PhysicalReg> vreg_to_preg; // Virtual register to Physical Register mapping std::map<std::string, PhysicalReg> vreg_to_preg; // 虚拟寄存器到物理寄存器的映射
std::map<Value*, int> stack_map; // Value (AllocaInst) to stack offset std::map<Value*, int> stack_map; // AllocaInst到栈偏移的映射
int stack_size = 0; // Total stack frame size for locals and spills std::map<std::string, int> spill_map; // 溢出的虚拟寄存器到栈偏移的映射
int stack_size = 0; // 总栈帧大小
}; };
RISCv32CodeGen(Module* mod) : module(mod) {} RISCv32CodeGen(Module* mod) : module(mod) {}
@ -56,41 +56,46 @@ public:
std::string code_gen(); std::string code_gen();
std::string module_gen(); std::string module_gen();
std::string function_gen(Function* func); std::string function_gen(Function* func);
// 修改 basicBlock_gen 的声明,添加 int block_idx 参数
std::string basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc, int block_idx); std::string basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc, int block_idx);
// DAG related
std::vector<std::unique_ptr<DAGNode>> build_dag(BasicBlock* bb); std::vector<std::unique_ptr<DAGNode>> build_dag(BasicBlock* bb);
void select_instructions(DAGNode* node, const RegAllocResult& alloc); void select_instructions(DAGNode* node, const RegAllocResult& alloc);
// 改变 emit_instructions 的参数,使其可以直接添加汇编指令到 main ss
void emit_instructions(DAGNode* node, std::stringstream& ss, const RegAllocResult& alloc, std::set<DAGNode*>& emitted_nodes); void emit_instructions(DAGNode* node, std::stringstream& ss, const RegAllocResult& alloc, std::set<DAGNode*>& emitted_nodes);
// Register Allocation related
std::map<Instruction*, std::set<std::string>> liveness_analysis(Function* func); std::map<Instruction*, std::set<std::string>> liveness_analysis(Function* func);
std::map<std::string, std::set<std::string>> build_interference_graph( std::map<std::string, std::set<std::string>> build_interference_graph(
const std::map<Instruction*, std::set<std::string>>& live_sets); const std::map<Instruction*, std::set<std::string>>& live_sets);
void color_graph(std::map<std::string, PhysicalReg>& vreg_to_preg, RegAllocResult color_graph(Function* func, const std::map<std::string, std::set<std::string>>& interference_graph);
const std::map<std::string, std::set<std::string>>& interference_graph);
RegAllocResult register_allocation(Function* func);
void eliminate_phi(Function* func); // Phi elimination is typically done before DAG building
// Utility
std::string reg_to_string(PhysicalReg reg);
void print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name);
private: private:
static const std::vector<PhysicalReg> allocable_regs;
std::map<Value*, std::string> value_vreg_map; // Maps IR Value* to its virtual register name
Module* module; Module* module;
int vreg_counter = 0; // Counter for unique virtual register names std::map<PhysicalReg, std::string> preg_to_str = {
int alloca_offset_counter = 0; // Counter for alloca offsets {PhysicalReg::ZERO, "zero"}, {PhysicalReg::RA, "ra"}, {PhysicalReg::SP, "sp"},
{PhysicalReg::GP, "gp"}, {PhysicalReg::TP, "tp"}, {PhysicalReg::T0, "t0"},
{PhysicalReg::T1, "t1"}, {PhysicalReg::T2, "t2"}, {PhysicalReg::S0, "s0"},
{PhysicalReg::S1, "s1"}, {PhysicalReg::A0, "a0"}, {PhysicalReg::A1, "a1"},
{PhysicalReg::A2, "a2"}, {PhysicalReg::A3, "a3"}, {PhysicalReg::A4, "a4"},
{PhysicalReg::A5, "a5"}, {PhysicalReg::A6, "a6"}, {PhysicalReg::A7, "a7"},
{PhysicalReg::S2, "s2"}, {PhysicalReg::S3, "s3"}, {PhysicalReg::S4, "s4"},
{PhysicalReg::S5, "s5"}, {PhysicalReg::S6, "s6"}, {PhysicalReg::S7, "s7"},
{PhysicalReg::S8, "s8"}, {PhysicalReg::S9, "s9"}, {PhysicalReg::S10, "s10"},
{PhysicalReg::S11, "s11"}, {PhysicalReg::T3, "t3"}, {PhysicalReg::T4, "t4"},
{PhysicalReg::T5, "t5"}, {PhysicalReg::T6, "t6"}
};
// 新增一个成员变量来存储当前函数的所有 DAGNode以确保其生命周期贯穿整个函数代码生成 std::vector<PhysicalReg> caller_saved = {
// 这样可以在多个 BasicBlock_gen 调用中访问到完整的 DAG 节点 PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
std::vector<std::unique_ptr<DAGNode>> current_function_dag_nodes; PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3, PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7
};
// 为空标签定义一个伪名称前缀,加上块索引以确保唯一性 std::vector<PhysicalReg> callee_saved = {
const std::string ENTRY_BLOCK_PSEUDO_NAME = "entry_block_"; PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5,
PhysicalReg::S6, PhysicalReg::S7, PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11
};
std::string get_preg_str(PhysicalReg preg) const {
return preg_to_str.at(preg);
}
PhysicalReg get_preg_or_temp(const std::string& vreg, const RegAllocResult& alloc) const;
}; };
} // namespace sysy } // namespace sysy