forked from NUDT-compiler/nudt-compiler-cpp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
415 lines
8.0 KiB
415 lines
8.0 KiB
#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,
|
|
W11,
|
|
W12,
|
|
W13,
|
|
W14,
|
|
W15,
|
|
W16,
|
|
W17,
|
|
W18,
|
|
W19,
|
|
W20,
|
|
W21,
|
|
W22,
|
|
W23,
|
|
W24,
|
|
W25,
|
|
W26,
|
|
W27,
|
|
W28,
|
|
W29,
|
|
W30,
|
|
X0,
|
|
X1,
|
|
X2,
|
|
X3,
|
|
X4,
|
|
X5,
|
|
X6,
|
|
X7,
|
|
X8,
|
|
X9,
|
|
X10,
|
|
X11,
|
|
X12,
|
|
X13,
|
|
X14,
|
|
X15,
|
|
X16,
|
|
X17,
|
|
X18,
|
|
X19,
|
|
X20,
|
|
X21,
|
|
X22,
|
|
X23,
|
|
X24,
|
|
X25,
|
|
X26,
|
|
X27,
|
|
X28,
|
|
X29,
|
|
X30,
|
|
S0,
|
|
S1,
|
|
S2,
|
|
S3,
|
|
S4,
|
|
S5,
|
|
S6,
|
|
S7,
|
|
S8,
|
|
S9,
|
|
S10,
|
|
S11,
|
|
S12,
|
|
S13,
|
|
S14,
|
|
S15,
|
|
S16,
|
|
S17,
|
|
S18,
|
|
S19,
|
|
S20,
|
|
S21,
|
|
S22,
|
|
S23,
|
|
S24,
|
|
S25,
|
|
S26,
|
|
S27,
|
|
S28,
|
|
S29,
|
|
S30,
|
|
S31,
|
|
XZR,
|
|
SP,
|
|
WZR
|
|
};
|
|
|
|
const char *PhysRegName(PhysReg reg);
|
|
|
|
enum class VRegClass
|
|
{
|
|
Int,
|
|
Float,
|
|
Ptr
|
|
};
|
|
|
|
enum class Opcode
|
|
{
|
|
Prologue,
|
|
Epilogue,
|
|
MovImm,
|
|
LoadStack,
|
|
StoreStack,
|
|
LoadStackAddr,
|
|
LoadGlobal,
|
|
StoreGlobal,
|
|
LoadGlobalAddr,
|
|
LoadMem,
|
|
StoreMem,
|
|
AddRR,
|
|
SubRR,
|
|
MulRR,
|
|
DivRR,
|
|
ModRR,
|
|
AndRR,
|
|
OrRR,
|
|
XorRR,
|
|
ShlRR,
|
|
ShrRR,
|
|
AsrRR,
|
|
Asr64RR,
|
|
Uxtw,
|
|
Sxtw,
|
|
CmpRR,
|
|
CmpImm,
|
|
FCmpRR,
|
|
CSet,
|
|
Csel,
|
|
Smull,
|
|
Msub,
|
|
NegRR,
|
|
FAddRR,
|
|
FSubRR,
|
|
FMulRR,
|
|
FDivRR,
|
|
Scvtf,
|
|
FCvtzs,
|
|
FMovWS,
|
|
Br,
|
|
CondBr,
|
|
Call,
|
|
Ret,
|
|
LoadAddr,
|
|
MovReg,
|
|
};
|
|
|
|
enum class CondCode
|
|
{
|
|
EQ,
|
|
NE,
|
|
LT,
|
|
LE,
|
|
GT,
|
|
GE
|
|
};
|
|
|
|
class Operand
|
|
{
|
|
public:
|
|
enum class Kind
|
|
{
|
|
Reg,
|
|
VReg,
|
|
Imm,
|
|
FrameIndex,
|
|
Label,
|
|
Symbol
|
|
};
|
|
|
|
static Operand Reg(PhysReg reg);
|
|
static Operand VReg(int id, VRegClass vreg_class);
|
|
static Operand Imm(int value);
|
|
static Operand FrameIndex(int index);
|
|
static Operand Label(int label_id);
|
|
static Operand Symbol(std::string symbol);
|
|
|
|
Kind GetKind() const { return kind_; }
|
|
PhysReg GetReg() const { return reg_; }
|
|
int GetImm() const { return imm_; }
|
|
int GetFrameIndex() const { return imm_; }
|
|
int GetLabel() const { return imm_; }
|
|
const std::string &GetSymbol() const { return symbol_; }
|
|
int GetVRegId() const { return imm_; }
|
|
VRegClass GetVRegClass() const { return vreg_class_; }
|
|
|
|
private:
|
|
Operand(Kind kind, PhysReg reg, int imm,
|
|
VRegClass vreg_class = VRegClass::Int, std::string symbol = "");
|
|
|
|
Kind kind_;
|
|
PhysReg reg_;
|
|
int imm_;
|
|
std::string symbol_;
|
|
VRegClass vreg_class_;
|
|
};
|
|
|
|
class MachineInstr
|
|
{
|
|
public:
|
|
MachineInstr(Opcode opcode, std::vector<Operand> operands = {});
|
|
|
|
Opcode GetOpcode() const { return opcode_; }
|
|
const std::vector<Operand> &GetOperands() const { return operands_; }
|
|
std::vector<Operand> &GetOperands() { return operands_; }
|
|
|
|
private:
|
|
Opcode opcode_;
|
|
std::vector<Operand> operands_;
|
|
};
|
|
|
|
struct FrameSlot
|
|
{
|
|
int index = 0;
|
|
int size = 4;
|
|
int offset = 0;
|
|
bool is_stack_arg = false;
|
|
bool is_callee_stack_arg = false;
|
|
};
|
|
|
|
class MachineBasicBlock
|
|
{
|
|
public:
|
|
explicit MachineBasicBlock(std::string name, int label_id = -1);
|
|
|
|
const std::string &GetName() const { return name_; }
|
|
int GetLabelId() const { return label_id_; }
|
|
void SetLabelId(int label_id) { label_id_ = label_id; }
|
|
|
|
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_;
|
|
int label_id_ = -1;
|
|
std::vector<MachineInstr> instructions_;
|
|
};
|
|
|
|
class MachineFunction
|
|
{
|
|
public:
|
|
explicit MachineFunction(std::string name);
|
|
|
|
const std::string &GetName() const { return name_; }
|
|
|
|
MachineBasicBlock &GetEntry() { return *entry_; }
|
|
const MachineBasicBlock &GetEntry() const { return *entry_; }
|
|
|
|
MachineBasicBlock *GetEntryPtr() { return entry_; }
|
|
const MachineBasicBlock *GetEntryPtr() const { return entry_; }
|
|
|
|
MachineBasicBlock &CreateBlock(std::string name);
|
|
MachineBasicBlock *FindBlock(const std::string &name);
|
|
const MachineBasicBlock *FindBlock(const std::string &name) const;
|
|
|
|
std::vector<std::unique_ptr<MachineBasicBlock>> &GetBlocks()
|
|
{
|
|
return blocks_;
|
|
}
|
|
const std::vector<std::unique_ptr<MachineBasicBlock>> &GetBlocks() const
|
|
{
|
|
return blocks_;
|
|
}
|
|
|
|
int CreateLabel();
|
|
|
|
int CreateFrameIndex(int size = 4);
|
|
int CreateStackArgFrameIndex(int size = 4);
|
|
int CreateCalleeStackArgFrameIndex(int size = 4);
|
|
FrameSlot &GetFrameSlot(int index);
|
|
const FrameSlot &GetFrameSlot(int index) const;
|
|
const std::vector<FrameSlot> &GetFrameSlots() const { return frame_slots_; }
|
|
std::vector<FrameSlot> &GetFrameSlots() { return frame_slots_; }
|
|
|
|
int GetFrameSize() const { return frame_size_; }
|
|
void SetFrameSize(int size) { frame_size_ = size; }
|
|
|
|
int CreateVReg(VRegClass vreg_class);
|
|
VRegClass GetVRegClass(int vreg_id) const;
|
|
int GetNumVRegs() const { return static_cast<int>(vreg_classes_.size()); }
|
|
|
|
void AddCalleeSavedReg(PhysReg reg);
|
|
const std::vector<PhysReg> &GetCalleeSavedRegs() const { return callee_saved_regs_; }
|
|
|
|
private:
|
|
std::string name_;
|
|
std::vector<std::unique_ptr<MachineBasicBlock>> blocks_;
|
|
MachineBasicBlock *entry_ = nullptr;
|
|
|
|
std::vector<FrameSlot> frame_slots_;
|
|
int frame_size_ = 0;
|
|
int next_label_id_ = 0;
|
|
|
|
std::vector<VRegClass> vreg_classes_;
|
|
std::vector<PhysReg> callee_saved_regs_;
|
|
};
|
|
|
|
struct MachineGlobal
|
|
{
|
|
enum class Kind
|
|
{
|
|
I32Scalar,
|
|
I32Array
|
|
};
|
|
|
|
std::string name;
|
|
Kind kind = Kind::I32Scalar;
|
|
int init_value = 0;
|
|
size_t array_size = 0;
|
|
std::vector<int> init_values;
|
|
};
|
|
|
|
class MachineModule
|
|
{
|
|
public:
|
|
MachineModule() = default;
|
|
|
|
MachineFunction &CreateFunction(std::string name);
|
|
MachineFunction *GetFunction(const std::string &name);
|
|
const MachineFunction *GetFunction(const std::string &name) const;
|
|
|
|
std::vector<std::unique_ptr<MachineFunction>> &GetFunctions()
|
|
{
|
|
return functions_;
|
|
}
|
|
const std::vector<std::unique_ptr<MachineFunction>> &GetFunctions() const
|
|
{
|
|
return functions_;
|
|
}
|
|
|
|
void AddGlobalI32(std::string name, int init_value)
|
|
{
|
|
MachineGlobal g;
|
|
g.name = std::move(name);
|
|
g.kind = MachineGlobal::Kind::I32Scalar;
|
|
g.init_value = init_value;
|
|
globals_.push_back(std::move(g));
|
|
}
|
|
|
|
void AddGlobalArrayI32(std::string name, size_t array_size,
|
|
std::vector<int> init_values = {})
|
|
{
|
|
MachineGlobal g;
|
|
g.name = std::move(name);
|
|
g.kind = MachineGlobal::Kind::I32Array;
|
|
g.array_size = array_size;
|
|
g.init_values = std::move(init_values);
|
|
globals_.push_back(std::move(g));
|
|
}
|
|
|
|
std::vector<MachineGlobal> &GetGlobals() { return globals_; }
|
|
const std::vector<MachineGlobal> &GetGlobals() const { return globals_; }
|
|
|
|
private:
|
|
std::vector<std::unique_ptr<MachineFunction>> functions_;
|
|
std::vector<MachineGlobal> globals_;
|
|
};
|
|
|
|
std::unique_ptr<MachineModule> LowerModuleToMIR(const ir::Module &module);
|
|
std::unique_ptr<MachineFunction> LowerToMIR(const ir::Module &module);
|
|
|
|
void RunRegAlloc(MachineFunction &function);
|
|
void RunRegAlloc(MachineModule &module);
|
|
|
|
void RunFrameLowering(MachineFunction &function);
|
|
void RunFrameLowering(MachineModule &module);
|
|
|
|
void RunPeephole(MachineFunction &function);
|
|
void RunPeephole(MachineModule &module);
|
|
|
|
void PrintAsm(const MachineFunction &function, std::ostream &os);
|
|
void PrintAsm(const MachineModule &module, std::ostream &os);
|
|
|
|
} // namespace mir
|