[backend-beta] saving for simpler implementation for register allocation
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,8 @@
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <functional> // For std::function
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
// Move DAGNode and RegAllocResult to public section
|
||||
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;
|
||||
Value* value = nullptr; // For IR Value
|
||||
std::string inst; // Generated RISC-V instruction(s) for this node
|
||||
std::string result_vreg; // Virtual register assigned to this node's result
|
||||
Value* value = nullptr;
|
||||
std::string inst;
|
||||
std::string result_vreg;
|
||||
std::vector<DAGNode*> operands;
|
||||
std::vector<DAGNode*> users; // For debugging and potentially optimizations
|
||||
std::vector<DAGNode*> users;
|
||||
DAGNode(NodeKind k) : kind(k) {}
|
||||
|
||||
// Debugging / helper
|
||||
std::string getNodeKindString() const {
|
||||
switch (kind) {
|
||||
case CONSTANT: return "CONSTANT";
|
||||
@ -46,9 +45,10 @@ public:
|
||||
};
|
||||
|
||||
struct RegAllocResult {
|
||||
std::map<std::string, PhysicalReg> vreg_to_preg; // Virtual register to Physical Register mapping
|
||||
std::map<Value*, int> stack_map; // Value (AllocaInst) to stack offset
|
||||
int stack_size = 0; // Total stack frame size for locals and spills
|
||||
std::map<std::string, PhysicalReg> vreg_to_preg; // 虚拟寄存器到物理寄存器的映射
|
||||
std::map<Value*, int> stack_map; // AllocaInst到栈偏移的映射
|
||||
std::map<std::string, int> spill_map; // 溢出的虚拟寄存器到栈偏移的映射
|
||||
int stack_size = 0; // 总栈帧大小
|
||||
};
|
||||
|
||||
RISCv32CodeGen(Module* mod) : module(mod) {}
|
||||
@ -56,41 +56,46 @@ public:
|
||||
std::string code_gen();
|
||||
std::string module_gen();
|
||||
std::string function_gen(Function* func);
|
||||
// 修改 basicBlock_gen 的声明,添加 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);
|
||||
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);
|
||||
|
||||
// Register Allocation related
|
||||
std::map<Instruction*, std::set<std::string>> liveness_analysis(Function* func);
|
||||
std::map<std::string, std::set<std::string>> build_interference_graph(
|
||||
const std::map<Instruction*, std::set<std::string>>& live_sets);
|
||||
void color_graph(std::map<std::string, PhysicalReg>& vreg_to_preg,
|
||||
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);
|
||||
RegAllocResult color_graph(Function* func, const std::map<std::string, std::set<std::string>>& interference_graph);
|
||||
|
||||
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;
|
||||
int vreg_counter = 0; // Counter for unique virtual register names
|
||||
int alloca_offset_counter = 0; // Counter for alloca offsets
|
||||
std::map<PhysicalReg, std::string> preg_to_str = {
|
||||
{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,以确保其生命周期贯穿整个函数代码生成
|
||||
// 这样可以在多个 BasicBlock_gen 调用中访问到完整的 DAG 节点
|
||||
std::vector<std::unique_ptr<DAGNode>> current_function_dag_nodes;
|
||||
std::vector<PhysicalReg> caller_saved = {
|
||||
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
|
||||
};
|
||||
|
||||
// 为空标签定义一个伪名称前缀,加上块索引以确保唯一性
|
||||
const std::string ENTRY_BLOCK_PSEUDO_NAME = "entry_block_";
|
||||
std::vector<PhysicalReg> callee_saved = {
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user