#ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H
#define LLVM_CODEGEN_MACHINEINSTRBUILDER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <cstdint>
namespace llvm {
class MCInstrDesc;
class MDNode;
namespace RegState {
enum {
Define = 0x2,
Implicit = 0x4,
Kill = 0x8,
Dead = 0x10,
Undef = 0x20,
EarlyClobber = 0x40,
Debug = 0x80,
InternalRead = 0x100,
Renamable = 0x200,
DefineNoRead = Define | Undef,
ImplicitDefine = Implicit | Define,
ImplicitKill = Implicit | Kill
};
}
class MachineInstrBuilder {
MachineFunction *MF = nullptr;
MachineInstr *MI = nullptr;
public:
MachineInstrBuilder() = default;
MachineInstrBuilder(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {}
MachineInstrBuilder(MachineFunction &F, MachineBasicBlock::iterator I)
: MF(&F), MI(&*I) {}
operator MachineInstr*() const { return MI; }
MachineInstr *operator->() const { return MI; }
operator MachineBasicBlock::iterator() const { return MI; }
MachineInstr *getInstr() const { return MI; }
Register getReg(unsigned Idx) const { return MI->getOperand(Idx).getReg(); }
const MachineInstrBuilder &addReg(Register 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,
flags & RegState::Define,
flags & RegState::Implicit,
flags & RegState::Kill,
flags & RegState::Dead,
flags & RegState::Undef,
flags & RegState::EarlyClobber,
SubReg,
flags & RegState::Debug,
flags & RegState::InternalRead,
flags & RegState::Renamable));
return *this;
}
const MachineInstrBuilder &addDef(Register RegNo, unsigned Flags = 0,
unsigned SubReg = 0) const {
return addReg(RegNo, Flags | RegState::Define, SubReg);
}
const MachineInstrBuilder &addUse(Register RegNo, unsigned Flags = 0,
unsigned SubReg = 0) const {
assert(!(Flags & RegState::Define) &&
"Misleading addUse defines register, use addReg instead.");
return addReg(RegNo, Flags, SubReg);
}
const MachineInstrBuilder &addImm(int64_t Val) const {
MI->addOperand(*MF, MachineOperand::CreateImm(Val));
return *this;
}
const MachineInstrBuilder &addCImm(const ConstantInt *Val) const {
MI->addOperand(*MF, MachineOperand::CreateCImm(Val));
return *this;
}
const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const {
MI->addOperand(*MF, MachineOperand::CreateFPImm(Val));
return *this;
}
const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB,
unsigned TargetFlags = 0) const {
MI->addOperand(*MF, MachineOperand::CreateMBB(MBB, TargetFlags));
return *this;
}
const MachineInstrBuilder &addFrameIndex(int Idx) const {
MI->addOperand(*MF, MachineOperand::CreateFI(Idx));
return *this;
}
const MachineInstrBuilder &
addConstantPoolIndex(unsigned Idx, int Offset = 0,
unsigned TargetFlags = 0) const {
MI->addOperand(*MF, MachineOperand::CreateCPI(Idx, Offset, TargetFlags));
return *this;
}
const MachineInstrBuilder &addTargetIndex(unsigned Idx, int64_t Offset = 0,
unsigned TargetFlags = 0) const {
MI->addOperand(*MF, MachineOperand::CreateTargetIndex(Idx, Offset,
TargetFlags));
return *this;
}
const MachineInstrBuilder &addJumpTableIndex(unsigned Idx,
unsigned TargetFlags = 0) const {
MI->addOperand(*MF, MachineOperand::CreateJTI(Idx, TargetFlags));
return *this;
}
const MachineInstrBuilder &addGlobalAddress(const GlobalValue *GV,
int64_t Offset = 0,
unsigned TargetFlags = 0) const {
MI->addOperand(*MF, MachineOperand::CreateGA(GV, Offset, TargetFlags));
return *this;
}
const MachineInstrBuilder &addExternalSymbol(const char *FnName,
unsigned TargetFlags = 0) const {
MI->addOperand(*MF, MachineOperand::CreateES(FnName, TargetFlags));
return *this;
}
const MachineInstrBuilder &addBlockAddress(const BlockAddress *BA,
int64_t Offset = 0,
unsigned TargetFlags = 0) const {
MI->addOperand(*MF, MachineOperand::CreateBA(BA, Offset, TargetFlags));
return *this;
}
const MachineInstrBuilder &addRegMask(const uint32_t *Mask) const {
MI->addOperand(*MF, MachineOperand::CreateRegMask(Mask));
return *this;
}
const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const {
MI->addMemOperand(*MF, MMO);
return *this;
}
const MachineInstrBuilder &
setMemRefs(ArrayRef<MachineMemOperand *> MMOs) const {
MI->setMemRefs(*MF, MMOs);
return *this;
}
const MachineInstrBuilder &cloneMemRefs(const MachineInstr &OtherMI) const {
MI->cloneMemRefs(*MF, OtherMI);
return *this;
}
const MachineInstrBuilder &
cloneMergedMemRefs(ArrayRef<const MachineInstr *> OtherMIs) const {
MI->cloneMergedMemRefs(*MF, OtherMIs);
return *this;
}
const MachineInstrBuilder &add(const MachineOperand &MO) const {
MI->addOperand(*MF, MO);
return *this;
}
const MachineInstrBuilder &add(ArrayRef<MachineOperand> MOs) const {
for (const MachineOperand &MO : MOs) {
MI->addOperand(*MF, MO);
}
return *this;
}
const MachineInstrBuilder &addMetadata(const MDNode *MD) const {
MI->addOperand(*MF, MachineOperand::CreateMetadata(MD));
assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable())
: true) &&
"first MDNode argument of a DBG_VALUE not a variable");
assert((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel())
: true) &&
"first MDNode argument of a DBG_LABEL not a label");
return *this;
}
const MachineInstrBuilder &addCFIIndex(unsigned CFIIndex) const {
MI->addOperand(*MF, MachineOperand::CreateCFIIndex(CFIIndex));
return *this;
}
const MachineInstrBuilder &addIntrinsicID(Intrinsic::ID ID) const {
MI->addOperand(*MF, MachineOperand::CreateIntrinsicID(ID));
return *this;
}
const MachineInstrBuilder &addPredicate(CmpInst::Predicate Pred) const {
MI->addOperand(*MF, MachineOperand::CreatePredicate(Pred));
return *this;
}
const MachineInstrBuilder &addShuffleMask(ArrayRef<int> Val) const {
MI->addOperand(*MF, MachineOperand::CreateShuffleMask(Val));
return *this;
}
const MachineInstrBuilder &addSym(MCSymbol *Sym,
unsigned char TargetFlags = 0) const {
MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags));
return *this;
}
const MachineInstrBuilder &setMIFlags(unsigned Flags) const {
MI->setFlags(Flags);
return *this;
}
const MachineInstrBuilder &setMIFlag(MachineInstr::MIFlag Flag) const {
MI->setFlag(Flag);
return *this;
}
const MachineInstrBuilder &addDisp(const MachineOperand &Disp, int64_t off,
unsigned char TargetFlags = 0) const {
if (0 == TargetFlags)
TargetFlags = Disp.getTargetFlags();
switch (Disp.getType()) {
default:
llvm_unreachable("Unhandled operand type in addDisp()");
case MachineOperand::MO_Immediate:
return addImm(Disp.getImm() + off);
case MachineOperand::MO_ConstantPoolIndex:
return addConstantPoolIndex(Disp.getIndex(), Disp.getOffset() + off,
TargetFlags);
case MachineOperand::MO_GlobalAddress:
return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off,
TargetFlags);
case MachineOperand::MO_BlockAddress:
return addBlockAddress(Disp.getBlockAddress(), Disp.getOffset() + off,
TargetFlags);
case MachineOperand::MO_JumpTableIndex:
assert(off == 0 && "cannot create offset into jump tables");
return addJumpTableIndex(Disp.getIndex(), TargetFlags);
}
}
const MachineInstrBuilder &
copyImplicitOps(const MachineInstr &OtherMI) const {
MI->copyImplicitOps(*MF, OtherMI);
return *this;
}
bool constrainAllUses(const TargetInstrInfo &TII,
const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI) const {
return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
}
};
inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID) {
return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL));
}
inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID, Register DestReg) {
return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL))
.addReg(DestReg, RegState::Define);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
const DebugLoc &DL, const MCInstrDesc &MCID,
Register DestReg) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
BB.insert(I, MI);
return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::instr_iterator I,
const DebugLoc &DL, const MCInstrDesc &MCID,
Register DestReg) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
BB.insert(I, MI);
return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I,
const DebugLoc &DL, const MCInstrDesc &MCID,
Register DestReg) {
if (I.isInsideBundle())
return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID, DestReg);
return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID, DestReg);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I,
const DebugLoc &DL, const MCInstrDesc &MCID,
Register DestReg) {
return BuildMI(BB, *I, DL, MCID, DestReg);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
const DebugLoc &DL,
const MCInstrDesc &MCID) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
BB.insert(I, MI);
return MachineInstrBuilder(MF, MI);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::instr_iterator I,
const DebugLoc &DL,
const MCInstrDesc &MCID) {
MachineFunction &MF = *BB.getParent();
MachineInstr *MI = MF.CreateMachineInstr(MCID, DL);
BB.insert(I, MI);
return MachineInstrBuilder(MF, MI);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I,
const DebugLoc &DL,
const MCInstrDesc &MCID) {
if (I.isInsideBundle())
return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID);
return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I,
const DebugLoc &DL,
const MCInstrDesc &MCID) {
return BuildMI(BB, *I, DL, MCID);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL,
const MCInstrDesc &MCID) {
return BuildMI(*BB, BB->end(), DL, MCID);
}
inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL,
const MCInstrDesc &MCID, Register DestReg) {
return BuildMI(*BB, BB->end(), DL, MCID, DestReg);
}
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID, bool IsIndirect,
Register Reg, const MDNode *Variable,
const MDNode *Expr);
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID, bool IsIndirect,
const MachineOperand &MO, const MDNode *Variable,
const MDNode *Expr);
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL,
const MCInstrDesc &MCID, bool IsIndirect,
ArrayRef<MachineOperand> MOs,
const MDNode *Variable, const MDNode *Expr);
MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I, const DebugLoc &DL,
const MCInstrDesc &MCID, bool IsIndirect,
Register Reg, const MDNode *Variable,
const MDNode *Expr);
MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I, const DebugLoc &DL,
const MCInstrDesc &MCID, bool IsIndirect,
MachineOperand &MO, const MDNode *Variable,
const MDNode *Expr);
MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
MachineBasicBlock::iterator I, const DebugLoc &DL,
const MCInstrDesc &MCID, bool IsIndirect,
ArrayRef<MachineOperand> MOs,
const MDNode *Variable, const MDNode *Expr);
MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB,
MachineBasicBlock::iterator I,
const MachineInstr &Orig, int FrameIndex,
Register SpillReg);
MachineInstr *
buildDbgValueForSpill(MachineBasicBlock &BB, MachineBasicBlock::iterator I,
const MachineInstr &Orig, int FrameIndex,
SmallVectorImpl<const MachineOperand *> &SpilledOperands);
void updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex, Register Reg);
inline unsigned getDefRegState(bool B) {
return B ? RegState::Define : 0;
}
inline unsigned getImplRegState(bool B) {
return B ? RegState::Implicit : 0;
}
inline unsigned getKillRegState(bool B) {
return B ? RegState::Kill : 0;
}
inline unsigned getDeadRegState(bool B) {
return B ? RegState::Dead : 0;
}
inline unsigned getUndefRegState(bool B) {
return B ? RegState::Undef : 0;
}
inline unsigned getInternalReadRegState(bool B) {
return B ? RegState::InternalRead : 0;
}
inline unsigned getDebugRegState(bool B) {
return B ? RegState::Debug : 0;
}
inline unsigned getRenamableRegState(bool B) {
return B ? RegState::Renamable : 0;
}
inline unsigned getRegState(const MachineOperand &RegOp) {
assert(RegOp.isReg() && "Not a register operand");
return getDefRegState(RegOp.isDef()) | getImplRegState(RegOp.isImplicit()) |
getKillRegState(RegOp.isKill()) | getDeadRegState(RegOp.isDead()) |
getUndefRegState(RegOp.isUndef()) |
getInternalReadRegState(RegOp.isInternalRead()) |
getDebugRegState(RegOp.isDebug()) |
getRenamableRegState(Register::isPhysicalRegister(RegOp.getReg()) &&
RegOp.isRenamable());
}
class MIBundleBuilder {
MachineBasicBlock &MBB;
MachineBasicBlock::instr_iterator Begin;
MachineBasicBlock::instr_iterator End;
public:
MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator Pos)
: MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {}
MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator B,
MachineBasicBlock::iterator E)
: MBB(BB), Begin(B.getInstrIterator()), End(E.getInstrIterator()) {
assert(B != E && "No instructions to bundle");
++B;
while (B != E) {
MachineInstr &MI = *B;
++B;
MI.bundleWithPred();
}
}
explicit MIBundleBuilder(MachineInstr *MI)
: MBB(*MI->getParent()), Begin(MI),
End(getBundleEnd(MI->getIterator())) {}
MachineBasicBlock &getMBB() const { return MBB; }
bool empty() const { return Begin == End; }
MachineBasicBlock::instr_iterator begin() const { return Begin; }
MachineBasicBlock::instr_iterator end() const { return End; }
MIBundleBuilder &insert(MachineBasicBlock::instr_iterator I,
MachineInstr *MI) {
MBB.insert(I, MI);
if (I == Begin) {
if (!empty())
MI->bundleWithSucc();
Begin = MI->getIterator();
return *this;
}
if (I == End) {
MI->bundleWithPred();
return *this;
}
MI->setFlag(MachineInstr::BundledPred);
MI->setFlag(MachineInstr::BundledSucc);
return *this;
}
MIBundleBuilder &prepend(MachineInstr *MI) {
return insert(begin(), MI);
}
MIBundleBuilder &append(MachineInstr *MI) {
return insert(end(), MI);
}
};
}
#endif