|
|
#pragma once
|
|
|
|
|
|
#include <initializer_list>
|
|
|
#include <iosfwd>
|
|
|
#include <memory>
|
|
|
#include <string>
|
|
|
#include <vector>
|
|
|
|
|
|
namespace ir {
|
|
|
class Module;
|
|
|
}
|
|
|
|
|
|
namespace mir {
|
|
|
|
|
|
class MIRContext {
|
|
|
public:
|
|
|
MIRContext() = default;
|
|
|
};
|
|
|
|
|
|
MIRContext& DefaultContext();
|
|
|
|
|
|
enum class PhysReg {
|
|
|
W0, W1, W2, W3, W4, W5, W6, W7,
|
|
|
W8, W9, W10,
|
|
|
X0, X1, X2, X3, X4, X5, X6, X7,
|
|
|
X8, X9, X10, X29, X30, SP,
|
|
|
S0, S1, S2, S3, S4, S5, S6, S7, // 单精度浮点寄存器
|
|
|
S8, S9, S10
|
|
|
};
|
|
|
|
|
|
const char* PhysRegName(PhysReg reg);
|
|
|
|
|
|
enum class Opcode {
|
|
|
Prologue,
|
|
|
Epilogue,
|
|
|
MovImm,
|
|
|
MovReg,
|
|
|
FMovImm, // 浮点立即数加载
|
|
|
FMovReg, // 浮点寄存器移动
|
|
|
LoadStack,
|
|
|
StoreStack,
|
|
|
LoadStackOffset, // 加载数组元素:ldr w8, [x29, base_offset + element_offset]
|
|
|
StoreStackOffset, // 存储数组元素:str w8, [x29, base_offset + element_offset]
|
|
|
LoadStackAddr, // 加载栈地址:add x9, x29, #offset(用于数组基址)
|
|
|
LoadIndirect, // 间接加载:ldr w8, [x9]
|
|
|
StoreIndirect, // 间接存储:str w8, [x9]
|
|
|
LoadGlobal,
|
|
|
StoreGlobal,
|
|
|
LoadGlobalAddr, // 加载全局变量地址(用于数组)
|
|
|
AddRR,
|
|
|
SubRR,
|
|
|
MulRR,
|
|
|
DivRR,
|
|
|
ModRR,
|
|
|
LslRR, // 逻辑左移(用于 index * 4)
|
|
|
FAddRR, // 浮点加法
|
|
|
FSubRR, // 浮点减法
|
|
|
FMulRR, // 浮点乘法
|
|
|
FDivRR, // 浮点除法
|
|
|
CmpRR,
|
|
|
FCmpRR, // 浮点比较
|
|
|
Bl,
|
|
|
B, // 无条件跳转
|
|
|
Bcond, // 条件跳转(基于之前的 cmp)
|
|
|
Cbnz, // 非零跳转
|
|
|
Cbz, // 零跳转
|
|
|
Ret,
|
|
|
};
|
|
|
|
|
|
class Operand {
|
|
|
public:
|
|
|
enum class Kind { Reg, Imm, FrameIndex, Symbol };
|
|
|
|
|
|
static Operand Reg(PhysReg reg);
|
|
|
static Operand Imm(int value);
|
|
|
static Operand FrameIndex(int index);
|
|
|
static Operand Symbol(std::string name);
|
|
|
|
|
|
Kind GetKind() const { return kind_; }
|
|
|
PhysReg GetReg() const { return reg_; }
|
|
|
int GetImm() const { return imm_; }
|
|
|
int GetFrameIndex() const { return imm_; }
|
|
|
const std::string& GetSymbol() const { return symbol_; }
|
|
|
|
|
|
private:
|
|
|
Operand(Kind kind, PhysReg reg, int imm, std::string symbol = "");
|
|
|
|
|
|
Kind kind_;
|
|
|
PhysReg reg_;
|
|
|
int imm_;
|
|
|
std::string symbol_;
|
|
|
};
|
|
|
|
|
|
class MachineInstr {
|
|
|
public:
|
|
|
MachineInstr(Opcode opcode, std::vector<Operand> operands = {});
|
|
|
|
|
|
Opcode GetOpcode() const { return opcode_; }
|
|
|
const std::vector<Operand>& GetOperands() const { return operands_; }
|
|
|
|
|
|
private:
|
|
|
Opcode opcode_;
|
|
|
std::vector<Operand> operands_;
|
|
|
};
|
|
|
|
|
|
struct FrameSlot {
|
|
|
int index = 0;
|
|
|
int size = 4;
|
|
|
int offset = 0;
|
|
|
};
|
|
|
|
|
|
class MachineBasicBlock {
|
|
|
public:
|
|
|
explicit MachineBasicBlock(std::string name);
|
|
|
|
|
|
const std::string& GetName() const { return name_; }
|
|
|
std::vector<MachineInstr>& GetInstructions() { return instructions_; }
|
|
|
const std::vector<MachineInstr>& GetInstructions() const { return instructions_; }
|
|
|
|
|
|
MachineInstr& Append(Opcode opcode,
|
|
|
std::initializer_list<Operand> operands = {});
|
|
|
|
|
|
private:
|
|
|
std::string name_;
|
|
|
std::vector<MachineInstr> instructions_;
|
|
|
};
|
|
|
|
|
|
class MachineFunction {
|
|
|
public:
|
|
|
explicit MachineFunction(std::string name);
|
|
|
|
|
|
const std::string& GetName() const { return name_; }
|
|
|
MachineBasicBlock& GetEntry() { return *blocks_.front(); }
|
|
|
const MachineBasicBlock& GetEntry() const { return *blocks_.front(); }
|
|
|
|
|
|
MachineBasicBlock* CreateBlock(std::string name);
|
|
|
MachineBasicBlock* FindBlock(const std::string& name);
|
|
|
const std::vector<std::unique_ptr<MachineBasicBlock>>& GetBlocks() const {
|
|
|
return blocks_;
|
|
|
}
|
|
|
|
|
|
int CreateFrameIndex(int size = 4);
|
|
|
FrameSlot& GetFrameSlot(int index);
|
|
|
const FrameSlot& GetFrameSlot(int index) const;
|
|
|
const std::vector<FrameSlot>& GetFrameSlots() const { return frame_slots_; }
|
|
|
|
|
|
int GetFrameSize() const { return frame_size_; }
|
|
|
void SetFrameSize(int size) { frame_size_ = size; }
|
|
|
|
|
|
private:
|
|
|
std::string name_;
|
|
|
std::vector<std::unique_ptr<MachineBasicBlock>> blocks_;
|
|
|
std::vector<FrameSlot> frame_slots_;
|
|
|
int frame_size_ = 0;
|
|
|
};
|
|
|
|
|
|
class MachineModule {
|
|
|
public:
|
|
|
MachineModule() = default;
|
|
|
MachineFunction* CreateFunction(std::string name);
|
|
|
const std::vector<std::unique_ptr<MachineFunction>>& GetFunctions() const {
|
|
|
return functions_;
|
|
|
}
|
|
|
|
|
|
void AddGlobalVar(std::string name, int init_val, int count);
|
|
|
const std::vector<std::tuple<std::string, int, int>>& GetGlobalVars() const {
|
|
|
return global_vars_;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
std::vector<std::unique_ptr<MachineFunction>> functions_;
|
|
|
std::vector<std::tuple<std::string, int, int>> global_vars_; // (name, init, count)
|
|
|
};
|
|
|
|
|
|
std::unique_ptr<MachineModule> LowerToMIR(const ir::Module& module);
|
|
|
void RunRegAlloc(MachineFunction& function);
|
|
|
void RunFrameLowering(MachineFunction& function);
|
|
|
void PrintAsm(const MachineModule& module, std::ostream& os);
|
|
|
|
|
|
} // namespace mir
|