Newer
Older
//===-- MachineInstr.cpp --------------------------------------------------===//
Vikram S. Adve
committed
//
//===----------------------------------------------------------------------===//
Vikram S. Adve
committed
#include "llvm/CodeGen/MachineInstr.h"
Chris Lattner
committed
#include "llvm/Target/MachineInstrInfo.h" // FIXME: shouldn't need this!
#include "llvm/Target/TargetMachine.h"
// Global variable holding an array of descriptors for machine instructions.
// The actual object needs to be created separately for each target machine.
// This variable is initialized and reset by class MachineInstrInfo.
//
// FIXME: This should be a property of the target so that more than one target
// at a time can be active...
//
extern const MachineInstrDescriptor *TargetInstrDescriptors;
// Constructor for instructions with fixed #operands (nearly all)
MachineInstr::MachineInstr(MachineOpCode _opCode)
: opCode(_opCode),
operands(TargetInstrDescriptors[_opCode].numOperands, MachineOperand()),
numImplicitRefs(0)
{
assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
}
// Constructor for instructions with variable #operands
MachineInstr::MachineInstr(MachineOpCode OpCode, unsigned numOperands)
: opCode(OpCode),
operands(numOperands, MachineOperand()),
numImplicitRefs(0)
{
}
/// 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::MachineInstr(MachineOpCode Opcode, unsigned numOperands,
bool XX, bool YY)
: opCode(Opcode),
numImplicitRefs(0)
{
operands.reserve(numOperands);
}
/// 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::MachineInstr(MachineBasicBlock *MBB, MachineOpCode Opcode,
unsigned numOperands)
: opCode(Opcode),
numImplicitRefs(0)
{
assert(MBB && "Cannot use inserting ctor with null basic block!");
operands.reserve(numOperands);
MBB->push_back(this); // Add instruction to end of basic block!
}
// OperandComplete - Return true if it's illegal to add a new operand
bool MachineInstr::OperandsComplete() const
{
int NumOperands = TargetInstrDescriptors[opCode].numOperands;
if (NumOperands >= 0 && getNumOperands() >= (unsigned)NumOperands)
return true; // Broken!
return false;
Vikram S. Adve
committed
}
Vikram S. Adve
committed
//
// Support for replacing opcode and operands of a MachineInstr in place.
// This only resets the size of the operand vector and initializes it.
// The new operands must be set explicitly later.
//
void MachineInstr::replace(MachineOpCode Opcode, unsigned numOperands)
{
assert(getNumImplicitRefs() == 0 &&
"This is probably broken because implicit refs are going to be lost.");
opCode = Opcode;
Vikram S. Adve
committed
operands.clear();
operands.resize(numOperands, MachineOperand());
Vikram S. Adve
committed
}
Vikram S. Adve
committed
void
MachineInstr::SetMachineOperandVal(unsigned i,
MachineOperand::MachineOperandType opType,
Vikram S. Adve
committed
{
assert(i < operands.size()); // may be explicit or implicit op
operands[i].opType = opType;
operands[i].value = V;
operands[i].regNum = -1;
operands[i].flags = 0;
if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
operands[i].markDef();
if (isDefAndUse)
operands[i].markDefAndUse();
Vikram S. Adve
committed
}
void
MachineInstr::SetMachineOperandConst(unsigned i,
Vikram S. Adve
committed
MachineOperand::MachineOperandType operandType,
Vikram S. Adve
committed
{
assert(i < getNumOperands()); // must be explicit op
assert(TargetInstrDescriptors[opCode].resultPos != (int) i &&
"immed. constant cannot be defined");
operands[i].opType = operandType;
operands[i].value = NULL;
operands[i].immedVal = intValue;
operands[i].regNum = -1;
operands[i].flags = 0;
Vikram S. Adve
committed
}
void
MachineInstr::SetMachineOperandReg(unsigned i,
assert(i < getNumOperands()); // must be explicit op
operands[i].opType = MachineOperand::MO_MachineRegister;
operands[i].value = NULL;
operands[i].regNum = regNum;
operands[i].flags = 0;
if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
operands[i].markDef();
insertUsedReg(regNum);
Vikram S. Adve
committed
}
void
MachineInstr::SetRegForOperand(unsigned i, int regNum)
Vikram S. Adve
committed
{
assert(i < getNumOperands()); // must be explicit op
operands[i].setRegForValue(regNum);
insertUsedReg(regNum);
}
// Subsitute all occurrences of Value* oldVal with newVal in all operands
// and all implicit refs. If defsOnly == true, substitute defs only.
unsigned
MachineInstr::substituteValue(const Value* oldVal, Value* newVal, bool defsOnly)
{
unsigned numSubst = 0;
// Subsitute operands
for (MachineInstr::val_op_iterator O = begin(), E = end(); O != E; ++O)
if (*O == oldVal)
if (!defsOnly || O.isDef())
{
O.getMachineOperand().value = newVal;
++numSubst;
}
// Subsitute implicit refs
for (unsigned i=0, N=getNumImplicitRefs(); i < N; ++i)
if (getImplicitRef(i) == oldVal)
if (!defsOnly || implicitRefIsDefined(i))
{
getImplicitOp(i).value = newVal;
++numSubst;
}
return numSubst;
}
void
MachineInstr::dump() const
{
cerr << " " << *this;
Vikram S. Adve
committed
}
static inline std::ostream&
OutputValue(std::ostream &os, const Value* val)
{
os << "(val ";
if (val && val->hasName())
return os << val->getName() << ")";
return os << (void*) val << ")"; // print address only
static inline std::ostream&
OutputReg(std::ostream &os, unsigned int regNum)
{
return os << "%mreg(" << regNum << ")";
}
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
static void print(const MachineOperand &MO, std::ostream &OS,
const TargetMachine &TM) {
bool CloseParen = true;
if (MO.opHiBits32())
OS << "%lm(";
else if (MO.opLoBits32())
OS << "%lo(";
else if (MO.opHiBits64())
OS << "%hh(";
else if (MO.opLoBits64())
OS << "%hm(";
else
CloseParen = false;
switch (MO.getType()) {
case MachineOperand::MO_VirtualRegister:
if (MO.getVRegValue()) {
OS << "%reg";
OutputValue(OS, MO.getVRegValue());
if (MO.hasAllocatedReg())
OS << "==";
}
if (MO.hasAllocatedReg())
OutputReg(OS, MO.getAllocatedRegNum());
break;
case MachineOperand::MO_CCRegister:
OS << "%ccreg";
OutputValue(OS, MO.getVRegValue());
if (MO.hasAllocatedReg()) {
OS << "==";
OutputReg(OS, MO.getAllocatedRegNum());
}
break;
case MachineOperand::MO_MachineRegister:
OutputReg(OS, MO.getMachineRegNum());
break;
case MachineOperand::MO_SignExtendedImmed:
OS << (long)MO.getImmedValue();
break;
case MachineOperand::MO_UnextendedImmed:
OS << (long)MO.getImmedValue();
break;
case MachineOperand::MO_PCRelativeDisp: {
const Value* opVal = MO.getVRegValue();
bool isLabel = isa<Function>(opVal) || isa<BasicBlock>(opVal);
OS << "%disp(" << (isLabel? "label " : "addr-of-val ");
if (opVal->hasName())
OS << opVal->getName();
else
OS << (const void*) opVal;
OS << ")";
break;
}
default:
assert(0 && "Unrecognized operand type");
}
if (CloseParen)
OS << ")";
}
void MachineInstr::print(std::ostream &OS, const TargetMachine &TM) {
OS << TM.getInstrInfo().getName(getOpcode());
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
OS << "\t";
::print(getOperand(i), OS, TM);
if (operandIsDefinedAndUsed(i))
OS << "<def&use>";
else if (operandIsDefined(i))
OS << "<def>";
}
// code for printing implict references
if (getNumImplicitRefs()) {
OS << "\tImplicitRefs: ";
for(unsigned i = 0, e = getNumImplicitRefs(); i != e; ++i) {
OS << "\t";
OutputValue(OS, getImplicitRef(i));
if (implicitRefIsDefinedAndUsed(i))
OS << "<def&use>";
else if (implicitRefIsDefined(i))
OS << "<def>";
}
}
OS << "\n";
}
std::ostream &operator<<(std::ostream& os, const MachineInstr& minstr)
Vikram S. Adve
committed
{
os << TargetInstrDescriptors[minstr.opCode].Name;
Vikram S. Adve
committed
Ruchira Sasanka
committed
for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++) {
Vikram S. Adve
committed
os << "\t" << minstr.getOperand(i);
if( minstr.operandIsDefined(i) )
os << "*";
if( minstr.operandIsDefinedAndUsed(i) )
os << "*";
Ruchira Sasanka
committed
}
Vikram S. Adve
committed
// code for printing implict references
unsigned NumOfImpRefs = minstr.getNumImplicitRefs();
if( NumOfImpRefs > 0 ) {
for(unsigned z=0; z < NumOfImpRefs; z++) {
OutputValue(os, minstr.getImplicitRef(z));
Ruchira Sasanka
committed
if( minstr.implicitRefIsDefined(z)) os << "*";
if( minstr.implicitRefIsDefinedAndUsed(z)) os << "*";
os << "\t";
}
}
Vikram S. Adve
committed
}
std::ostream &operator<<(std::ostream &os, const MachineOperand &mop)
if (mop.opHiBits32())
os << "%lm(";
else if (mop.opLoBits32())
os << "%lo(";
else if (mop.opHiBits64())
os << "%hh(";
else if (mop.opLoBits64())
os << "%hm(";
{
case MachineOperand::MO_VirtualRegister:
os << "%reg";
OutputValue(os, mop.getVRegValue());
if (mop.hasAllocatedReg()) {
os << "==";
OutputReg(os, mop.getAllocatedRegNum());
}
OutputValue(os, mop.getVRegValue());
if (mop.hasAllocatedReg()) {
os << "==";
OutputReg(os, mop.getAllocatedRegNum());
}
break;
case MachineOperand::MO_MachineRegister:
OutputReg(os, mop.getMachineRegNum());
os << (long)mop.getImmedValue();
os << (long)mop.getImmedValue();
{
const Value* opVal = mop.getVRegValue();
bool isLabel = isa<Function>(opVal) || isa<BasicBlock>(opVal);
os << "%disp(" << (isLabel? "label " : "addr-of-val ");
if (opVal->hasName())
os << (const void*) opVal;
os << ")";
break;
default:
assert(0 && "Unrecognized operand type");
break;
}
if (mop.flags &
(MachineOperand::HIFLAG32 | MachineOperand::LOFLAG32 |
MachineOperand::HIFLAG64 | MachineOperand::LOFLAG64))
os << ")";
Vikram S. Adve
committed
return os;
}