//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class --------*- C++ -*-===//
//
//                     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 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 "llvm/ADT/iterator"
#include "llvm/Support/DataTypes.h"
#include <vector>
#include <cassert>

namespace llvm {

class Value;
class Function;
class MachineBasicBlock;
class TargetMachine;
class GlobalValue;

template <typename T> struct ilist_traits;
template <typename T> struct ilist;

typedef short MachineOpCode;

//===----------------------------------------------------------------------===//
// class MachineOperand
//
// Purpose:
//   Representation of each machine instruction operand.
//   This class is designed so that you can allocate a vector of operands
//   first and initialize each one later.
//
//   E.g, for this VM instruction:
//     ptr = alloca type, numElements
//   we generate 2 machine instructions on the SPARC:
//
//    mul Constant, Numelements -> Reg
//    add %sp, Reg -> Ptr
//
//   Each instruction has 3 operands, listed above.  Of those:
//   - Reg, NumElements, and Ptr are of operand type MO_Register.
//   - Constant is of operand type MO_SignExtendedImmed on the SPARC.
//
//   For the register operands, the virtual register type is as follows:
//
//   - Reg will be of virtual register type MO_MInstrVirtualReg.  The field
//     MachineInstr* minstr will point to the instruction that computes reg.
//
//   - %sp will be of virtual register type MO_MachineReg.
//     The field regNum identifies the machine register.
//
//   - NumElements will be of virtual register type MO_VirtualReg.
//     The field Value* value identifies the value.
//
//   - Ptr will also be of virtual register type MO_VirtualReg.
//     Again, the field Value* value identifies the value.
//
//===----------------------------------------------------------------------===//

struct MachineOperand {
private:
  // Bit fields of the flags variable used for different operand properties
  enum {
    DEFFLAG     = 0x01,       // this is a def of the operand
    USEFLAG     = 0x02,       // this is a use of the operand
    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
  };

public:
  // UseType - This enum describes how the machine operand is used by
  // the instruction. 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.
  //
  enum UseType {
    Use = USEFLAG,        /// only read
    Def = DEFFLAG,        /// only written
    UseAndDef = Use | Def /// read AND written
  };

  enum MachineOperandType {
    MO_VirtualRegister,         // virtual register for *value
    MO_MachineRegister,         // pre-assigned machine register `regNum'
    MO_CCRegister,
    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:
  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.
                        // LLVM global for MO_GlobalAddress.

    int64_t immedVal;   // Constant value for an explicit constant

    MachineBasicBlock *MBB;     // For MO_MachineBasicBlock type
    const char *SymbolName;     // For MO_ExternalSymbol type
  } contents;

  char flags;                   // see bit field definitions above
  MachineOperandType opType:8;  // Pack into 8 bits efficiently after flags.
  union {
    int regNum;                 // register number for an explicit register
                                // will be set for a value after reg allocation

    int offset;                 // Offset to address of global or external, only
                                // valid for MO_GlobalAddress and MO_ExternalSym
  } extra;

  void zeroContents () {
    memset (&contents, 0, sizeof (contents));
    memset (&extra, 0, sizeof (extra));
  }

  MachineOperand(int64_t ImmVal = 0,
        MachineOperandType OpTy = MO_VirtualRegister)
    : flags(0), opType(OpTy) {
    zeroContents ();
    contents.immedVal = ImmVal;
    extra.regNum = -1;
  }

  MachineOperand(int Reg, MachineOperandType OpTy, UseType UseTy)
    : flags(UseTy), opType(OpTy) {
    zeroContents ();
    extra.regNum = Reg;
  }

  MachineOperand(Value *V, MachineOperandType OpTy, UseType UseTy,
                 bool isPCRelative = false)
    : flags(UseTy | (isPCRelative?PCRELATIVE:0)), opType(OpTy) {
    assert(OpTy != MachineOperand::MO_GlobalAddress);
    zeroContents();
    contents.value = V;
    extra.regNum = -1;
  }

  MachineOperand(GlobalValue *V, MachineOperandType OpTy, UseType UseTy,
                 bool isPCRelative = false, int Offset = 0)
    : flags(UseTy | (isPCRelative?PCRELATIVE:0)), opType(OpTy) {
    assert(OpTy == MachineOperand::MO_GlobalAddress);
    zeroContents ();
    contents.value = (Value*)V;
    extra.offset = Offset;
  }

  MachineOperand(MachineBasicBlock *mbb)
    : flags(0), opType(MO_MachineBasicBlock) {
    zeroContents ();
    contents.MBB = mbb;
    extra.regNum = -1;
  }

  MachineOperand(const char *SymName, bool isPCRelative, int Offset)
    : flags(isPCRelative?PCRELATIVE:0), opType(MO_ExternalSymbol) {
    zeroContents ();
    contents.SymbolName = SymName;
    extra.offset = Offset;
  }

public:
  MachineOperand(const MachineOperand &M)
    : flags(M.flags), opType(M.opType) {
    zeroContents ();
    contents = M.contents;
    extra = M.extra;
  }


  ~MachineOperand() {}

  const MachineOperand &operator=(const MachineOperand &MO) {
    contents = MO.contents;
    flags    = MO.flags;
    opType   = MO.opType;
    extra    = MO.extra;
    return *this;
  }

  /// getType - Returns the MachineOperandType for this operand.
  ///
  MachineOperandType getType() const { return opType; }

  /// getUseType - Returns the MachineOperandUseType of this operand.
  ///
  UseType getUseType() const { return UseType(flags & (USEFLAG|DEFFLAG)); }

  /// 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; }

  /// isRegister - Return true if this operand is a register operand.  The X86
  /// backend currently can't decide whether to use MO_MR or MO_VR to represent
  /// them, so we accept both.
  ///
  /// Note: The sparc backend should not use this method.
  ///
  bool isRegister() const {
    return opType == MO_MachineRegister || opType == MO_VirtualRegister;
  }

  /// Accessors that tell you what kind of MachineOperand you're looking at.
  ///
  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; }

  /// getVRegValueOrNull - Get the Value* out of a MachineOperand if it
  /// has one. This is deprecated and only used by the SPARC v9 backend.
  ///
  Value* getVRegValueOrNull() const {
    return (opType == MO_VirtualRegister || opType == MO_CCRegister ||
            isPCRelativeDisp()) ? contents.value : NULL;
  }

  /// MachineOperand accessors that only work on certain types of
  /// MachineOperand...
  ///
  Value* getVRegValue() const {
    assert ((opType == MO_VirtualRegister || opType == MO_CCRegister
             || isPCRelativeDisp()) && "Wrong MachineOperand accessor");
    return contents.value;
  }
  int getMachineRegNum() const {
    assert(opType == MO_MachineRegister && "Wrong MachineOperand accessor");
    return extra.regNum;
  }
  int64_t getImmedValue() const {
    assert(isImmediate() && "Wrong MachineOperand accessor");
    return contents.immedVal;
  }
  MachineBasicBlock *getMachineBasicBlock() const {
    assert(isMachineBasicBlock() && "Wrong MachineOperand accessor");
    return contents.MBB;
  }
  void setMachineBasicBlock(MachineBasicBlock *MBB) {
    assert(isMachineBasicBlock() && "Wrong MachineOperand accessor");
    contents.MBB = MBB;
  }
  int getFrameIndex() const {
    assert(isFrameIndex() && "Wrong MachineOperand accessor");
    return (int)contents.immedVal;
  }
  unsigned getConstantPoolIndex() const {
    assert(isConstantPoolIndex() && "Wrong MachineOperand accessor");
    return (unsigned)contents.immedVal;
  }
  GlobalValue *getGlobal() const {
    assert(isGlobalAddress() && "Wrong MachineOperand accessor");
    return (GlobalValue*)contents.value;
  }
  int getOffset() const {
    assert((isGlobalAddress() || isExternalSymbol()) &&
        "Wrong MachineOperand accessor");
    return extra.offset;
  }
  const char *getSymbolName() const {
    assert(isExternalSymbol() && "Wrong MachineOperand accessor");
    return contents.SymbolName;
  }

  /// MachineOperand methods for testing that work on any kind of
  /// MachineOperand...
  ///
  bool            isUse           () const { return flags & USEFLAG; }
  MachineOperand& setUse          ()       { flags |= USEFLAG; return *this; }
  bool            isDef           () const { return flags & DEFFLAG; }
  MachineOperand& setDef          ()       { flags |= DEFFLAG; return *this; }
  bool            isHiBits32      () const { return flags & HIFLAG32; }
  bool            isLoBits32      () const { return flags & LOFLAG32; }
  bool            isHiBits64      () const { return flags & HIFLAG64; }
  bool            isLoBits64      () const { return flags & LOFLAG64; }

  /// hasAllocatedReg - Returns true iff a machine register has been
  /// allocated to this operand.
  ///
  bool hasAllocatedReg() const {
    return (extra.regNum >= 0 &&
            (opType == MO_VirtualRegister || opType == MO_CCRegister ||
             opType == MO_MachineRegister));
  }

  /// getReg - Returns the register number. It is a runtime error to call this
  /// if a register is not allocated.
  ///
  unsigned getReg() const {
    assert(hasAllocatedReg());
    return extra.regNum;
  }

  /// MachineOperand mutators...
  ///
  void setReg(unsigned Reg) {
    // This method's comment used to say: 'TODO: get rid of this duplicate
    // code.' It's not clear where the duplication is.
    assert(hasAllocatedReg() && "This operand cannot have a register number!");
    extra.regNum = Reg;
  }

  void setValueReg(Value *val) {
    assert(getVRegValueOrNull() != 0 && "Original operand must of type Value*");
    contents.value = val;
  }

  void setImmedValue(int immVal) {
    assert(isImmediate() && "Wrong MachineOperand mutator");
    contents.immedVal = immVal;
  }

  void setOffset(int Offset) {
    assert((isGlobalAddress() || isExternalSymbol()) &&
        "Wrong MachineOperand accessor");
    extra.offset = Offset;
  }

  friend std::ostream& operator<<(std::ostream& os, const MachineOperand& mop);

  /// markHi32, markLo32, etc. - These methods are deprecated and only used by
  /// the SPARC v9 back-end.
  ///
  void markHi32()      { flags |= HIFLAG32; }
  void markLo32()      { flags |= LOFLAG32; }
  void markHi64()      { flags |= HIFLAG64; }
  void markLo64()      { flags |= LOFLAG64; }

private:
  /// setRegForValue - Replaces the Value with its corresponding physical
  /// register after register allocation is complete. This is deprecated
  /// and only used by the SPARC v9 back-end.
  ///
  void setRegForValue(int reg) {
    assert(opType == MO_VirtualRegister || opType == MO_CCRegister ||
           opType == MO_MachineRegister);
    extra.regNum = reg;
  }

  friend class MachineInstr;
};


//===----------------------------------------------------------------------===//
// class MachineInstr
//
// Purpose:
//   Representation of each machine instruction.
//
//   MachineOpCode must be an enum, defined separately for each target.
//   E.g., It is defined in SparcInstructionSelection.h for the SPARC.
//
//  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 {
  short Opcode;                         // the opcode
  unsigned char numImplicitRefs;        // number of implicit operands
  std::vector<MachineOperand> operands; // the operands
  MachineInstr* prev, *next;            // links for our intrusive list
  MachineBasicBlock* parent;            // pointer to the owning basic block

  // OperandComplete - Return true if it's illegal to add a new operand
  bool OperandsComplete() const;

  //Constructor used by clone() method
  MachineInstr(const MachineInstr&);

  void operator=(const MachineInstr&); // DO NOT IMPLEMENT

  // Intrusive list support
  //
  friend struct ilist_traits<MachineInstr>;

public:
  MachineInstr(short 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(short 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, short Opcode, unsigned numOps);

  ~MachineInstr();

  const MachineBasicBlock* getParent() const { return parent; }
  MachineBasicBlock* getParent() { return parent; }

  /// getOpcode - Returns the opcode of this MachineInstr.
  ///
  const int getOpcode() const { return Opcode; }

  /// Access to explicit operands of the instruction.
  ///
  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];
  }

  //
  // 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; }

  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);
  }

  /// clone - Create a copy of 'this' instruction that is identical in
  /// all ways except the the instruction has no parent, prev, or next.
  MachineInstr* clone() const;

  //
  // Debugging support
  //
  void print(std::ostream &OS, const TargetMachine *TM) const;
  void dump() const;
  friend std::ostream& operator<<(std::ostream& os, const MachineInstr& minstr);

  // 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.  NOTE, these are
  // SparcV9 specific!
  //
  template<class _MI, class _V> class ValOpIterator;
  typedef ValOpIterator<const MachineInstr*,const Value*> const_val_op_iterator;
  typedef ValOpIterator<      MachineInstr*,      Value*> val_op_iterator;


  //===--------------------------------------------------------------------===//
  // Accessors to add operands when building up machine instructions
  //

  /// 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 ? MachineOperand::Use :
                     (isDefAndUse ? MachineOperand::UseAndDef :
                      MachineOperand::Def)));
  }

  void addRegOperand(Value *V,
                     MachineOperand::UseType UTy = MachineOperand::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));
  }

  void addCCRegOperand(Value *V,
                       MachineOperand::UseType UTy = MachineOperand::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));
  }


  /// 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 ? MachineOperand::Def : MachineOperand::Use));
  }

  /// addRegOperand - Add a symbolic virtual register reference...
  ///
  void addRegOperand(int reg,
                     MachineOperand::UseType UTy = MachineOperand::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));
  }

  /// 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,MachineOperand::Use));
  }

  /// 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 ? MachineOperand::Def : MachineOperand::Use));
  }

  /// addMachineRegOperand - Add a virtual register operand to this MachineInstr
  ///
  void addMachineRegOperand(int reg,
                            MachineOperand::UseType UTy = MachineOperand::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));
  }

  /// addZeroExtImmOperand - Add a zero extended constant argument to the
  /// machine instruction.
  ///
  void addZeroExtImmOperand(int intValue) {
    assert(!OperandsComplete() &&
           "Trying to add an operand to a machine instr that is already done!");
    operands.push_back(
      MachineOperand(intValue, MachineOperand::MO_UnextendedImmed));
  }

  /// addZeroExtImm64Operand - Add a zero extended 64-bit constant argument
  /// to the machine instruction.
  ///
  void addZeroExtImm64Operand(uint64_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));
  }

  /// addSignExtImmOperand - Add a zero extended constant argument to the
  /// machine instruction.
  ///
  void addSignExtImmOperand(int 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));
  }

  /// 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));
  }

  void addGlobalAddressOperand(GlobalValue *GV, bool isPCRelative, int Offset) {
    assert(!OperandsComplete() &&
           "Trying to add an operand to a machine instr that is already done!");
    operands.push_back(
      MachineOperand(GV, MachineOperand::MO_GlobalAddress,
                     MachineOperand::Use, isPCRelative, Offset));
  }

  /// addExternalSymbolOperand - Add an external symbol operand to this instr
  ///
  void addExternalSymbolOperand(const char *SymName, bool isPCRelative) {
    operands.push_back(MachineOperand(SymName, isPCRelative, 0));
  }

  //===--------------------------------------------------------------------===//
  // 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(short 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);

  void SetMachineOperandConst(unsigned i,
                              MachineOperand::MachineOperandType operandType,
                              int intValue);

  void SetMachineOperandReg(unsigned i, int regNum);


  unsigned substituteValue(const Value* oldVal, Value* newVal,
                           bool defsOnly, bool notDefsAndUses,
                           bool& someArgsWereIgnored);

  // 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);

  //
  // Iterator to enumerate machine operands.  NOTE, this is SPARCV9 specific!
  //
  template<class MITy, class VTy>
  class ValOpIterator : public forward_iterator<VTy, ptrdiff_t> {
    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<MITy, VTy> _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 isUse()   const { return MI->getOperand(i).isUse(); }
    inline bool isDef()   const { return MI->getOperand(i).isDef(); }

    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());
    }
  };

  // Note: These are Sparc-V9 specific!
  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);
  }
  const_val_op_iterator end() const {
    return const_val_op_iterator::end(this);
  }
};

//===----------------------------------------------------------------------===//
// 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);

} // End llvm namespace

#endif
