#ifndef INSTRUCTIONH #define INSTRUCTIONH #include "ir.h" #include "riscv.h" #include "regalloc.h" // 语句块,也使用标号标识 // 必须挂靠在函数下,否则无法正常生成标号 // 可以考虑转化到riscv basic block做数据流分析,预留接口 class RiscvBasicBlock : public RiscvLabel { public: RiscvFunction *func_; std::vector instruction; int blockInd_; // 表示了各个block之间的顺序 RiscvBasicBlock(std::string name, RiscvFunction *func, int blockInd) : RiscvLabel(Block, name), func_(func), blockInd_(blockInd) { func->addBlock(this); } RiscvBasicBlock(std::string name, int blockInd) : RiscvLabel(Block, name), func_(nullptr), blockInd_(blockInd) {} void addFunction(RiscvFunction *func) { func->addBlock(this); } std::string printname() { return name_; } // void addOutBlock(RiscvBasicBlock *bb) { inB.push_back(bb); } // void addInBlock(RiscvBasicBlock *bb) { outB.push_back(bb); } void deleteInstr(RiscvInstr *instr) { auto it = std::find(instruction.begin(), instruction.end(), instr); if (it != instruction.end()) instruction.erase( std::remove(instruction.begin(), instruction.end(), instr), instruction.end()); } void replaceInstr(RiscvInstr *oldinst, RiscvInstr *newinst) {} // 在全部指令后面加入 void addInstrBack(RiscvInstr *instr) { if (instr == nullptr) return; instruction.push_back(instr); } // 在全部指令之前加入 void addInstrFront(RiscvInstr *instr) { if (instr == nullptr) return; instruction.insert(instruction.begin(), instr); } void addInstrBefore(RiscvInstr *instr, RiscvInstr *dst) { if (instr == nullptr) return; auto it = std::find(instruction.begin(), instruction.end(), dst); if (it != instruction.end()) instruction.insert(it, instr); else addInstrBack(instr); } void addInstrAfter(RiscvInstr *instr, RiscvInstr *dst) { if (instr == nullptr) return; auto it = std::find(instruction.begin(), instruction.end(), dst); if (it != instruction.end()) { if (next(it) == instruction.end()) instruction.push_back(instr); else instruction.insert(next(it), instr); } else { addInstrBack(instr); } } std::string print(); }; // 传入寄存器编号以生成一条语句, // 上层由basic block整合 class RiscvInstr { public: // 指令类型,除分支语句外,其他对应到riscv // 加立即数或者浮点加需要做区分 enum InstrType { ADD = 0, ADDI, SUB, SUBI, MUL, DIV = 6, REM, FADD = 8, FSUB = 10, FMUL = 12, FDIV = 14, XOR = 16, XORI, AND, ANDI, OR, ORI, SW, LW, FSW = 30, FLW, ICMP, FCMP, PUSH, POP, CALL, RET, LI, MOV, FMV, FPTOSI, SITOFP, JMP, SHL, LSHR, ASHR, SHLI = 52, LSHRI, ASHRI, LA, ADDIW, BGT }; const static std::map RiscvName; InstrType type_; RiscvBasicBlock *parent_; std::vector operand_; RiscvInstr(InstrType type, int op_nums); RiscvInstr(InstrType type, int op_nums, RiscvBasicBlock *bb); ~RiscvInstr() = default; virtual std::string print() = 0; RiscvOperand *result_; void setOperand(int ind, RiscvOperand *val) { assert(ind >= 0 && ind < operand_.size()); operand_[ind] = val; } void setResult(RiscvOperand *result) { result_ = result; } void removeResult() { result_ = nullptr; } // 消除一个操作数 void removeOperand(int i) { operand_[i] = nullptr; } // 清除指令 void clear() { operand_.clear(), removeResult(); } // 先操作数后返回值 std::vector getOperandResult() { std::vector ans(operand_); if (result_ != nullptr) ans.push_back(result_); return ans; } RiscvOperand *getOperand(int i) const { return operand_[i]; } }; // 二元指令 class BinaryRiscvInst : public RiscvInstr { public: std::string print() override; BinaryRiscvInst() = default; // target = v1 op v2,后面接一个flag参数表示要不要加入到对应的basic block中 BinaryRiscvInst(InstrType op, RiscvOperand *v1, RiscvOperand *v2, RiscvOperand *target, RiscvBasicBlock *bb, bool flag = 0) : RiscvInstr(op, 2, bb), word(flag) { setOperand(0, v1); setOperand(1, v2); setResult(target); this->parent_ = bb; // Optimize: 若立即数为0,则改用寄存器zero。 if(v2->getType() == v2->IntImm && static_cast(v2)->intval == 0){ type_ = ADD; setOperand(1, getRegOperand("zero")); } } bool word; }; // 一元指令 class UnaryRiscvInst : public RiscvInstr { public: std::string print() override; UnaryRiscvInst() = default; // target = op v1,后面接一个flag参数表示要不要加入到对应的basic block中 UnaryRiscvInst(InstrType op, RiscvOperand *v1, RiscvOperand *target, RiscvBasicBlock *bb, bool flag = 0) : RiscvInstr(op, 1, bb) { setOperand(0, v1); setResult(target); this->parent_ = bb; if (flag) this->parent_->addInstrBack(this); } }; // 加入一个整型mov指令(LI) class MoveRiscvInst : public RiscvInstr { public: std::string print() override; MoveRiscvInst() = default; MoveRiscvInst(RiscvOperand *v1, int Imm, RiscvBasicBlock *bb, bool flag = 0) : RiscvInstr(InstrType::LI, 2, bb) { RiscvOperand *Const = new RiscvConst(Imm); setOperand(0, v1); setOperand(1, Const); this->parent_ = bb; if (flag) this->parent_->addInstrBack(this); } // v2->v1 MoveRiscvInst(RiscvOperand *v1, RiscvOperand *v2, RiscvBasicBlock *bb, bool flag = 0) : RiscvInstr(InstrType::MOV, 2, bb) { setOperand(0, v1); setOperand(1, v2); this->parent_ = bb; if (flag) this->parent_->addInstrBack(this); } }; // 注意压栈顺序问题!打印的时候严格按照lists内顺序 class PushRiscvInst : public RiscvInstr { int basicShift_; public: PushRiscvInst(std::vector &lists, RiscvBasicBlock *bb, int basicShift) : RiscvInstr(InstrType::PUSH, lists.size(), bb), basicShift_(basicShift) { for (int i = 0; i < lists.size(); i++) setOperand(i, lists[i]); } std::string print() override; }; // 打印的时候严格按照lists内顺序 class PopRiscvInst : public RiscvInstr { int basicShift_; public: // 传入所有要pop的变量 PopRiscvInst(std::vector &lists, RiscvBasicBlock *bb, int basicShift) : RiscvInstr(InstrType::POP, lists.size(), bb), basicShift_(basicShift) { for (int i = 0; i < lists.size(); i++) setOperand(i, lists[i]); } std::string print() override; }; // call调用语句+压栈语句 // 0作为函数名,1-n是函数各参数 class CallRiscvInst : public RiscvInstr { public: CallRiscvInst(RiscvFunction *func, RiscvBasicBlock *bb) : RiscvInstr(InstrType::CALL, 1, bb) { setOperand(0, func); } virtual std::string print() override; }; // 仅返回语句,返回参数由上层的block对应的function构造push语句和lw sw指令 class ReturnRiscvInst : public RiscvInstr { public: ReturnRiscvInst(RiscvBasicBlock *bb) : RiscvInstr(InstrType::RET, 0, bb) {} std::string print() override; }; // Store 指令格式:sw source_value(reg), shift(base reg) // 目的:source_value->M[base reg + shift] // 传入源寄存器,目的寄存器和偏移地址(默认为0) // 如果是直接寻址,则base填x0号寄存器 class StoreRiscvInst : public RiscvInstr { public: int shift_; // 地址偏移量 Type type; // 到底是浮点还是整型 StoreRiscvInst(Type *ty, RiscvOperand *source, RiscvOperand *target, RiscvBasicBlock *bb, int shift = 0) : RiscvInstr(InstrType::SW, 2, bb), shift_(shift), type(ty->tid_) { setOperand(0, source); setOperand(1, target); this->parent_ = bb; if (source->isRegister() == false) { std::cerr << "[Fatal error] Invalid store instruction: " << print() << std::endl; std::terminate(); } } std::string print() override; }; // 指令传入格式同store // 先dest 后base reg // 目的:M[base reg + shift]->dest reg // 需指明是浮点还是整型 class LoadRiscvInst : public RiscvInstr { public: int shift_; // 地址偏移量 Type type; // 到底是浮点还是整型 LoadRiscvInst(Type *ty, RiscvOperand *dest, RiscvOperand *target, RiscvBasicBlock *bb, int shift = 0) : RiscvInstr(InstrType::LW, 2, bb), shift_(shift), type(ty->tid_) { setOperand(0, dest); setOperand(1, target); if (target == nullptr) { std::cerr << "[Fatal Error] Load Instruction's target is nullptr." << std::endl; std::terminate(); } this->parent_ = bb; } std::string print() override; }; // 整型比较 // 类型:cmpop val1, val2, true_link // 传入参数:val1, val2, true_link, false_link(basic block指针形式) // false_link如果为为下一条语句则不会发射j false_link指令 class ICmpRiscvInstr : public RiscvInstr { public: static const std::map ICmpOpName; static const std::map ICmpOpSName; static const std::map ICmpOpEquiv; ICmpRiscvInstr(ICmpInst::ICmpOp op, RiscvOperand *v1, RiscvOperand *v2, RiscvBasicBlock *trueLink, RiscvBasicBlock *falseLink, RiscvBasicBlock *bb) : RiscvInstr(ICMP, 4, bb), icmp_op_(op) { setOperand(0, v1); setOperand(1, v2); setOperand(2, trueLink); setOperand(3, falseLink); } ICmpRiscvInstr(ICmpInst::ICmpOp op, RiscvOperand *v1, RiscvOperand *v2, RiscvBasicBlock *trueLink, RiscvBasicBlock *bb) : RiscvInstr(ICMP, 4, bb), icmp_op_(op) { setOperand(0, v1); setOperand(1, v2); setOperand(2, trueLink); setOperand(3, nullptr); } ICmpInst::ICmpOp icmp_op_; std::string print() override; }; class ICmpSRiscvInstr : public ICmpRiscvInstr { public: ICmpSRiscvInstr(ICmpInst::ICmpOp op, RiscvOperand *v1, RiscvOperand *v2, RiscvOperand *target, RiscvBasicBlock *bb) : ICmpRiscvInstr(op, v1, v2, nullptr, bb) { setOperand(0, v1); setOperand(1, v2); setResult(target); } std::string print() override; }; // 浮点比较 // 类型:cmpop val1, val2, true_link, false_link // 假定basic block是顺序排布的,那么如果false_link恰好为下一个basic // block,则不会发射j false_link指令 class FCmpRiscvInstr : public RiscvInstr { public: static const std::map FCmpOpName; static const std::map FCmpOpEquiv; FCmpRiscvInstr(FCmpInst::FCmpOp op, RiscvOperand *v1, RiscvOperand *v2, RiscvOperand *target, RiscvBasicBlock *bb) : RiscvInstr(FCMP, 2, bb), fcmp_op_(op) { setOperand(0, v1); setOperand(1, v2); setResult(target); } FCmpInst::FCmpOp fcmp_op_; std::string print() override; }; class FpToSiRiscvInstr : public RiscvInstr { public: FpToSiRiscvInstr(RiscvOperand *Source, RiscvOperand *Target, RiscvBasicBlock *bb) : RiscvInstr(FPTOSI, 2, bb) { setOperand(0, Source); setOperand(1, Target); } virtual std::string print() override; }; class SiToFpRiscvInstr : public RiscvInstr { public: SiToFpRiscvInstr(RiscvOperand *Source, RiscvOperand *Target, RiscvBasicBlock *bb) : RiscvInstr(SITOFP, 2, bb) { setOperand(0, Source); setOperand(1, Target); } virtual std::string print() override; }; // LA rd, symbol ; x[rd] = &symbol // `dest` : rd // `name` : symbol class LoadAddressRiscvInstr : public RiscvInstr { public: std::string name_; LoadAddressRiscvInstr(RiscvOperand *dest, std::string name, RiscvBasicBlock *bb) : RiscvInstr(LA, 1, bb), name_(name) { setOperand(0, dest); } virtual std::string print() override; }; /** * 分支指令类。 * BEQ rs1, zero, label1 * J label2 */ class BranchRiscvInstr : public RiscvInstr { public: /// @brief 生成分支指令类。 /// @param rs1 存储布尔值的寄存器 /// @param trueLink 真值跳转基本块 /// @param falseLink 假值跳转基本块 BranchRiscvInstr(RiscvOperand *rs1, RiscvBasicBlock *trueLink, RiscvBasicBlock *falseLink, RiscvBasicBlock *bb) : RiscvInstr(BGT, 3, bb) { setOperand(0, rs1); setOperand(1, trueLink); setOperand(2, falseLink); } virtual std::string print() override; }; #endif // !INSTRUCTIONH