#ifndef LLVM_CODEGEN_MACHINEINSTR_H
#define LLVM_CODEGEN_MACHINEINSTR_H
-#include "Support/iterator"
+#include "llvm/ADT/iterator"
#include <vector>
#include <cassert>
class TargetMachine;
class GlobalValue;
-template <typename T> class ilist_traits;
-template <typename T> class ilist;
+template <typename T> struct ilist_traits;
+template <typename T> struct ilist;
typedef short MachineOpCode;
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.
+ 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.
int immedVal; // Constant value for an explicit constant
MachineBasicBlock *MBB; // For MO_MachineBasicBlock type
- std::string *SymbolName; // For MO_ExternalSymbol 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.
- int regNum; // register number for an explicit register
+ union {
+ int regNum; // register number for an explicit register
// will be set for a value after reg allocation
-private:
+
+ 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(int ImmVal = 0, MachineOperandType OpTy = MO_VirtualRegister)
- : immedVal(ImmVal),
- flags(0),
- opType(OpTy),
- regNum(-1) {}
+ : flags(0), opType(OpTy) {
+ zeroContents ();
+ contents.immedVal = ImmVal;
+ extra.regNum = -1;
+ }
MachineOperand(int Reg, MachineOperandType OpTy, UseType UseTy)
- : immedVal(0), flags(UseTy), opType(OpTy), regNum(Reg) { }
+ : flags(UseTy), opType(OpTy) {
+ zeroContents ();
+ extra.regNum = Reg;
+ }
MachineOperand(Value *V, MachineOperandType OpTy, UseType UseTy,
bool isPCRelative = false)
- : value(V),
- flags(UseTy | (isPCRelative ? PCRELATIVE : 0)),
- opType(OpTy),
- regNum(-1) {
+ : 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)
- : MBB(mbb), flags(0), opType(MO_MachineBasicBlock), regNum(-1) { }
+ : flags(0), opType(MO_MachineBasicBlock) {
+ zeroContents ();
+ contents.MBB = mbb;
+ extra.regNum = -1;
+ }
- MachineOperand(const std::string &SymName, bool isPCRelative)
- : SymbolName(new std::string(SymName)), flags(isPCRelative ? PCRELATIVE :0),
- opType(MO_ExternalSymbol), 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) : immedVal(M.immedVal),
- flags(M.flags),
- opType(M.opType),
- regNum(M.regNum) {
- if (isExternalSymbol())
- SymbolName = new std::string(M.getSymbolName());
+ MachineOperand(const MachineOperand &M)
+ : flags(M.flags), opType(M.opType) {
+ zeroContents ();
+ contents = M.contents;
+ extra = M.extra;
}
- ~MachineOperand() {
- if (isExternalSymbol())
- delete SymbolName;
- }
+
+ ~MachineOperand() {}
const MachineOperand &operator=(const MachineOperand &MO) {
- if (isExternalSymbol()) // if old operand had a symbol name,
- delete SymbolName; // release old memory
- immedVal = MO.immedVal;
+ contents = MO.contents;
flags = MO.flags;
opType = MO.opType;
- regNum = MO.regNum;
- if (isExternalSymbol())
- SymbolName = new std::string(MO.getSymbolName());
+ extra = MO.extra;
return *this;
}
/// getUseType - Returns the MachineOperandUseType of this operand.
///
- UseType getUseType() const {
- return UseType(flags & (USEFLAG|DEFFLAG));
- }
+ 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
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 {
bool isGlobalAddress() const { return opType == MO_GlobalAddress; }
bool isExternalSymbol() const { return opType == MO_ExternalSymbol; }
- Value* getVRegValue() const {
- assert(opType == MO_VirtualRegister || opType == MO_CCRegister ||
- isPCRelativeDisp());
- return value;
- }
+ /// 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()) ? value : NULL;
+ 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);
- return regNum;
+ assert(opType == MO_MachineRegister && "Wrong MachineOperand accessor");
+ return extra.regNum;
+ }
+ int getImmedValue() const {
+ assert(isImmediate() && "Wrong MachineOperand accessor");
+ return contents.immedVal;
}
- int getImmedValue() const { assert(isImmediate()); return immedVal; }
- void setImmedValue(int ImmVal) { assert(isImmediate()); immedVal = ImmVal; }
-
MachineBasicBlock *getMachineBasicBlock() const {
- assert(isMachineBasicBlock() && "Can't get MBB in non-MBB operand!");
- return MBB;
+ 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 contents.immedVal;
}
- int getFrameIndex() const { assert(isFrameIndex()); return immedVal; }
unsigned getConstantPoolIndex() const {
- assert(isConstantPoolIndex());
- return immedVal;
+ assert(isConstantPoolIndex() && "Wrong MachineOperand accessor");
+ return contents.immedVal;
}
-
GlobalValue *getGlobal() const {
- assert(isGlobalAddress());
- return (GlobalValue*)value;
+ assert(isGlobalAddress() && "Wrong MachineOperand accessor");
+ return (GlobalValue*)contents.value;
}
-
- const std::string &getSymbolName() const {
- assert(isExternalSymbol());
- return *SymbolName;
+ 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; }
+ 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; }
- // used to check if a machine register has been allocated to this operand
+ /// hasAllocatedReg - Returns true iff a machine register has been
+ /// allocated to this operand.
+ ///
bool hasAllocatedReg() const {
- return (regNum >= 0 &&
+ return (extra.regNum >= 0 &&
(opType == MO_VirtualRegister || opType == MO_CCRegister ||
opType == MO_MachineRegister));
}
- // used to get the reg number if when one is allocated
+ /// 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 regNum;
+ return extra.regNum;
}
- // ********** TODO: get rid of this duplicate code! ***********
+ /// 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!");
- regNum = Reg;
- }
+ extra.regNum = Reg;
+ }
- friend std::ostream& operator<<(std::ostream& os, const MachineOperand& mop);
+ 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;
+ }
-private:
+ void setOffset(int Offset) {
+ assert((isGlobalAddress() || isExternalSymbol()) &&
+ "Wrong MachineOperand accessor");
+ extra.offset = Offset;
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const MachineOperand& mop);
- // Construction methods needed for fine-grain control.
- // These must be accessed via coresponding methods in MachineInstr.
+ /// 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; }
- // Replaces the Value with its corresponding physical register after
- // register allocation is complete
+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);
- regNum = reg;
+ extra.regNum = reg;
}
friend class MachineInstr;
//===----------------------------------------------------------------------===//
class MachineInstr {
- short Opcode; // the opcode
+ 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;
- MachineInstr(const MachineInstr &); // DO NOT IMPLEMENT
+ //Constructor used by clone() method
+ MachineInstr(const MachineInstr&);
+
void operator=(const MachineInstr&); // DO NOT IMPLEMENT
-private:
// Intrusive list support
//
- friend class ilist_traits<MachineInstr>;
+ friend struct ilist_traits<MachineInstr>;
public:
MachineInstr(short Opcode, unsigned numOperands);
const MachineBasicBlock* getParent() const { return parent; }
MachineBasicBlock* getParent() { return parent; }
- /// Accessors for opcode.
+ /// getOpcode - Returns the opcode of this MachineInstr.
///
const int getOpcode() const { return Opcode; }
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 print(std::ostream &OS, const TargetMachine *TM) const;
void dump() const;
friend std::ostream& operator<<(std::ostream& os, const MachineInstr& minstr);
operands.push_back(MachineOperand(I, MachineOperand::MO_ConstantPoolIndex));
}
- void addGlobalAddressOperand(GlobalValue *GV, bool isPCRelative) {
+ 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((Value*)GV, MachineOperand::MO_GlobalAddress,
- MachineOperand::Use, isPCRelative));
+ MachineOperand(GV, MachineOperand::MO_GlobalAddress,
+ MachineOperand::Use, isPCRelative, Offset));
}
/// addExternalSymbolOperand - Add an external symbol operand to this instr
///
- void addExternalSymbolOperand(const std::string &SymName, bool isPCRelative) {
- operands.push_back(MachineOperand(SymName, isPCRelative));
+ void addExternalSymbolOperand(const char *SymName, bool isPCRelative) {
+ operands.push_back(MachineOperand(SymName, isPCRelative, 0));
}
//===--------------------------------------------------------------------===//
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 -