Files
nudt-compiler-cpp/include/mir/MIR.h

161 lines
3.7 KiB
C++

#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,
W19, W20, W21, W22, W23, W24, W25, W26, W27, W28,
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15,
X19, X20, X21, X22, X23, X24, X25, X26, X27, X28,
S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15,
X29, X30, SP
};
const char* PhysRegName(PhysReg reg);
enum class Opcode {
Prologue,
Epilogue,
MovImm,
LoadStack,
StoreStack,
AddRR,
SubRR,
MulRR,
SDivRR,
MSubRRRR,
FAddRRR,
FSubRRR,
FMulRRR,
FDivRRR,
CmpRR,
FCmpRR,
Cset,
B,
BCond,
Call,
Ret,
MovReg,
Adrp,
AddRegImm,
LdrRegReg,
StrRegReg,
SIToFP,
FPToSI,
ZExt
};
class Operand {
public:
enum class Kind { Reg, Imm, FrameIndex, Global, Label, Cond };
static Operand Reg(PhysReg reg);
static Operand Imm(int value);
static Operand FrameIndex(int index);
static Operand Global(std::string name);
static Operand Label(std::string name);
static Operand Cond(std::string cond);
Kind GetKind() const { return kind_; }
PhysReg GetReg() const { return reg_; }
int GetImm() const { return imm_; }
int GetFrameIndex() const { return imm_; }
const std::string& GetGlobalName() const { return str_; }
const std::string& GetLabelName() const { return str_; }
const std::string& GetCondCode() const { return str_; }
private:
Operand(Kind kind, PhysReg reg, int imm, std::string str = "");
Kind kind_;
PhysReg reg_;
int imm_;
std::string str_;
};
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& CreateBlock(std::string name);
std::vector<MachineBasicBlock>& GetBlocks() { return blocks_; }
const std::vector<MachineBasicBlock>& GetBlocks() const { return blocks_; }
// Stack/Frame management
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<MachineBasicBlock> blocks_;
std::vector<FrameSlot> frame_slots_;
int frame_size_ = 0;
};
std::vector<std::unique_ptr<MachineFunction>> LowerToMIR(const ir::Module& module);
void RunRegAlloc(MachineFunction& function);
void RunFrameLowering(MachineFunction& function);
void RunPeephole(MachineFunction& function);
void PrintAsm(const MachineFunction& function, std::ostream& os);
void PrintGlobals(const ir::Module& module, std::ostream& os);
} // namespace mir