X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FCodeGen%2FMachineInstr.h;h=fc886d97f54830e7919067e89d2ea8bb013069f0;hb=6fbcc26f1460eaee4e0eb8b426fc1ff0c7af11be;hp=43dc78dfc55847ce097d37df73d27d974cd0b5aa;hpb=746e0014a6c59f285ffefc30c722ef2cf69eb95d;p=oota-llvm.git diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 43dc78dfc55..fc886d97f54 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -1,30 +1,60 @@ -// $Id$ -*-c++-*- -//*************************************************************************** -// File: -// MachineInstr.h +//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class --------*- C++ -*-===// // -// Purpose: -// -// -// Strategy: +// 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. // -// History: -// 7/2/01 - Vikram Adve - Created -//**************************************************************************/ +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MachineInstr class, which is the +// basic representation for all target dependent machine instructions used by +// the back end. +// +//===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_MACHINEINSTR_H #define LLVM_CODEGEN_MACHINEINSTR_H -#include -#include "llvm/CodeGen/InstrForest.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/NonCopyable.h" -#include "llvm/CodeGen/TargetMachine.h" - -template class ValOpIterator; +#include "llvm/Target/MRegisterInfo.h" +#include "Support/Annotation.h" +#include "Support/iterator" + +class Value; +class Function; +class MachineBasicBlock; +class TargetMachine; +class GlobalValue; + +typedef int MachineOpCode; + +//===----------------------------------------------------------------------===// +/// Special flags on instructions that modify the opcode. +/// These flags are unused for now, but having them enforces that some +/// changes will be needed if they are used. +/// +enum MachineOpCodeFlags { + AnnulFlag, /// 1 if annul bit is set on a branch + PredTakenFlag, /// 1 if branch should be predicted taken + PredNotTakenFlag /// 1 if branch should be predicted not taken +}; +//===----------------------------------------------------------------------===// +/// MOTy - MachineOperandType - This namespace contains an enum that describes +/// how the machine operand is used by the instruction: is it read, defined, or +/// both? Note that the MachineInstr/Operator class currently uses bool +/// arguments to represent this information instead of an enum. Eventually this +/// should change over to use this _easier to read_ representation instead. +/// +namespace MOTy { + enum UseType { + Use, /// This machine operand is only read by the instruction + Def, /// This machine operand is only written by the instruction + UseAndDef /// This machine operand is read AND written + }; +} -//--------------------------------------------------------------------------- +//===----------------------------------------------------------------------===// // class MachineOperand // // Purpose: @@ -57,10 +87,9 @@ template class ValOpIterator; // - Ptr will also be of virtual register type MO_VirtualReg. // Again, the field Value* value identifies the value. // -//--------------------------------------------------------------------------- +//===----------------------------------------------------------------------===// -class MachineOperand { -public: +struct MachineOperand { enum MachineOperandType { MO_VirtualRegister, // virtual register for *value MO_MachineRegister, // pre-assigned machine register `regNum' @@ -68,144 +97,238 @@ public: MO_SignExtendedImmed, MO_UnextendedImmed, MO_PCRelativeDisp, + MO_MachineBasicBlock, // MachineBasicBlock reference + MO_FrameIndex, // Abstract Stack Frame Index + MO_ConstantPoolIndex, // Address of indexed Constant in Constant Pool + MO_ExternalSymbol, // Name of external global symbol + MO_GlobalAddress, // Address of a global value }; private: - MachineOperandType opType; + // Bit fields of the flags variable used for different operand properties + enum { + DEFONLYFLAG = 0x01, // this is a def but not a use of the operand + DEFUSEFLAG = 0x02, // this is both a def and a use + HIFLAG32 = 0x04, // operand is %hi32(value_or_immedVal) + LOFLAG32 = 0x08, // operand is %lo32(value_or_immedVal) + HIFLAG64 = 0x10, // operand is %hi64(value_or_immedVal) + LOFLAG64 = 0x20, // operand is %lo64(value_or_immedVal) + PCRELATIVE = 0x40, // Operand is relative to PC, not a global address + USEDEFMASK = 0x03, + }; + +private: union { Value* value; // BasicBlockVal for a label operand. // ConstantVal for a non-address immediate. // Virtual register for an SSA operand, - // including hidden operands required for - // the generated machine code. - - unsigned int regNum; // register number for an explicit register - - int64_t immedVal; // constant value for an explicit constant + // including hidden operands required for + // the generated machine code. + // LLVM global for MO_GlobalAddress. + + int64_t immedVal; // Constant value for an explicit constant + + MachineBasicBlock *MBB; // For MO_MachineBasicBlock type + std::string *SymbolName; // For MO_ExternalSymbol type }; - bool isDef; // is this a defition for the value - // made public for faster access - + char flags; // see bit field definitions above + MachineOperandType opType:8; // Pack into 8 bits efficiently after flags. + int regNum; // register number for an explicit register + // will be set for a value after reg allocation +private: + MachineOperand() + : immedVal(0), + flags(0), + opType(MO_VirtualRegister), + regNum(-1) {} + + MachineOperand(int64_t ImmVal, MachineOperandType OpTy) + : immedVal(ImmVal), + flags(0), + opType(OpTy), + regNum(-1) {} + + MachineOperand(int Reg, MachineOperandType OpTy, MOTy::UseType UseTy) + : immedVal(0), + opType(OpTy), + regNum(Reg) { + switch (UseTy) { + case MOTy::Use: flags = 0; break; + case MOTy::Def: flags = DEFONLYFLAG; break; + case MOTy::UseAndDef: flags = DEFUSEFLAG; break; + default: assert(0 && "Invalid value for UseTy!"); + } + } + + MachineOperand(Value *V, MachineOperandType OpTy, MOTy::UseType UseTy, + bool isPCRelative = false) + : value(V), opType(OpTy), regNum(-1) { + switch (UseTy) { + case MOTy::Use: flags = 0; break; + case MOTy::Def: flags = DEFONLYFLAG; break; + case MOTy::UseAndDef: flags = DEFUSEFLAG; break; + default: assert(0 && "Invalid value for UseTy!"); + } + if (isPCRelative) flags |= PCRELATIVE; + } + + MachineOperand(MachineBasicBlock *mbb) + : MBB(mbb), flags(0), opType(MO_MachineBasicBlock), regNum(-1) {} + + MachineOperand(const std::string &SymName, bool isPCRelative) + : SymbolName(new std::string(SymName)), flags(isPCRelative ? PCRELATIVE :0), + opType(MO_ExternalSymbol), regNum(-1) {} + public: - /*ctor*/ MachineOperand (); - /*ctor*/ MachineOperand (MachineOperandType operandType, - Value* _val); - /*copy ctor*/ MachineOperand (const MachineOperand&); - /*dtor*/ ~MachineOperand () {} + MachineOperand(const MachineOperand &M) : immedVal(M.immedVal), + flags(M.flags), + opType(M.opType), + regNum(M.regNum) { + if (isExternalSymbol()) + SymbolName = new std::string(M.getSymbolName()); + } + + ~MachineOperand() { + if (isExternalSymbol()) + delete SymbolName; + } + const MachineOperand &operator=(const MachineOperand &MO) { + if (isExternalSymbol()) // if old operand had a symbol name, + delete SymbolName; // release old memory + immedVal = MO.immedVal; + flags = MO.flags; + opType = MO.opType; + regNum = MO.regNum; + if (isExternalSymbol()) + SymbolName = new std::string(MO.getSymbolName()); + return *this; + } + // Accessor methods. Caller is responsible for checking the // operand type before invoking the corresponding accessor. // - inline MachineOperandType getOperandType () const { - return opType; + MachineOperandType getType() const { return opType; } + + /// isPCRelative - This returns the value of the PCRELATIVE flag, which + /// indicates whether this operand should be emitted as a PC relative value + /// instead of a global address. This is used for operands of the forms: + /// MachineBasicBlock, GlobalAddress, ExternalSymbol + /// + bool isPCRelative() const { return (flags & PCRELATIVE) != 0; } + + + // This is to finally stop caring whether we have a virtual or machine + // register -- an easier interface is to simply call both virtual and machine + // registers essentially the same, yet be able to distinguish when + // necessary. Thus the instruction selector can just add registers without + // abandon, and the register allocator won't be confused. + bool isVirtualRegister() const { + return (opType == MO_VirtualRegister || opType == MO_MachineRegister) + && regNum >= MRegisterInfo::FirstVirtualRegister; + } + bool isPhysicalRegister() const { + return (opType == MO_VirtualRegister || opType == MO_MachineRegister) + && (unsigned)regNum < MRegisterInfo::FirstVirtualRegister; } - inline Value* getVRegValue () const { + bool isRegister() const { return isVirtualRegister() || isPhysicalRegister();} + bool isMachineRegister() const { return !isVirtualRegister(); } + bool isMachineBasicBlock() const { return opType == MO_MachineBasicBlock; } + bool isPCRelativeDisp() const { return opType == MO_PCRelativeDisp; } + bool isImmediate() const { + return opType == MO_SignExtendedImmed || opType == MO_UnextendedImmed; + } + bool isFrameIndex() const { return opType == MO_FrameIndex; } + bool isConstantPoolIndex() const { return opType == MO_ConstantPoolIndex; } + bool isGlobalAddress() const { return opType == MO_GlobalAddress; } + bool isExternalSymbol() const { return opType == MO_ExternalSymbol; } + + Value* getVRegValue() const { assert(opType == MO_VirtualRegister || opType == MO_CCRegister || - opType == MO_PCRelativeDisp); + isPCRelativeDisp()); return value; } - inline unsigned int getMachineRegNum() const { + Value* getVRegValueOrNull() const { + return (opType == MO_VirtualRegister || opType == MO_CCRegister || + isPCRelativeDisp()) ? value : NULL; + } + int getMachineRegNum() const { assert(opType == MO_MachineRegister); return regNum; } - inline int64_t getImmedValue () const { - assert(opType >= MO_SignExtendedImmed || opType <= MO_PCRelativeDisp); + int64_t getImmedValue() const { assert(isImmediate()); return immedVal; } + MachineBasicBlock *getMachineBasicBlock() const { + assert(isMachineBasicBlock() && "Can't get MBB in non-MBB operand!"); + return MBB; + } + int getFrameIndex() const { assert(isFrameIndex()); return immedVal; } + unsigned getConstantPoolIndex() const { + assert(isConstantPoolIndex()); return immedVal; } - inline bool opIsDef () const { - return isDef; + + GlobalValue *getGlobal() const { + assert(isGlobalAddress()); + return (GlobalValue*)value; } - -public: - friend ostream& operator<<(ostream& os, const MachineOperand& mop); - -private: - // These functions are provided so that a vector of operands can be - // statically allocated and individual ones can be initialized later. - // Give class MachineInstr gets access to these functions. - // - void Initialize (MachineOperandType operandType, - Value* _val); - void InitializeConst (MachineOperandType operandType, - int64_t intValue); - void InitializeReg (unsigned int regNum); + const std::string &getSymbolName() const { + assert(isExternalSymbol()); + return *SymbolName; + } - friend class MachineInstr; - friend class ValOpIterator; - friend class ValOpIterator< MachineInstr, Value>; + bool opIsUse () const { return (flags & USEDEFMASK) == 0; } + bool opIsDefOnly () const { return flags & DEFONLYFLAG; } + bool opIsDefAndUse () const { return flags & DEFUSEFLAG; } + bool opHiBits32 () const { return flags & HIFLAG32; } + bool opLoBits32 () const { return flags & LOFLAG32; } + bool opHiBits64 () const { return flags & HIFLAG64; } + bool opLoBits64 () const { return flags & LOFLAG64; } + + // used to check if a machine register has been allocated to this operand + bool hasAllocatedReg() const { + return (regNum >= 0 && + (opType == MO_VirtualRegister || opType == MO_CCRegister || + opType == MO_MachineRegister)); + } + // used to get the reg number if when one is allocated + int getAllocatedRegNum() const { + assert(hasAllocatedReg()); + return regNum; + } -public: + // ********** TODO: get rid of this duplicate code! *********** + unsigned getReg() const { + return getAllocatedRegNum(); + } - -}; + friend std::ostream& operator<<(std::ostream& os, const MachineOperand& mop); +private: -inline -MachineOperand::MachineOperand() - : opType(MO_VirtualRegister), - value(NULL), - regNum(0), - immedVal(0), - isDef(false) -{} - -inline -MachineOperand::MachineOperand(MachineOperandType operandType, - Value* _val) - : opType(operandType), - value(_val), - regNum(0), - immedVal(0), - isDef(false) -{} - -inline -MachineOperand::MachineOperand(const MachineOperand& mo) - : opType(mo.opType), - isDef(false) -{ - switch(opType) { - case MO_VirtualRegister: - case MO_CCRegister: value = mo.value; break; - case MO_MachineRegister: regNum = mo.regNum; break; - case MO_SignExtendedImmed: - case MO_UnextendedImmed: - case MO_PCRelativeDisp: immedVal = mo.immedVal; break; - default: assert(0); + // Construction methods needed for fine-grain control. + // These must be accessed via coresponding methods in MachineInstr. + void markHi32() { flags |= HIFLAG32; } + void markLo32() { flags |= LOFLAG32; } + void markHi64() { flags |= HIFLAG64; } + void markLo64() { flags |= LOFLAG64; } + + // Replaces the Value with its corresponding physical register after + // register allocation is complete + void setRegForValue(int reg) { + assert(opType == MO_VirtualRegister || opType == MO_CCRegister || + opType == MO_MachineRegister); + regNum = reg; } -} - -inline void -MachineOperand::Initialize(MachineOperandType operandType, - Value* _val) -{ - opType = operandType; - value = _val; -} - -inline void -MachineOperand::InitializeConst(MachineOperandType operandType, - int64_t intValue) -{ - opType = operandType; - value = NULL; - immedVal = intValue; -} - -inline void -MachineOperand::InitializeReg(unsigned int _regNum) -{ - opType = MO_MachineRegister; - value = NULL; - regNum = _regNum; -} + + friend class MachineInstr; +}; -//--------------------------------------------------------------------------- +//===----------------------------------------------------------------------===// // class MachineInstr // // Purpose: @@ -214,266 +337,382 @@ MachineOperand::InitializeReg(unsigned int _regNum) // MachineOpCode must be an enum, defined separately for each target. // E.g., It is defined in SparcInstructionSelection.h for the SPARC. // -// opCodeMask is used to record variants of an instruction. -// E.g., each branch instruction on SPARC has 2 flags (i.e., 4 variants): -// ANNUL: if 1: Annul delay slot instruction. -// PREDICT-NOT-TAKEN: if 1: predict branch not taken. -// Instead of creating 4 different opcodes for BNZ, we create a single -// opcode and set bits in opCodeMask for each of these flags. -//--------------------------------------------------------------------------- - -class MachineInstr : public NonCopyable { -private: - MachineOpCode opCode; - OpCodeMask opCodeMask; // extra bits for variants of an opcode - vector operands; - -public: - typedef ValOpIterator val_op_const_iterator; - typedef ValOpIterator val_op_iterator; - +// There are 2 kinds of operands: +// +// (1) Explicit operands of the machine instruction in vector operands[] +// +// (2) "Implicit operands" are values implicitly used or defined by the +// machine instruction, such as arguments to a CALL, return value of +// a CALL (if any), and return value of a RETURN. +//===----------------------------------------------------------------------===// + +class MachineInstr { + int opCode; // the opcode + unsigned opCodeFlags; // flags modifying instrn behavior + std::vector operands; // the operands + unsigned numImplicitRefs; // number of implicit operands + + // OperandComplete - Return true if it's illegal to add a new operand + bool OperandsComplete() const; + + MachineInstr(const MachineInstr &); // DO NOT IMPLEMENT + void operator=(const MachineInstr&); // DO NOT IMPLEMENT public: - /*ctor*/ MachineInstr (MachineOpCode _opCode, - OpCodeMask _opCodeMask = 0x0); - /*ctor*/ MachineInstr (MachineOpCode _opCode, - unsigned numOperands, - OpCodeMask _opCodeMask = 0x0); - inline ~MachineInstr () {} - - const MachineOpCode getOpCode () const; + MachineInstr(int Opcode, unsigned numOperands); + + /// MachineInstr ctor - This constructor only does a _reserve_ of the + /// operands, not a resize for them. It is expected that if you use this that + /// you call add* methods below to fill up the operands, instead of the Set + /// methods. Eventually, the "resizing" ctors will be phased out. + /// + MachineInstr(int Opcode, unsigned numOperands, bool XX, bool YY); + + /// MachineInstr ctor - Work exactly the same as the ctor above, except that + /// the MachineInstr is created and added to the end of the specified basic + /// block. + /// + MachineInstr(MachineBasicBlock *MBB, int Opcode, unsigned numOps); - unsigned int getNumOperands () const; - - const MachineOperand& getOperand (unsigned int i) const; - MachineOperand& getOperand (unsigned int i); + + // The opcode. + // + const int getOpcode() const { return opCode; } + const int getOpCode() const { return opCode; } + + // Opcode flags. + // + unsigned getOpCodeFlags() const { return opCodeFlags; } + + // + // Access to explicit operands of the instruction + // + unsigned getNumOperands() const { return operands.size() - numImplicitRefs; } - bool operandIsDefined(unsigned int i) const; + const MachineOperand& getOperand(unsigned i) const { + assert(i < getNumOperands() && "getOperand() out of range!"); + return operands[i]; + } + MachineOperand& getOperand(unsigned i) { + assert(i < getNumOperands() && "getOperand() out of range!"); + return operands[i]; + } + + // + // Access to explicit or implicit operands of the instruction + // This returns the i'th entry in the operand vector. + // That represents the i'th explicit operand or the (i-N)'th implicit operand, + // depending on whether i < N or i >= N. + // + const MachineOperand& getExplOrImplOperand(unsigned i) const { + assert(i < operands.size() && "getExplOrImplOperand() out of range!"); + return (i < getNumOperands()? getOperand(i) + : getImplicitOp(i - getNumOperands())); + } + + // + // Access to implicit operands of the instruction + // + unsigned getNumImplicitRefs() const{ return numImplicitRefs; } - void dump (unsigned int indent = 0) const; + MachineOperand& getImplicitOp(unsigned i) { + assert(i < numImplicitRefs && "implicit ref# out of range!"); + return operands[i + operands.size() - numImplicitRefs]; + } + const MachineOperand& getImplicitOp(unsigned i) const { + assert(i < numImplicitRefs && "implicit ref# out of range!"); + return operands[i + operands.size() - numImplicitRefs]; + } + Value* getImplicitRef(unsigned i) { + return getImplicitOp(i).getVRegValue(); + } + const Value* getImplicitRef(unsigned i) const { + return getImplicitOp(i).getVRegValue(); + } + void addImplicitRef(Value* V, bool isDef = false, bool isDefAndUse = false) { + ++numImplicitRefs; + addRegOperand(V, isDef, isDefAndUse); + } + void setImplicitRef(unsigned i, Value* V) { + assert(i < getNumImplicitRefs() && "setImplicitRef() out of range!"); + SetMachineOperandVal(i + getNumOperands(), + MachineOperand::MO_VirtualRegister, V); + } + // + // Debugging support + // + void print(std::ostream &OS, const TargetMachine &TM) const; + void dump() const; + friend std::ostream& operator<<(std::ostream& os, const MachineInstr& minstr); - -public: - friend ostream& operator<<(ostream& os, const MachineInstr& minstr); - friend val_op_const_iterator; - friend val_op_iterator; + // + // Define iterators to access the Value operands of the Machine Instruction. + // Note that these iterators only enumerate the explicit operands. + // begin() and end() are defined to produce these iterators... + // + template class ValOpIterator; + typedef ValOpIterator const_val_op_iterator; + typedef ValOpIterator< MachineInstr*, Value*> val_op_iterator; -public: - // Access to set the operands when building the machine instruction - void SetMachineOperand(unsigned int i, - MachineOperand::MachineOperandType operandType, - Value* _val, bool isDef=false); - void SetMachineOperand(unsigned int i, - MachineOperand::MachineOperandType operandType, - int64_t intValue, bool isDef=false); - void SetMachineOperand(unsigned int i, - unsigned int regNum, - bool isDef=false); -}; -inline const MachineOpCode -MachineInstr::getOpCode() const -{ - return opCode; -} + //===--------------------------------------------------------------------===// + // Accessors to add operands when building up machine instructions + // -inline unsigned int -MachineInstr::getNumOperands() const -{ - return operands.size(); -} + /// addRegOperand - Add a MO_VirtualRegister operand to the end of the + /// operands list... + /// + void addRegOperand(Value *V, bool isDef, bool isDefAndUse=false) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(V, MachineOperand::MO_VirtualRegister, + !isDef ? MOTy::Use : (isDefAndUse ? MOTy::UseAndDef : MOTy::Def))); + } -inline MachineOperand& -MachineInstr::getOperand(unsigned int i) -{ - assert(i < operands.size() && "getOperand() out of range!"); - return operands[i]; -} + void addRegOperand(Value *V, MOTy::UseType UTy = MOTy::Use, + bool isPCRelative = false) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(V, MachineOperand::MO_VirtualRegister, + UTy, isPCRelative)); + } -inline const MachineOperand& -MachineInstr::getOperand(unsigned int i) const -{ - assert(i < operands.size() && "getOperand() out of range!"); - return operands[i]; -} + void addCCRegOperand(Value *V, MOTy::UseType UTy = MOTy::Use) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(V, MachineOperand::MO_CCRegister, UTy, + false)); + } -inline bool -MachineInstr::operandIsDefined(unsigned int i) const -{ - return getOperand(i).opIsDef(); -} + /// addRegOperand - Add a symbolic virtual register reference... + /// + void addRegOperand(int reg, bool isDef) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(reg, MachineOperand::MO_VirtualRegister, + isDef ? MOTy::Def : MOTy::Use)); + } -template -class ValOpIterator : public std::forward_iterator<_V, ptrdiff_t> { -private: - unsigned int i; - int resultPos; - _MI* minstr; - - inline void skipToNextVal() { - while (i < minstr->getNumOperands() && - ! ((minstr->operands[i].opType == MachineOperand::MO_VirtualRegister - || minstr->operands[i].opType == MachineOperand::MO_CCRegister) - && minstr->operands[i].value != NULL)) - ++i; + /// addRegOperand - Add a symbolic virtual register reference... + /// + void addRegOperand(int reg, MOTy::UseType UTy = MOTy::Use) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(reg, MachineOperand::MO_VirtualRegister, + UTy)); } - -public: - typedef ValOpIterator<_MI, _V> _Self; - - inline ValOpIterator(_MI* _minstr) : i(0), minstr(_minstr) { - resultPos = TargetInstrDescriptors[minstr->opCode].resultPos; - skipToNextVal(); - }; - - inline _V* operator*() const { return minstr->getOperand(i).getVRegValue();} - inline _V* operator->() const { return operator*(); } - // inline bool isDef () const { return (((int) i) == resultPos); } - - inline bool isDef () const { return minstr->getOperand(i).isDef; } - inline bool done () const { return (i == minstr->getNumOperands()); } - - inline _Self& operator++() { i++; skipToNextVal(); return *this; } - inline _Self operator++(int) { _Self tmp = *this; ++*this; return tmp; } -}; + /// addPCDispOperand - Add a PC relative displacement operand to the MI + /// + void addPCDispOperand(Value *V) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(V, MachineOperand::MO_PCRelativeDisp, + MOTy::Use)); + } -//--------------------------------------------------------------------------- -// class MachineCodeForVMInstr -// -// Purpose: -// Representation of the sequence of machine instructions created -// for a single VM instruction. Additionally records any temporary -// "values" used as intermediate values in this sequence. -// Note that such values should be treated as pure SSA values with -// no interpretation of their operands (i.e., as a TmpInstruction object -// which actually represents such a value). -// -//--------------------------------------------------------------------------- + /// addMachineRegOperand - Add a virtual register operand to this MachineInstr + /// + void addMachineRegOperand(int reg, bool isDef) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(reg, MachineOperand::MO_MachineRegister, + isDef ? MOTy::Def : MOTy::Use)); + } -class MachineCodeForVMInstr: public vector -{ -private: - vector tempVec; - -public: - /*ctor*/ MachineCodeForVMInstr () {} - /*ctor*/ ~MachineCodeForVMInstr (); - - const vector& - getTempValues () const { return tempVec; } - - void addTempValue (Value* val) - { tempVec.push_back(val); } + /// addMachineRegOperand - Add a virtual register operand to this MachineInstr + /// + void addMachineRegOperand(int reg, MOTy::UseType UTy = MOTy::Use) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(reg, MachineOperand::MO_MachineRegister, + UTy)); + } - // dropAllReferences() - This function drops all references within - // temporary (hidden) instructions created in implementing the original - // VM intruction. This ensures there are no remaining "uses" within - // these hidden instructions, before the values of a method are freed. - // - // Make this inline because it has to be called from class Instruction - // and inlining it avoids a serious circurality in link order. - inline void dropAllReferences() { - for (unsigned i=0, N=tempVec.size(); i < N; i++) - if (Instruction *I = tempVec[i]->castInstruction()) - I->dropAllReferences(); + /// addZeroExtImmOperand - Add a zero extended constant argument to the + /// machine instruction. + /// + void addZeroExtImmOperand(int64_t intValue) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(intValue, + MachineOperand::MO_UnextendedImmed)); } -}; -inline -MachineCodeForVMInstr::~MachineCodeForVMInstr() -{ - // Free the Value objects created to hold intermediate values - for (unsigned i=0, N=tempVec.size(); i < N; i++) - delete tempVec[i]; - - // Free the MachineInstr objects allocated, if any. - for (unsigned i=0, N=this->size(); i < N; i++) - delete (*this)[i]; -} + /// addSignExtImmOperand - Add a zero extended constant argument to the + /// machine instruction. + /// + void addSignExtImmOperand(int64_t intValue) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(intValue, + MachineOperand::MO_SignExtendedImmed)); + } + void addMachineBasicBlockOperand(MachineBasicBlock *MBB) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(MBB)); + } -//--------------------------------------------------------------------------- -// class MachineCodeForBasicBlock -// -// Purpose: -// Representation of the sequence of machine instructions created -// for a basic block. -//--------------------------------------------------------------------------- + /// addFrameIndexOperand - Add an abstract frame index to the instruction + /// + void addFrameIndexOperand(unsigned Idx) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(Idx, MachineOperand::MO_FrameIndex)); + } + /// addConstantPoolndexOperand - Add a constant pool object index to the + /// instruction. + /// + void addConstantPoolIndexOperand(unsigned I) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(I, MachineOperand::MO_ConstantPoolIndex)); + } -class MachineCodeForBasicBlock: public vector { -public: - typedef vector::iterator iterator; - typedef vector::const_iterator const_iterator; -}; + void addGlobalAddressOperand(GlobalValue *GV, bool isPCRelative) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand((Value*)GV, + MachineOperand::MO_GlobalAddress, + MOTy::Use, isPCRelative)); + } + /// addExternalSymbolOperand - Add an external symbol operand to this instr + /// + void addExternalSymbolOperand(const std::string &SymName, bool isPCRelative) { + operands.push_back(MachineOperand(SymName, isPCRelative)); + } -//--------------------------------------------------------------------------- -// Target-independent utility routines for creating machine instructions -//--------------------------------------------------------------------------- + //===--------------------------------------------------------------------===// + // Accessors used to modify instructions in place. + // + // FIXME: Move this stuff to MachineOperand itself! + + /// replace - Support to rewrite a machine instruction in place: for now, + /// simply replace() and then set new operands with Set.*Operand methods + /// below. + /// + void replace(int Opcode, unsigned numOperands); + + /// setOpcode - Replace the opcode of the current instruction with a new one. + /// + void setOpcode(unsigned Op) { opCode = Op; } + + /// RemoveOperand - Erase an operand from an instruction, leaving it with one + /// fewer operand than it started with. + /// + void RemoveOperand(unsigned i) { + operands.erase(operands.begin()+i); + } + // Access to set the operands when building the machine instruction + // + void SetMachineOperandVal (unsigned i, + MachineOperand::MachineOperandType operandType, + Value* V); -//------------------------------------------------------------------------ -// Function Set2OperandsFromInstr -// Function Set3OperandsFromInstr -// -// For the common case of 2- and 3-operand arithmetic/logical instructions, -// set the m/c instr. operands directly from the VM instruction's operands. -// Check whether the first or second operand is 0 and can use a dedicated -// "0" register. -// Check whether the second operand should use an immediate field or register. -// (First and third operands are never immediates for such instructions.) -// -// Arguments: -// canDiscardResult: Specifies that the result operand can be discarded -// by using the dedicated "0" -// -// op1position, op2position and resultPosition: Specify in which position -// in the machine instruction the 3 operands (arg1, arg2 -// and result) should go. -// -// RETURN VALUE: unsigned int flags, where -// flags & 0x01 => operand 1 is constant and needs a register -// flags & 0x02 => operand 2 is constant and needs a register -//------------------------------------------------------------------------ + void SetMachineOperandConst (unsigned i, + MachineOperand::MachineOperandType operandType, + int64_t intValue); -void Set2OperandsFromInstr (MachineInstr* minstr, - InstructionNode* vmInstrNode, - const TargetMachine& targetMachine, - bool canDiscardResult = false, - int op1Position = 0, - int resultPosition = 1); + void SetMachineOperandReg(unsigned i, int regNum); -void Set3OperandsFromInstr (MachineInstr* minstr, - InstructionNode* vmInstrNode, - const TargetMachine& targetMachine, - bool canDiscardResult = false, - int op1Position = 0, - int op2Position = 1, - int resultPosition = 2); -MachineOperand::MachineOperandType - ChooseRegOrImmed(Value* val, - MachineOpCode opCode, - const TargetMachine& targetMachine, - bool canUseImmed, - unsigned int& getMachineRegNum, - int64_t& getImmedValue); + unsigned substituteValue(const Value* oldVal, Value* newVal, + bool defsOnly, bool notDefsAndUses, + bool& someArgsWereIgnored); + void setOperandHi32(unsigned i) { operands[i].markHi32(); } + void setOperandLo32(unsigned i) { operands[i].markLo32(); } + void setOperandHi64(unsigned i) { operands[i].markHi64(); } + void setOperandLo64(unsigned i) { operands[i].markLo64(); } + + + // SetRegForOperand - + // SetRegForImplicitRef - + // Mark an explicit or implicit operand with its allocated physical register. + // + void SetRegForOperand(unsigned i, int regNum); + void SetRegForImplicitRef(unsigned i, int regNum); -ostream& operator<<(ostream& os, const MachineInstr& minstr); + // + // Iterator to enumerate machine operands. + // + template + class ValOpIterator : public forward_iterator { + unsigned i; + MITy MI; + + void skipToNextVal() { + while (i < MI->getNumOperands() && + !( (MI->getOperand(i).getType() == MachineOperand::MO_VirtualRegister || + MI->getOperand(i).getType() == MachineOperand::MO_CCRegister) + && MI->getOperand(i).getVRegValue() != 0)) + ++i; + } + + inline ValOpIterator(MITy mi, unsigned I) : i(I), MI(mi) { + skipToNextVal(); + } + + public: + typedef ValOpIterator _Self; + + inline VTy operator*() const { + return MI->getOperand(i).getVRegValue(); + } + + const MachineOperand &getMachineOperand() const { return MI->getOperand(i);} + MachineOperand &getMachineOperand() { return MI->getOperand(i);} + + inline VTy operator->() const { return operator*(); } + + inline bool isUseOnly() const { return MI->getOperand(i).opIsUse(); } + inline bool isDefOnly() const { return MI->getOperand(i).opIsDefOnly(); } + inline bool isDefAndUse() const { return MI->getOperand(i).opIsDefAndUse();} + + inline _Self& operator++() { i++; skipToNextVal(); return *this; } + inline _Self operator++(int) { _Self tmp = *this; ++*this; return tmp; } + + inline bool operator==(const _Self &y) const { + return i == y.i; + } + inline bool operator!=(const _Self &y) const { + return !operator==(y); + } + + static _Self begin(MITy MI) { + return _Self(MI, 0); + } + static _Self end(MITy MI) { + return _Self(MI, MI->getNumOperands()); + } + }; + // define begin() and end() + val_op_iterator begin() { return val_op_iterator::begin(this); } + val_op_iterator end() { return val_op_iterator::end(this); } -ostream& operator<<(ostream& os, const MachineOperand& mop); - + const_val_op_iterator begin() const { + return const_val_op_iterator::begin(this); + } + const_val_op_iterator end() const { + return const_val_op_iterator::end(this); + } +}; -void PrintMachineInstructions (const Method *method); +//===----------------------------------------------------------------------===// +// Debugging Support -//**************************************************************************/ +std::ostream& operator<<(std::ostream &OS, const MachineInstr &MI); +std::ostream& operator<<(std::ostream &OS, const MachineOperand &MO); +void PrintMachineInstructions(const Function *F); #endif