[backend] introduced DAG, GraphAlloc
This commit is contained in:
@@ -6,61 +6,57 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class RISCv32CodeGen {
|
||||
public:
|
||||
explicit RISCv32CodeGen(Module* mod) : module(mod) {}
|
||||
std::string code_gen(); // 生成模块的汇编代码
|
||||
|
||||
private:
|
||||
Module* module;
|
||||
|
||||
// 物理寄存器
|
||||
enum class PhysicalReg {
|
||||
S0, // x8, 帧指针
|
||||
T0, T1, T2, T3, T4, T5, T6, // x5-x7, x28-x31
|
||||
A0, A1, A2, A3, A4, A5, A6, A7 // x10-x17
|
||||
};
|
||||
static const std::vector<PhysicalReg> allocable_regs;
|
||||
|
||||
// 操作数
|
||||
struct Operand {
|
||||
enum class Kind { Reg, Imm, Label };
|
||||
Kind kind;
|
||||
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) {}
|
||||
S0, T0, T1, T2, T3, T4, T5, T6,
|
||||
A0, A1, A2, A3, A4, A5, A6, A7
|
||||
};
|
||||
|
||||
// RISC-V 指令
|
||||
struct RISCv32Inst {
|
||||
std::string opcode;
|
||||
std::vector<Operand> operands;
|
||||
RISCv32Inst(const std::string& op, const std::vector<Operand>& ops)
|
||||
: opcode(op), operands(ops) {}
|
||||
// Move DAGNode and RegAllocResult to public section
|
||||
struct DAGNode {
|
||||
enum NodeKind { CONSTANT, LOAD, STORE, BINARY, CALL, RETURN };
|
||||
NodeKind kind;
|
||||
Value* value = nullptr;
|
||||
std::string inst;
|
||||
std::string result_reg;
|
||||
std::vector<DAGNode*> operands;
|
||||
std::vector<DAGNode*> users;
|
||||
DAGNode(NodeKind k) : kind(k) {}
|
||||
};
|
||||
|
||||
// 寄存器分配结果
|
||||
struct RegAllocResult {
|
||||
std::map<Value*, PhysicalReg> reg_map; // 虚拟寄存器到物理寄存器的映射
|
||||
std::map<Value*, int> stack_map; // 虚拟寄存器到堆栈槽的映射
|
||||
int stack_size; // 堆栈帧大小
|
||||
std::map<std::string, PhysicalReg> vreg_to_preg;
|
||||
std::map<Value*, int> stack_map;
|
||||
int stack_size = 0;
|
||||
};
|
||||
|
||||
// 后端方法
|
||||
RISCv32CodeGen(Module* mod) : module(mod) {}
|
||||
|
||||
std::string code_gen();
|
||||
std::string module_gen();
|
||||
std::string function_gen(Function* func);
|
||||
std::string basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc);
|
||||
std::vector<std::string> instruction_gen(Instruction* inst, const RegAllocResult& alloc);
|
||||
std::vector<std::unique_ptr<DAGNode>> build_dag(BasicBlock* bb);
|
||||
void select_instructions(DAGNode* node, const RegAllocResult& alloc); // Use const
|
||||
void emit_instructions(DAGNode* node, std::vector<std::string>& insts, const RegAllocResult& alloc); // Add alloc
|
||||
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);
|
||||
std::map<Instruction*, std::set<Value*>> liveness_analysis(Function* func);
|
||||
std::map<Value*, std::set<Value*>> build_interference_graph(
|
||||
const std::map<Instruction*, std::set<Value*>>& live_sets);
|
||||
std::string reg_to_string(PhysicalReg reg);
|
||||
|
||||
private:
|
||||
static const std::vector<PhysicalReg> allocable_regs;
|
||||
std::map<Value*, std::string> value_vreg_map;
|
||||
Module* module;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
Reference in New Issue
Block a user