X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FCodeGen%2FMachineInstr.h;h=fc886d97f54830e7919067e89d2ea8bb013069f0;hb=6fbcc26f1460eaee4e0eb8b426fc1ff0c7af11be;hp=7c347a43ca4a92628d63ae891bde04e80d4593ba;hpb=e9bb2df410f7a22decad9a883f7139d5857c1520;p=oota-llvm.git diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 7c347a43ca4..fc886d97f54 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -1,43 +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 "Support/DataTypes.h" -#include "Support/NonCopyable.h" -#include "llvm/CodeGen/InstrForest.h" -#include "llvm/Target/MachineInstrInfo.h" -#include "llvm/Annotation.h" -#include "llvm/Method.h" -#include -#include -#include -#include - -template class ValOpIterator; - - -//************************** External Constants ****************************/ - -const int INVALID_FRAME_OFFSET = MAXINT; - - -//*************************** External Classes *****************************/ +#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: @@ -70,11 +87,9 @@ const int INVALID_FRAME_OFFSET = MAXINT; // - 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' @@ -82,158 +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. - 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 }; + 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 - bool isDef; // is this a defition for the value - +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; } - inline Value* getVRegValue () const { + bool isPhysicalRegister() const { + return (opType == MO_VirtualRegister || opType == MO_MachineRegister) + && (unsigned)regNum < MRegisterInfo::FirstVirtualRegister; + } + 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 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_UnextendedImmed); + 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 (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: - // replaces the Value with its corresponding physical register after + // 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; } - - // used to get the reg number if when one is allocted (must be - // called only after reg alloc) - inline int getAllocatedRegNum() const { - assert(opType == MO_VirtualRegister || opType == MO_CCRegister || - opType == MO_MachineRegister); - return regNum; - } - - + + friend class MachineInstr; }; -inline -MachineOperand::MachineOperand() - : opType(MO_VirtualRegister), - immedVal(0), - regNum(-1), - isDef(false) -{} - -inline -MachineOperand::MachineOperand(MachineOperandType operandType, - Value* _val) - : opType(operandType), - immedVal(0), - regNum(-1), - 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); - } -} - -inline void -MachineOperand::Initialize(MachineOperandType operandType, - Value* _val) -{ - opType = operandType; - value = _val; - regNum = -1; -} - -inline void -MachineOperand::InitializeConst(MachineOperandType operandType, - int64_t intValue) -{ - opType = operandType; - value = NULL; - immedVal = intValue; - regNum = -1; -} - -inline void -MachineOperand::InitializeReg(int _regNum) -{ - opType = MO_MachineRegister; - value = NULL; - regNum = (int) _regNum; -} - - -//--------------------------------------------------------------------------- +//===----------------------------------------------------------------------===// // class MachineInstr // // Purpose: @@ -242,13 +337,6 @@ MachineOperand::InitializeReg(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. -// // There are 2 kinds of operands: // // (1) Explicit operands of the machine instruction in vector operands[] @@ -256,387 +344,375 @@ MachineOperand::InitializeReg(int _regNum) // (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 : public NonCopyable { -private: - MachineOpCode opCode; - OpCodeMask opCodeMask; // extra bits for variants of an opcode - vector operands; - vector implicitRefs; // values implicitly referenced by this - vector implicitIsDef; // machine instruction (eg, call args) - +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: - typedef ValOpIterator val_op_const_iterator; - typedef ValOpIterator val_op_iterator; + 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); -public: - /*ctor*/ MachineInstr (MachineOpCode _opCode, - OpCodeMask _opCodeMask = 0x0); - /*ctor*/ MachineInstr (MachineOpCode _opCode, - unsigned numOperands, - OpCodeMask _opCodeMask = 0x0); - inline ~MachineInstr () {} - const MachineOpCode getOpCode () const { return opCode; } - // - // Information about explicit operands of the instruction + // The opcode. // - unsigned int getNumOperands () const { return operands.size(); } - - bool operandIsDefined(unsigned int i) const; - - const MachineOperand& getOperand (unsigned int i) const; - MachineOperand& getOperand (unsigned int i); - + const int getOpcode() const { return opCode; } + const int getOpCode() const { return opCode; } + + // Opcode flags. + // + unsigned getOpCodeFlags() const { return opCodeFlags; } + // - // Information about implicit operands of the instruction + // Access to explicit operands of the instruction // - unsigned int getNumImplicitRefs() const{return implicitRefs.size();} - - bool implicitRefIsDefined(unsigned int i) const; - - const Value* getImplicitRef (unsigned int i) const; - Value* getImplicitRef (unsigned int i); + unsigned getNumOperands() const { return operands.size() - numImplicitRefs; } + 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]; + } + // - // Debugging support + // 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. // - void dump (unsigned int indent = 0) const; + 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; } -public: - friend ostream& operator<<(ostream& os, const MachineInstr& minstr); - friend val_op_const_iterator; - friend val_op_iterator; + 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]; + } -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, - int regNum, - bool isDef=false); - - void addImplicitRef (Value* val, - bool isDef=false); - - void setImplicitRef (unsigned int i, - Value* val, - bool isDef=false); -}; + 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); + } -inline MachineOperand& -MachineInstr::getOperand(unsigned int i) -{ - assert(i < operands.size() && "getOperand() out of range!"); - return operands[i]; -} + // + // Debugging support + // + void print(std::ostream &OS, const TargetMachine &TM) const; + void dump() const; + friend std::ostream& operator<<(std::ostream& os, const MachineInstr& minstr); -inline const MachineOperand& -MachineInstr::getOperand(unsigned int i) const -{ - assert(i < operands.size() && "getOperand() out of range!"); - return operands[i]; -} + // + // 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; -inline bool -MachineInstr::operandIsDefined(unsigned int i) const -{ - return getOperand(i).opIsDef(); -} -inline bool -MachineInstr::implicitRefIsDefined(unsigned int i) const -{ - assert(i < implicitIsDef.size() && "operand out of range!"); - return implicitIsDef[i]; -} + //===--------------------------------------------------------------------===// + // Accessors to add operands when building up machine instructions + // -inline const Value* -MachineInstr::getImplicitRef(unsigned int i) const -{ - assert(i < implicitRefs.size() && "getImplicitRef() out of range!"); - return implicitRefs[i]; -} + /// 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 Value* -MachineInstr::getImplicitRef(unsigned int i) -{ - assert(i < implicitRefs.size() && "getImplicitRef() out of range!"); - return implicitRefs[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 void -MachineInstr::addImplicitRef(Value* val, - bool isDef) -{ - implicitRefs.push_back(val); - implicitIsDef.push_back(isDef); -} + 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 void -MachineInstr::setImplicitRef(unsigned int i, - Value* val, - bool isDef) -{ - assert(i < implicitRefs.size() && "setImplicitRef() out of range!"); - implicitRefs[i] = val; - implicitIsDef[i] = isDef; -} + /// 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();} - const MachineOperand & getMachineOperand() const { return minstr->getOperand(i); } + /// 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)); + } - 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; } -}; + /// 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)); + } + /// 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)); + } -//--------------------------------------------------------------------------- -// class MachineCodeForVMInstr -// -// Purpose: -// Representation of the sequence of machine instructions created -// for a single VM instruction. Additionally records information -// about hidden and implicit values used by the machine instructions: -// about hidden values used by the machine instructions: -// -// "Temporary values" are intermediate values used in the machine -// instruction sequence, but not in the VM instruction -// 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). -// -// (2) "Implicit uses" are values used in the VM instruction but not in -// the machine instruction sequence -// -//--------------------------------------------------------------------------- + /// 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)); + } -class MachineCodeForVMInstr: public vector -{ -private: - vector tempVec; // used by m/c instr but not VM instr - -public: - /*ctor*/ MachineCodeForVMInstr () {} - /*ctor*/ ~MachineCodeForVMInstr (); - - const vector& getTempValues () const { return tempVec; } - vector& getTempValues () { return tempVec; } - - void addTempValue (Value* val) { tempVec.push_back(val); } - - // 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 = dyn_cast(tempVec[i])) - I->dropAllReferences(); + /// 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)); } -}; -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]; -} + void addMachineBasicBlockOperand(MachineBasicBlock *MBB) { + assert(!OperandsComplete() && + "Trying to add an operand to a machine instr that is already done!"); + operands.push_back(MachineOperand(MBB)); + } + /// 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)); + } -//--------------------------------------------------------------------------- -// class MachineCodeForBasicBlock -// -// Purpose: -// Representation of the sequence of machine instructions created -// for a basic block. -//--------------------------------------------------------------------------- + /// 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)); + } + 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)); + } -class MachineCodeForBasicBlock: public vector { -public: - typedef vector::iterator iterator; - typedef vector::const_iterator const_iterator; -}; + /// addExternalSymbolOperand - Add an external symbol operand to this instr + /// + void addExternalSymbolOperand(const std::string &SymName, bool isPCRelative) { + operands.push_back(MachineOperand(SymName, isPCRelative)); + } + + //===--------------------------------------------------------------------===// + // 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); -//--------------------------------------------------------------------------- -// class MachineCodeForMethod -// -// Purpose: -// Collect native machine code information for a method. -// This allows target-specific information about the generated code -// to be stored with each method. -//--------------------------------------------------------------------------- + void SetMachineOperandConst (unsigned i, + MachineOperand::MachineOperandType operandType, + int64_t intValue); + void SetMachineOperandReg(unsigned i, int regNum); -class MachineCodeForMethod: public NonCopyable, private Annotation { -private: - static AnnotationID AID; -private: - const Method* method; - bool compiledAsLeaf; - unsigned staticStackSize; - unsigned automaticVarsSize; - unsigned regSpillsSize; - unsigned currentOptionalArgsSize; - unsigned maxOptionalArgsSize; - unsigned currentTmpValuesSize; - hash_set constantsForConstPool; - hash_map offsets; - // hash_map offsetsFromSP; + 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(); } -public: - /*ctor*/ MachineCodeForMethod(const Method* method, - const TargetMachine& target); - // The next two methods are used to construct and to retrieve - // the MachineCodeForMethod object for the given method. - // construct() -- Allocates and initializes for a given method and target - // get() -- Returns a handle to the object. - // This should not be called before "construct()" - // for a given Method. + // SetRegForOperand - + // SetRegForImplicitRef - + // Mark an explicit or implicit operand with its allocated physical register. // - inline static MachineCodeForMethod& construct(const Method* method, - const TargetMachine& target) - { - assert(method->getAnnotation(MachineCodeForMethod::AID) == NULL && - "Object already exists for this method!"); - MachineCodeForMethod* mcInfo = new MachineCodeForMethod(method, target); - method->addAnnotation(mcInfo); - return *mcInfo; - } - - inline static MachineCodeForMethod& get(const Method* method) - { - MachineCodeForMethod* mc = (MachineCodeForMethod*) - method->getAnnotation(MachineCodeForMethod::AID); - assert(mc && "Call construct() method first to allocate the object"); - return *mc; - } - - // - // Accessors for global information about generated code for a method. - // - inline bool isCompiledAsLeafMethod() const { return compiledAsLeaf; } - inline unsigned getStaticStackSize() const { return staticStackSize; } - inline unsigned getAutomaticVarsSize() const { return automaticVarsSize; } - inline unsigned getRegSpillsSize() const { return regSpillsSize; } - inline unsigned getMaxOptionalArgsSize() const { return maxOptionalArgsSize;} - inline unsigned getCurrentOptionalArgsSize() const - { return currentOptionalArgsSize;} - inline const hash_set& - getConstantPoolValues() const {return constantsForConstPool;} - + void SetRegForOperand(unsigned i, int regNum); + void SetRegForImplicitRef(unsigned i, int regNum); + // - // Modifiers used during code generation + // Iterator to enumerate machine operands. // - void initializeFrameLayout (const TargetMachine& target); - - void addToConstantPool (const Constant* constVal) - { constantsForConstPool.insert(constVal); } - - inline void markAsLeafMethod() { compiledAsLeaf = true; } - - int allocateLocalVar (const TargetMachine& target, - const Value* local, - unsigned int size = 0); - - int allocateSpilledValue (const TargetMachine& target, - const Type* type); - - int allocateOptionalArg (const TargetMachine& target, - const Type* type); - - void resetOptionalArgs (const TargetMachine& target); - - int pushTempValue (const TargetMachine& target, - unsigned int size); - - void popAllTempValues (const TargetMachine& target); - - int getOffset (const Value* val) const; - - // int getOffsetFromFP (const Value* val) const; - - void dump () const; + 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()); + } + }; -private: - inline void incrementAutomaticVarsSize(int incr) { - automaticVarsSize+= incr; - staticStackSize += incr; - } - inline void incrementRegSpillsSize(int incr) { - regSpillsSize+= incr; - staticStackSize += incr; + // define begin() and end() + val_op_iterator begin() { return val_op_iterator::begin(this); } + val_op_iterator end() { return val_op_iterator::end(this); } + + const_val_op_iterator begin() const { + return const_val_op_iterator::begin(this); } - inline void incrementCurrentOptionalArgsSize(int incr) { - currentOptionalArgsSize+= incr; // stack size already includes this! + const_val_op_iterator end() const { + return const_val_op_iterator::end(this); } }; -//--------------------------------------------------------------------------- +//===----------------------------------------------------------------------===// // Debugging Support -//--------------------------------------------------------------------------- - - -ostream& operator<< (ostream& os, const MachineInstr& minstr); - - -ostream& operator<< (ostream& os, const MachineOperand& mop); - - -void PrintMachineInstructions(const Method *method); - -//**************************************************************************/ +std::ostream& operator<<(std::ostream &OS, const MachineInstr &MI); +std::ostream& operator<<(std::ostream &OS, const MachineOperand &MO); +void PrintMachineInstructions(const Function *F); #endif