#ifndef LLVM_CODEGEN_MACHINEINSTR_H
#define LLVM_CODEGEN_MACHINEINSTR_H
+#include <iterator>
#include "llvm/CodeGen/InstrForest.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/NonCopyable.h"
#include "llvm/CodeGen/TargetMachine.h"
+template<class _MI, class _V> class ValOpIterator;
+
+
//---------------------------------------------------------------------------
// class MachineOperand
//
//---------------------------------------------------------------------------
class MachineOperand {
-public:
- friend ostream& operator<<(ostream& os, const MachineOperand& mop);
-
public:
enum MachineOperandType {
- MO_Register,
+ MO_VirtualRegister, // virtual register for *value
+ MO_MachineRegister, // pre-assigned machine register `regNum'
MO_CCRegister,
MO_SignExtendedImmed,
MO_UnextendedImmed,
MO_PCRelativeDisp,
};
- enum VirtualRegisterType {
- MO_VirtualReg, // virtual register for *value
- MO_MachineReg // pre-assigned machine register `regNum'
- };
-
- MachineOperandType machineOperandType;
-
- VirtualRegisterType vregType;
+private:
+ MachineOperandType opType;
- Value* value; // BasicBlockVal for a label operand.
+ union {
+ Value* value; // BasicBlockVal for a label operand.
// ConstantVal for a non-address immediate.
- // Virtual register for a register operand.
+ // Virtual register for an SSA operand,
+ // including hidden operands required for
+ // the generated machine code.
+
+ unsigned int regNum; // register number for an explicit register
- unsigned int regNum; // register number for an explicit register
-
- int64_t immedVal; // constant value for an explicit constant
+ int64_t immedVal; // constant value for an explicit constant
+ };
+public:
/*ctor*/ MachineOperand ();
/*ctor*/ MachineOperand (MachineOperandType operandType,
Value* _val);
/*copy ctor*/ MachineOperand (const MachineOperand&);
/*dtor*/ ~MachineOperand () {}
+ // Accessor methods. Caller is responsible for checking the
+ // operand type before invoking the corresponding accessor.
+ //
+ MachineOperandType getOperandType () const {
+ return opType;
+ }
+ Value* getVRegValue () const {
+ assert(opType == MO_VirtualRegister || opType == MO_CCRegister);
+ return value;
+ }
+ unsigned int getMachineRegNum() const {
+ assert(opType == MO_MachineRegister);
+ return regNum;
+ }
+ int64_t getImmedValue () const {
+ assert(opType >= MO_SignExtendedImmed || opType <= MO_PCRelativeDisp);
+ return immedVal;
+ }
+
+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);
+
+ friend class MachineInstr;
};
inline
MachineOperand::MachineOperand()
- : machineOperandType(MO_Register),
- vregType(MO_VirtualReg),
+ : opType(MO_VirtualRegister),
value(NULL),
regNum(0),
immedVal(0)
inline
MachineOperand::MachineOperand(MachineOperandType operandType,
Value* _val)
- : machineOperandType(operandType),
- vregType(MO_VirtualReg),
+ : opType(operandType),
value(_val),
regNum(0),
immedVal(0)
inline
MachineOperand::MachineOperand(const MachineOperand& mo)
- : machineOperandType(mo.machineOperandType),
- vregType(mo.vregType),
- value(mo.value),
- regNum(mo.regNum),
- immedVal(mo.immedVal)
+ : opType(mo.opType)
{
+ 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)
{
- machineOperandType = operandType;
+ opType = operandType;
value = _val;
}
MachineOperand::InitializeConst(MachineOperandType operandType,
int64_t intValue)
{
- machineOperandType = operandType;
+ opType = operandType;
value = NULL;
immedVal = intValue;
}
inline void
MachineOperand::InitializeReg(unsigned int _regNum)
{
- machineOperandType = MO_Register;
- vregType = MO_MachineReg;
+ opType = MO_MachineRegister;
value = NULL;
regNum = _regNum;
}
//
// MachineOpCode must be an enum, defined separately for each target.
// E.g., It is defined in SparcInstructionSelection.h for the SPARC.
-// The array MachineInstrInfo TargetMachineInstrInfo[] objects
-// (indexed by opCode) provides information about each target instruction.
//
// opCodeMask is used to record variants of an instruction.
// E.g., each branch instruction on SPARC has 2 flags (i.e., 4 variants):
private:
MachineOpCode opCode;
OpCodeMask opCodeMask; // extra bits for variants of an opcode
- vector<MachineOperand> operands; // operand 0 is the result
+ vector<MachineOperand> operands;
+
+public:
+ typedef ValOpIterator<const MachineInstr, const Value> val_op_const_iterator;
+ typedef ValOpIterator< MachineInstr, Value> val_op_iterator;
public:
/*ctor*/ MachineInstr (MachineOpCode _opCode,
OpCodeMask _opCodeMask = 0x0);
-
inline ~MachineInstr () {}
const MachineOpCode getOpCode () const;
unsigned int getNumOperands () const;
const MachineOperand& getOperand (unsigned int i) const;
+ MachineOperand& getOperand (unsigned int i);
void dump (unsigned int indent = 0);
public:
friend ostream& operator<<(ostream& os, const MachineInstr& minstr);
+ friend val_op_const_iterator;
+ friend val_op_iterator;
public:
// Access to set the operands when building the machine instruction
inline unsigned int
MachineInstr::getNumOperands() const
{
- assert(operands.size() == TargetMachineInstrInfo[opCode].numOperands);
return operands.size();
}
+inline MachineOperand&
+MachineInstr::getOperand(unsigned int i)
+{
+ return operands[i];
+}
+
inline const MachineOperand&
MachineInstr::getOperand(unsigned int i) const
{
}
+template<class _MI, class _V>
+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->getOperand(i).getOperandType() != MachineOperand::MO_VirtualRegister
+ && minstr->getOperand(i).getOperandType() != MachineOperand::MO_CCRegister)
+ ++i;
+ }
+
+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 done () const { return (i == minstr->getNumOperands()); }
+
+ inline _Self& operator++() { i++; skipToNextVal(); return *this; }
+ inline _Self operator++(int) { _Self tmp = *this; ++*this; return tmp; }
+};
+
+
//---------------------------------------------------------------------------
// class MachineInstructionsForVMInstr
//
MachineOperand::MachineOperandType
ChooseRegOrImmed(Value* val,
- MachineOpCode opCode,
- const TargetMachine& targetMachine,
- bool canUseImmed,
- MachineOperand::VirtualRegisterType& getVRegType,
- unsigned int& getMachineRegNum,
- int64_t& getImmedValue);
+ MachineOpCode opCode,
+ const TargetMachine& targetMachine,
+ bool canUseImmed,
+ unsigned int& getMachineRegNum,
+ int64_t& getImmedValue);
ostream& operator<<(ostream& os, const MachineInstr& minstr);
//************************ Class Implementations **************************/
-bool
-MachineInstrInfo::constantFitsInImmedField(int64_t intValue) const
-{
- // First, check if opCode has an immed field.
- bool isSignExtended;
- uint64_t maxImmedValue = this->maxImmedConstant(isSignExtended);
- if (maxImmedValue != 0)
- {
- // Now check if the constant fits
- if (intValue <= (int64_t) maxImmedValue &&
- intValue >= -((int64_t) maxImmedValue+1))
- return true;
- }
-
- return false;
-}
-
MachineInstr::MachineInstr(MachineOpCode _opCode,
OpCodeMask _opCodeMask)
: opCode(_opCode),
opCodeMask(_opCodeMask),
- operands(TargetMachineInstrInfo[_opCode].numOperands)
+ operands(TargetInstrDescriptors[_opCode].numOperands)
{
}
MachineOperand::MachineOperandType operandType,
Value* _val)
{
- assert(i < TargetMachineInstrInfo[opCode].numOperands);
+ assert(i < operands.size());
operands[i].Initialize(operandType, _val);
}
MachineOperand::MachineOperandType operandType,
int64_t intValue)
{
- assert(i < TargetMachineInstrInfo[opCode].numOperands);
+ assert(i < operands.size());
operands[i].InitializeConst(operandType, intValue);
}
MachineInstr::SetMachineOperand(unsigned int i,
unsigned int regNum)
{
- assert(i < TargetMachineInstrInfo[opCode].numOperands);
+ assert(i < operands.size());
operands[i].InitializeReg(regNum);
}
ostream&
operator<< (ostream& os, const MachineInstr& minstr)
{
- os << TargetMachineInstrInfo[minstr.opCode].opCodeString;
+ os << TargetInstrDescriptors[minstr.opCode].opCodeString;
for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++)
os << "\t" << minstr.getOperand(i);
+#undef DEBUG_VAL_OP_ITERATOR
+#ifdef DEBUG_VAL_OP_ITERATOR
+ os << endl << "\tValue operands are: ";
+ for (MachineInstr::val_op_const_iterator vo(&minstr); ! vo.done(); ++vo)
+ {
+ const Value* val = *vo;
+ os << val << (vo.isDef()? "(def), " : ", ");
+ }
+ os << endl;
+#endif
+
return os;
}
operator<< (ostream& os, const MachineOperand& mop)
{
strstream regInfo;
- if (mop.machineOperandType == MachineOperand::MO_Register)
- {
- if (mop.vregType == MachineOperand::MO_VirtualReg)
- regInfo << "(val " << mop.value << ")" << ends;
- else
- regInfo << "(" << mop.regNum << ")" << ends;
- }
- else if (mop.machineOperandType == MachineOperand::MO_CCRegister)
+ if (mop.opType == MachineOperand::MO_VirtualRegister)
+ regInfo << "(val " << mop.value << ")" << ends;
+ else if (mop.opType == MachineOperand::MO_MachineRegister)
+ regInfo << "(" << mop.regNum << ")" << ends;
+ else if (mop.opType == MachineOperand::MO_CCRegister)
regInfo << "(val " << mop.value << ")" << ends;
- switch(mop.machineOperandType)
+ switch(mop.opType)
{
- case MachineOperand::MO_Register:
+ case MachineOperand::MO_VirtualRegister:
+ case MachineOperand::MO_MachineRegister:
os << "%reg" << regInfo.str();
free(regInfo.str());
break;
void
Set2OperandsFromInstr(MachineInstr* minstr,
InstructionNode* vmInstrNode,
- const TargetMachine& targetMachine,
+ const TargetMachine& target,
bool canDiscardResult,
int op1Position,
int resultPosition)
{
- Set3OperandsFromInstr(minstr, vmInstrNode, targetMachine,
+ Set3OperandsFromInstr(minstr, vmInstrNode, target,
canDiscardResult, op1Position,
/*op2Position*/ -1, resultPosition);
}
-
+#undef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
+#ifdef REVERT_TO_EXPLICIT_CONSTANT_CHECKS
unsigned
Set3OperandsFromInstrJUNK(MachineInstr* minstr,
InstructionNode* vmInstrNode,
- const TargetMachine& targetMachine,
+ const TargetMachine& target,
bool canDiscardResult,
int op1Position,
int op2Position,
Value* op1Value = vmInstrNode->leftChild()->getValue();
bool isValidConstant;
int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant);
- if (isValidConstant && intValue == 0 && targetMachine.zeroRegNum >= 0)
- minstr->SetMachineOperand(op1Position, /*regNum*/ targetMachine.zeroRegNum);
+ if (isValidConstant && intValue == 0 && target.zeroRegNum >= 0)
+ minstr->SetMachineOperand(op1Position, /*regNum*/ target.zeroRegNum);
else
{
if (op1Value->getValueType() == Value::ConstantVal)
{// value is constant and must be loaded from constant pool
returnFlags = returnFlags | (1 << op1Position);
}
- minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register,
- op1Value);
+ minstr->SetMachineOperand(op1Position,MachineOperand::MO_VirtualRegister,
+ op1Value);
}
// Check if operand 2 (if any) fits in the immediate field of the instruction,
{
Value* op2Value = vmInstrNode->rightChild()->getValue();
int64_t immedValue;
- MachineOperand::VirtualRegisterType vregType;
unsigned int machineRegNum;
MachineOperand::MachineOperandType
- op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(),targetMachine,
+ op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(), target,
/*canUseImmed*/ true,
- vregType, machineRegNum, immedValue);
+ machineRegNum, immedValue);
- if (op2type == MachineOperand::MO_Register)
+ if (op2type == MachineOperand::MO_MachineRegister)
+ minstr->SetMachineOperand(op2Position, machineRegNum);
+ else if (op2type == MachineOperand::MO_VirtualRegister)
{
- if (vregType == MachineOperand::MO_MachineReg)
- minstr->SetMachineOperand(op2Position, machineRegNum);
- else
- {
- if (op2Value->getValueType() == Value::ConstantVal)
- {// value is constant and must be loaded from constant pool
- returnFlags = returnFlags | (1 << op2Position);
- }
- minstr->SetMachineOperand(op2Position, op2type, op2Value);
+ if (op2Value->getValueType() == Value::ConstantVal)
+ {// value is constant and must be loaded from constant pool
+ returnFlags = returnFlags | (1 << op2Position);
}
+ minstr->SetMachineOperand(op2Position, op2type, op2Value);
}
else
- minstr->SetMachineOperand(op2Position, op2type, immedValue);
+ {
+ assert(op2type != MO_CCRegister);
+ minstr->SetMachineOperand(op2Position, op2type, immedValue);
+ }
}
// If operand 3 (result) can be discarded, use a dead register if one exists
- if (canDiscardResult && targetMachine.zeroRegNum >= 0)
- minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum);
+ if (canDiscardResult && target.zeroRegNum >= 0)
+ minstr->SetMachineOperand(resultPosition, target.zeroRegNum);
else
- minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register,
- vmInstrNode->getValue());
+ minstr->SetMachineOperand(resultPosition, MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
return returnFlags;
}
+#endif
void
Set3OperandsFromInstr(MachineInstr* minstr,
InstructionNode* vmInstrNode,
- const TargetMachine& targetMachine,
+ const TargetMachine& target,
bool canDiscardResult,
int op1Position,
int op2Position,
assert(resultPosition >= 0);
// operand 1
- minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register,
+ minstr->SetMachineOperand(op1Position, MachineOperand::MO_VirtualRegister,
vmInstrNode->leftChild()->getValue());
// operand 2 (if any)
if (op2Position >= 0)
- minstr->SetMachineOperand(op2Position, MachineOperand::MO_Register,
+ minstr->SetMachineOperand(op2Position, MachineOperand::MO_VirtualRegister,
vmInstrNode->rightChild()->getValue());
// result operand: if it can be discarded, use a dead register if one exists
- if (canDiscardResult && targetMachine.zeroRegNum >= 0)
- minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum);
+ if (canDiscardResult && target.zeroRegNum >= 0)
+ minstr->SetMachineOperand(resultPosition, target.zeroRegNum);
else
- minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register,
- vmInstrNode->getValue());
+ minstr->SetMachineOperand(resultPosition, MachineOperand::MO_VirtualRegister, vmInstrNode->getValue());
}
MachineOperand::MachineOperandType
ChooseRegOrImmed(Value* val,
MachineOpCode opCode,
- const TargetMachine& targetMachine,
+ const TargetMachine& target,
bool canUseImmed,
- MachineOperand::VirtualRegisterType& getVRegType,
unsigned int& getMachineRegNum,
int64_t& getImmedValue)
{
- MachineOperand::MachineOperandType opType = MachineOperand::MO_Register;
- getVRegType = MachineOperand::MO_VirtualReg;
+ MachineOperand::MachineOperandType opType =
+ MachineOperand::MO_VirtualRegister;
getMachineRegNum = 0;
getImmedValue = 0;
if (isValidConstant)
{
- if (intValue == 0 && targetMachine.zeroRegNum >= 0)
+ if (intValue == 0 && target.zeroRegNum >= 0)
{
- getVRegType = MachineOperand::MO_MachineReg;
- getMachineRegNum = targetMachine.zeroRegNum;
+ opType = MachineOperand::MO_MachineRegister;
+ getMachineRegNum = target.zeroRegNum;
}
else if (canUseImmed &&
- targetMachine.machineInstrInfo[opCode].constantFitsInImmedField(intValue))
+ target.getInstrInfo().constantFitsInImmedField(opCode,intValue))
{
opType = MachineOperand::MO_SignExtendedImmed;
getImmedValue = intValue;