X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=include%2Fllvm%2FCodeGen%2FMachineInstrBuilder.h;h=8fe9b280d5d2dcc4ab83a7dd2df3bbe1debe6a0e;hb=3bd93089a9b944e40edb913871c2a67972ed0af7;hp=c2944c0369630cdcfbf9b1085433a6afdbfa2b4f;hpb=ea50fabfd4e5fad25a25b312f64a9b2a53363586;p=oota-llvm.git diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index c2944c03696..8fe9b280d5d 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -2,19 +2,13 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file exposes a function named BuildMI, which is useful for dramatically -// simplifying how MachineInstr's are created. Instead of using code like this: -// -// M = new MachineInstr(X86::ADDrr8); -// M->SetMachineOperandVal(0, MachineOperand::MO_VirtualRegister, argVal1); -// M->SetMachineOperandVal(1, MachineOperand::MO_VirtualRegister, argVal2); -// -// we can now use code like this: +// simplifying how MachineInstr's are created. It allows use of code like this: // // M = BuildMI(X86::ADDrr8, 2).addReg(argVal1).addReg(argVal2); // @@ -23,157 +17,486 @@ #ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H #define LLVM_CODEGEN_MACHINEINSTRBUILDER_H -#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Support/ErrorHandling.h" 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, + DefineNoRead = Define | Undef, + ImplicitDefine = Implicit | Define, + ImplicitKill = Implicit | Kill + }; +} + class MachineInstrBuilder { + MachineFunction *MF; MachineInstr *MI; public: - MachineInstrBuilder(MachineInstr *mi) : MI(mi) {} + MachineInstrBuilder() : MF(nullptr), MI(nullptr) {} + + /// Create a MachineInstrBuilder 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) {} /// Allow automatic conversion to the machine instruction we are working on. - /// operator MachineInstr*() const { return MI; } + MachineInstr *operator->() const { return MI; } operator MachineBasicBlock::iterator() const { return MI; } - /// addReg - Add a new virtual register operand... - /// - const MachineInstrBuilder &addReg( - int RegNo, - MachineOperand::UseType Ty = MachineOperand::Use) const { - MI->addRegOperand(RegNo, Ty); + /// If conversion operators fail, use this method to get the MachineInstr + /// explicitly. + MachineInstr *getInstr() const { return MI; } + + /// Add a new virtual register operand. + const MachineInstrBuilder &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, + 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)); return *this; } - /// addImm - Add a new immediate operand. - /// - const MachineInstrBuilder &addImm(int Val) const { - MI->addZeroExtImmOperand(Val); + /// Add a new immediate operand. + const MachineInstrBuilder &addImm(int64_t Val) const { + MI->addOperand(*MF, MachineOperand::CreateImm(Val)); return *this; } - /// addSImm - Add a new sign extended immediate operand... - /// - const MachineInstrBuilder &addSImm(int val) const { - MI->addSignExtImmOperand(val); + const MachineInstrBuilder &addCImm(const ConstantInt *Val) const { + MI->addOperand(*MF, MachineOperand::CreateCImm(Val)); return *this; } - /// addZImm - Add a new zero extended immediate operand... - /// - const MachineInstrBuilder &addZImm(unsigned Val) const { - MI->addZeroExtImmOperand(Val); + const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { + MI->addOperand(*MF, MachineOperand::CreateFPImm(Val)); return *this; } - /// addImm64 - Add a new 64-bit immediate operand... - /// - const MachineInstrBuilder &addImm64(uint64_t Val) const { - MI->addZeroExtImm64Operand(Val); + const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB, + unsigned char TargetFlags = 0) const { + MI->addOperand(*MF, MachineOperand::CreateMBB(MBB, TargetFlags)); return *this; } - const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB) const { - MI->addMachineBasicBlockOperand(MBB); + const MachineInstrBuilder &addFrameIndex(int Idx) const { + MI->addOperand(*MF, MachineOperand::CreateFI(Idx)); return *this; } - const MachineInstrBuilder &addFrameIndex(unsigned Idx) const { - MI->addFrameIndexOperand(Idx); + const MachineInstrBuilder &addConstantPoolIndex(unsigned Idx, + int Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(*MF, MachineOperand::CreateCPI(Idx, Offset, TargetFlags)); return *this; } - const MachineInstrBuilder &addConstantPoolIndex(unsigned Idx, - int Offset = 0) const { - MI->addConstantPoolIndexOperand(Idx, Offset); + const MachineInstrBuilder &addTargetIndex(unsigned Idx, int64_t Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(*MF, MachineOperand::CreateTargetIndex(Idx, Offset, + TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addJumpTableIndex(unsigned Idx, + unsigned char TargetFlags = 0) const { + MI->addOperand(*MF, MachineOperand::CreateJTI(Idx, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addGlobalAddress(const GlobalValue *GV, + int64_t Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(*MF, MachineOperand::CreateGA(GV, Offset, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addExternalSymbol(const char *FnName, + unsigned char TargetFlags = 0) const { + MI->addOperand(*MF, MachineOperand::CreateES(FnName, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addBlockAddress(const BlockAddress *BA, + int64_t Offset = 0, + unsigned char 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(MachineInstr::mmo_iterator b, + MachineInstr::mmo_iterator e) const { + MI->setMemRefs(b, e); + return *this; + } + + const MachineInstrBuilder &setMemRefs(std::pair MemOperandsRef) const { + MI->setMemRefs(MemOperandsRef); return *this; } - const MachineInstrBuilder &addJumpTableIndex(unsigned Idx) const { - MI->addJumpTableIndexOperand(Idx); + const MachineInstrBuilder &addOperand(const MachineOperand &MO) const { + MI->addOperand(*MF, MO); return *this; } - const MachineInstrBuilder &addGlobalAddress(GlobalValue *GV, - int Offset = 0) const { - MI->addGlobalAddressOperand(GV, Offset); + const MachineInstrBuilder &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; } - const MachineInstrBuilder &addExternalSymbol(const char *FnName) const{ - MI->addExternalSymbolOperand(FnName); + const MachineInstrBuilder &addCFIIndex(unsigned CFIIndex) const { + MI->addOperand(*MF, MachineOperand::CreateCFIIndex(CFIIndex)); + 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; + } + + // 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 { + // 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 + // target flags it needs to do so explicitly. + 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); + } + } + + /// Copy all the implicit operands from OtherMI onto this one. + const MachineInstrBuilder & + copyImplicitOps(const MachineInstr *OtherMI) const { + MI->copyImplicitOps(*MF, OtherMI); return *this; } }; -/// BuildMI - Builder interface. Specify how to create the initial instruction -/// itself. NumOperands is the number of operands to the machine instruction to -/// allow for memory efficient representation of machine instructions. -/// -inline MachineInstrBuilder BuildMI(int Opcode, unsigned NumOperands) { - return MachineInstrBuilder(new MachineInstr(Opcode, NumOperands, true, true)); +/// Builder interface. Specify how to create the initial instruction itself. +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const MCInstrDesc &MCID) { + return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)); } -/// BuildMI - This version of the builder sets up the first operand as a -/// destination virtual register. NumOperands is the number of additional add* -/// calls that are expected, not including the destination register. -/// -inline MachineInstrBuilder BuildMI( - int Opcode, unsigned NumOperands, - unsigned DestReg, - MachineOperand::UseType useType = MachineOperand::Def) { - return MachineInstrBuilder(new MachineInstr(Opcode, NumOperands+1, - true, true)).addReg(DestReg, useType); -} - -/// BuildMI - This version of the builder inserts the newly-built -/// instruction before the given position in the given MachineBasicBlock, and -/// sets up the first operand as a destination virtual register. -/// NumOperands is the number of additional add* calls that are expected, -/// not including the destination register. -/// +/// This version of the builder sets up the first operand as a +/// destination virtual register. +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const MCInstrDesc &MCID, + unsigned DestReg) { + return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)) + .addReg(DestReg, RegState::Define); +} + +/// This version of the builder inserts the newly-built instruction before +/// the given position in the given MachineBasicBlock, and sets up the first +/// operand as a destination virtual register. inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, - int Opcode, unsigned NumOperands, + DebugLoc DL, + const MCInstrDesc &MCID, unsigned DestReg) { - MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true); + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); BB.insert(I, MI); - return MachineInstrBuilder(MI).addReg(DestReg, MachineOperand::Def); + return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define); } -/// BuildMI - This version of the builder inserts the newly-built -/// instruction before the given position in the given MachineBasicBlock, and -/// does NOT take a destination register. -/// inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - int Opcode, unsigned NumOperands) { - MachineInstr *MI = new MachineInstr(Opcode, NumOperands, true, true); + MachineBasicBlock::instr_iterator I, + DebugLoc DL, + const MCInstrDesc &MCID, + unsigned DestReg) { + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); BB.insert(I, MI); - return MachineInstrBuilder(MI); + return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define); +} + +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineInstr *I, + DebugLoc DL, + const MCInstrDesc &MCID, + unsigned DestReg) { + if (I->isInsideBundle()) { + MachineBasicBlock::instr_iterator MII(I); + return BuildMI(BB, MII, DL, MCID, DestReg); + } + + MachineBasicBlock::iterator MII = I; + return BuildMI(BB, MII, DL, MCID, DestReg); } -/// BuildMI - This version of the builder inserts the newly-built -/// instruction at the end of the given MachineBasicBlock, and does NOT take a +/// This version of the builder inserts the newly-built instruction before the +/// given position in the given MachineBasicBlock, and does NOT take a /// destination register. -/// -inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, int Opcode, - unsigned NumOperands) { - return BuildMI(*BB, BB->end(), Opcode, NumOperands); +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const MCInstrDesc &MCID) { + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); + BB.insert(I, MI); + return MachineInstrBuilder(MF, MI); } -/// BuildMI - This version of the builder inserts the newly-built -/// instruction at the end of the given MachineBasicBlock, and sets up the first -/// operand as a destination virtual register. NumOperands is the number of -/// additional add* calls that are expected, not including the destination -/// register. -/// -inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, int Opcode, - unsigned NumOperands, unsigned DestReg) { - return BuildMI(*BB, BB->end(), Opcode, NumOperands, DestReg); +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::instr_iterator I, + 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, + DebugLoc DL, + const MCInstrDesc &MCID) { + if (I->isInsideBundle()) { + MachineBasicBlock::instr_iterator MII(I); + return BuildMI(BB, MII, DL, MCID); + } + + MachineBasicBlock::iterator MII = I; + return BuildMI(BB, MII, DL, MCID); +} + +/// This version of the builder inserts the newly-built instruction at the end +/// of the given MachineBasicBlock, and does NOT take a destination register. +inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, + DebugLoc DL, + const MCInstrDesc &MCID) { + return BuildMI(*BB, BB->end(), DL, MCID); +} + +/// This version of the builder inserts the newly-built instruction at the +/// end of the given MachineBasicBlock, and sets up the first operand as a +/// destination virtual register. +inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, + DebugLoc DL, + const MCInstrDesc &MCID, + unsigned DestReg) { + return BuildMI(*BB, BB->end(), DL, MCID, DestReg); +} + +/// This version of the builder builds a DBG_VALUE intrinsic +/// for either a value in a register or a register-indirect+offset +/// address. The convention is that a DBG_VALUE is indirect iff the +/// second operand is an immediate. +inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, + const MCInstrDesc &MCID, bool IsIndirect, + unsigned Reg, unsigned Offset, + const MDNode *Variable, const MDNode *Expr) { + assert(isa(Variable) && "not a variable"); + assert(cast(Expr)->isValid() && "not an expression"); + assert(cast(Variable)->isValidLocationForIntrinsic(DL) && + "Expected inlined-at fields to agree"); + if (IsIndirect) + return BuildMI(MF, DL, MCID) + .addReg(Reg, RegState::Debug) + .addImm(Offset) + .addMetadata(Variable) + .addMetadata(Expr); + else { + assert(Offset == 0 && "A direct address cannot have an offset."); + return BuildMI(MF, DL, MCID) + .addReg(Reg, RegState::Debug) + .addReg(0U, RegState::Debug) + .addMetadata(Variable) + .addMetadata(Expr); + } +} + +/// This version of the builder builds a DBG_VALUE intrinsic +/// for either a value in a register or a register-indirect+offset +/// address and inserts it at position I. +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, DebugLoc DL, + const MCInstrDesc &MCID, bool IsIndirect, + unsigned Reg, unsigned Offset, + const MDNode *Variable, const MDNode *Expr) { + assert(isa(Variable) && "not a variable"); + assert(cast(Expr)->isValid() && "not an expression"); + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = + BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr); + BB.insert(I, MI); + return MachineInstrBuilder(MF, MI); } + +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; +} + + +/// Helper class for constructing bundles of MachineInstrs. +/// +/// MIBundleBuilder can create a bundle from scratch by inserting new +/// MachineInstrs one at a time, or it can create a bundle from a sequence of +/// existing MachineInstrs in a basic block. +class MIBundleBuilder { + MachineBasicBlock &MBB; + MachineBasicBlock::instr_iterator Begin; + MachineBasicBlock::instr_iterator End; + +public: + /// Create an MIBundleBuilder that inserts instructions into a new bundle in + /// BB above the bundle or instruction at Pos. + MIBundleBuilder(MachineBasicBlock &BB, + MachineBasicBlock::iterator Pos) + : MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {} + + /// Create a bundle from the sequence of instructions between B and E. + 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(); + } + } + + /// Create an MIBundleBuilder representing an existing instruction or bundle + /// that has MI as its head. + explicit MIBundleBuilder(MachineInstr *MI) + : MBB(*MI->getParent()), Begin(MI), End(getBundleEnd(MI)) {} + + /// Return a reference to the basic block containing this bundle. + MachineBasicBlock &getMBB() const { return MBB; } + + /// Return true if no instructions have been inserted in this bundle yet. + /// Empty bundles aren't representable in a MachineBasicBlock. + bool empty() const { return Begin == End; } + + /// Return an iterator to the first bundled instruction. + MachineBasicBlock::instr_iterator begin() const { return Begin; } + + /// Return an iterator beyond the last bundled instruction. + MachineBasicBlock::instr_iterator end() const { return End; } + + /// Insert MI into this bundle before I which must point to an instruction in + /// the bundle, or 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 was inserted in the middle of the bundle, so its neighbors' flags are + // already fine. Update MI's bundle flags manually. + MI->setFlag(MachineInstr::BundledPred); + MI->setFlag(MachineInstr::BundledSucc); + return *this; + } + + /// Insert MI into MBB by prepending it to the instructions in the bundle. + /// MI will become the first instruction in the bundle. + MIBundleBuilder &prepend(MachineInstr *MI) { + return insert(begin(), MI); + } + + /// Insert MI into MBB by appending it to the instructions in the bundle. + /// MI will become the last instruction in the bundle. + MIBundleBuilder &append(MachineInstr *MI) { + return insert(end(), MI); + } +}; + } // End llvm namespace #endif