Index: include/llvm/CodeGen/MachineInstrBuilder.h =================================================================== --- include/llvm/CodeGen/MachineInstrBuilder.h +++ include/llvm/CodeGen/MachineInstrBuilder.h @@ -44,16 +44,32 @@ }; } -class MachineInstrBuilder { +/// Base class for building MachineInstrs. +/// +/// It provides an interface for easily adding operands to a MachineInstr by +/// chaining calls to its add* methods. +/// +/// Targets that have special operands can create a custom builder that inherits +/// from this class and provides itself as the template argument (via the +/// curiously recurring template pattern). This will allow chaining the default +/// add* methods with any addWhateverCustomOperand in the subclass. Overriding +/// the default add* methods in the subclass is currently not supported, but we +/// can revisit that in the future should the need arise. +template class MIBuilderBase { MachineFunction *MF; MachineInstr *MI; + + const Derived &getDerived() const { + return *static_cast(this); + } + public: - MachineInstrBuilder() : MF(nullptr), MI(nullptr) {} + MIBuilderBase() : MF(nullptr), MI(nullptr) {} - /// Create a MachineInstrBuilder for manipulating an existing instruction. + /// Create a MIBuilderBase for manipulating an existing instruction. /// F must be the machine function that was used to allocate I. - MachineInstrBuilder(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {} - MachineInstrBuilder(MachineFunction &F, MachineBasicBlock::iterator I) + MIBuilderBase(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {} + MIBuilderBase(MachineFunction &F, MachineBasicBlock::iterator I) : MF(&F), MI(&*I) {} /// Allow automatic conversion to the machine instruction we are working on. @@ -66,8 +82,8 @@ MachineInstr *getInstr() const { return MI; } /// Add a new virtual register operand. - const MachineInstrBuilder &addReg(unsigned RegNo, unsigned flags = 0, - unsigned SubReg = 0) const { + const Derived &addReg(unsigned RegNo, unsigned flags = 0, + unsigned SubReg = 0) const { assert((flags & 0x1) == 0 && "Passing in 'true' to addReg is forbidden! Use enums instead."); MI->addOperand(*MF, MachineOperand::CreateReg(RegNo, @@ -80,160 +96,156 @@ SubReg, flags & RegState::Debug, flags & RegState::InternalRead)); - return *this; + return getDerived(); } /// Add a virtual register definition operand. - const MachineInstrBuilder &addDef(unsigned RegNo, unsigned Flags = 0, - unsigned SubReg = 0) const { + const Derived &addDef(unsigned RegNo, unsigned Flags = 0, + unsigned SubReg = 0) const { return addReg(RegNo, Flags | RegState::Define, SubReg); } /// Add a virtual register use operand. It is an error for Flags to contain /// `RegState::Define` when calling this function. - const MachineInstrBuilder &addUse(unsigned RegNo, unsigned Flags = 0, - unsigned SubReg = 0) const { + const Derived &addUse(unsigned RegNo, unsigned Flags = 0, + unsigned SubReg = 0) const { assert(!(Flags & RegState::Define) && "Misleading addUse defines register, use addReg instead."); return addReg(RegNo, Flags, SubReg); } /// Add a new immediate operand. - const MachineInstrBuilder &addImm(int64_t Val) const { + const Derived &addImm(int64_t Val) const { MI->addOperand(*MF, MachineOperand::CreateImm(Val)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addCImm(const ConstantInt *Val) const { + const Derived &addCImm(const ConstantInt *Val) const { MI->addOperand(*MF, MachineOperand::CreateCImm(Val)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { + const Derived &addFPImm(const ConstantFP *Val) const { MI->addOperand(*MF, MachineOperand::CreateFPImm(Val)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB, - unsigned char TargetFlags = 0) const { + const Derived &addMBB(MachineBasicBlock *MBB, + unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateMBB(MBB, TargetFlags)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addFrameIndex(int Idx) const { + const Derived &addFrameIndex(int Idx) const { MI->addOperand(*MF, MachineOperand::CreateFI(Idx)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addConstantPoolIndex(unsigned Idx, - int Offset = 0, - unsigned char TargetFlags = 0) const { + const Derived &addConstantPoolIndex(unsigned Idx, int Offset = 0, + unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateCPI(Idx, Offset, TargetFlags)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addTargetIndex(unsigned Idx, int64_t Offset = 0, - unsigned char TargetFlags = 0) const { + const Derived &addTargetIndex(unsigned Idx, int64_t Offset = 0, + unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateTargetIndex(Idx, Offset, TargetFlags)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addJumpTableIndex(unsigned Idx, - unsigned char TargetFlags = 0) const { + const Derived &addJumpTableIndex(unsigned Idx, + unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateJTI(Idx, TargetFlags)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addGlobalAddress(const GlobalValue *GV, - int64_t Offset = 0, - unsigned char TargetFlags = 0) const { + const Derived &addGlobalAddress(const GlobalValue *GV, int64_t Offset = 0, + unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateGA(GV, Offset, TargetFlags)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addExternalSymbol(const char *FnName, - unsigned char TargetFlags = 0) const { + const Derived &addExternalSymbol(const char *FnName, + unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateES(FnName, TargetFlags)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addBlockAddress(const BlockAddress *BA, - int64_t Offset = 0, - unsigned char TargetFlags = 0) const { + const Derived &addBlockAddress(const BlockAddress *BA, int64_t Offset = 0, + unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateBA(BA, Offset, TargetFlags)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addRegMask(const uint32_t *Mask) const { + const Derived &addRegMask(const uint32_t *Mask) const { MI->addOperand(*MF, MachineOperand::CreateRegMask(Mask)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { + const Derived &addMemOperand(MachineMemOperand *MMO) const { MI->addMemOperand(*MF, MMO); - return *this; + return getDerived(); } - const MachineInstrBuilder &setMemRefs(MachineInstr::mmo_iterator b, - MachineInstr::mmo_iterator e) const { + const Derived &setMemRefs(MachineInstr::mmo_iterator b, + MachineInstr::mmo_iterator e) const { MI->setMemRefs(b, e); - return *this; + return getDerived(); } - const MachineInstrBuilder &setMemRefs(std::pair MemOperandsRef) const { + const Derived &setMemRefs( + std::pair MemOperandsRef) const { MI->setMemRefs(MemOperandsRef); - return *this; + return getDerived(); } - const MachineInstrBuilder &addOperand(const MachineOperand &MO) const { + const Derived &addOperand(const MachineOperand &MO) const { MI->addOperand(*MF, MO); - return *this; + return getDerived(); } - const MachineInstrBuilder &addMetadata(const MDNode *MD) const { + const Derived &addMetadata(const MDNode *MD) const { MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); assert((MI->isDebugValue() ? static_cast(MI->getDebugVariable()) : true) && "first MDNode argument of a DBG_VALUE not a variable"); - return *this; + return getDerived(); } - const MachineInstrBuilder &addCFIIndex(unsigned CFIIndex) const { + const Derived &addCFIIndex(unsigned CFIIndex) const { MI->addOperand(*MF, MachineOperand::CreateCFIIndex(CFIIndex)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addIntrinsicID(Intrinsic::ID ID) const { + const Derived &addIntrinsicID(Intrinsic::ID ID) const { MI->addOperand(*MF, MachineOperand::CreateIntrinsicID(ID)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addPredicate(CmpInst::Predicate Pred) const { + const Derived &addPredicate(CmpInst::Predicate Pred) const { MI->addOperand(*MF, MachineOperand::CreatePredicate(Pred)); - return *this; + return getDerived(); } - const MachineInstrBuilder &addSym(MCSymbol *Sym, - unsigned char TargetFlags = 0) const { + const Derived &addSym(MCSymbol *Sym, unsigned char TargetFlags = 0) const { MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags)); - return *this; + return getDerived(); } - const MachineInstrBuilder &setMIFlags(unsigned Flags) const { + const Derived &setMIFlags(unsigned Flags) const { MI->setFlags(Flags); - return *this; + return getDerived(); } - const MachineInstrBuilder &setMIFlag(MachineInstr::MIFlag Flag) const { + const Derived &setMIFlag(MachineInstr::MIFlag Flag) const { MI->setFlag(Flag); - return *this; + return getDerived(); } // Add a displacement from an existing MachineOperand with an added offset. - const MachineInstrBuilder &addDisp(const MachineOperand &Disp, int64_t off, - unsigned char TargetFlags = 0) const { + const Derived &addDisp(const MachineOperand &Disp, int64_t off, + unsigned char TargetFlags = 0) const { // If caller specifies new TargetFlags then use it, otherwise the // default behavior is to copy the target flags from the existing // MachineOperand. This means if the caller wants to clear the @@ -256,13 +268,18 @@ } /// Copy all the implicit operands from OtherMI onto this one. - const MachineInstrBuilder & - copyImplicitOps(const MachineInstr &OtherMI) const { + const Derived ©ImplicitOps(const MachineInstr &OtherMI) const { MI->copyImplicitOps(*MF, OtherMI); - return *this; + return getDerived(); } }; +/// Default class for building MachineInstrs. Use this if your target does not +/// provide a more specialized Builder. +class MachineInstrBuilder : public MIBuilderBase { + using MIBuilderBase::MIBuilderBase; +}; + /// Builder interface. Specify how to create the initial instruction itself. inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID) {