Remove separate vector of implicit refs from MachineInstr, and
[oota-llvm.git] / lib / CodeGen / MachineInstr.cpp
1 //===-- MachineInstr.cpp --------------------------------------------------===//
2 // 
3 //===----------------------------------------------------------------------===//
4
5 #include "llvm/CodeGen/MachineInstr.h"
6 #include "llvm/Value.h"
7 #include "llvm/Target/MachineInstrInfo.h"  // FIXME: shouldn't need this!
8 using std::cerr;
9
10 // Global variable holding an array of descriptors for machine instructions.
11 // The actual object needs to be created separately for each target machine.
12 // This variable is initialized and reset by class MachineInstrInfo.
13 // 
14 // FIXME: This should be a property of the target so that more than one target
15 // at a time can be active...
16 //
17 extern const MachineInstrDescriptor *TargetInstrDescriptors;
18
19 // Constructor for instructions with fixed #operands (nearly all)
20 MachineInstr::MachineInstr(MachineOpCode _opCode)
21   : opCode(_opCode),
22     operands(TargetInstrDescriptors[_opCode].numOperands, MachineOperand()),
23     numImplicitRefs(0)
24 {
25   assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
26 }
27
28 // Constructor for instructions with variable #operands
29 MachineInstr::MachineInstr(MachineOpCode OpCode, unsigned  numOperands)
30   : opCode(OpCode),
31     operands(numOperands, MachineOperand()),
32     numImplicitRefs(0)
33 {
34 }
35
36 MachineInstr::MachineInstr(MachineOpCode Opcode, unsigned numOperands,
37                            bool XX, bool YY)
38   : opCode(Opcode),
39     numImplicitRefs(0)
40 {
41   operands.reserve(numOperands);
42 }
43
44 // OperandComplete - Return true if it's illegal to add a new operand
45 bool MachineInstr::OperandsComplete() const
46 {
47   int NumOperands = TargetInstrDescriptors[opCode].numOperands;
48   if (NumOperands >= 0 && getNumOperands() >= (unsigned)NumOperands)
49     return true;  // Broken!
50   return false;
51 }
52
53
54 // 
55 // Support for replacing opcode and operands of a MachineInstr in place.
56 // This only resets the size of the operand vector and initializes it.
57 // The new operands must be set explicitly later.
58 // 
59 void MachineInstr::replace(MachineOpCode Opcode, unsigned numOperands)
60 {
61   assert(getNumImplicitRefs() == 0 &&
62          "This is probably broken because implicit refs are going to be lost.");
63   opCode = Opcode;
64   operands.clear();
65   operands.resize(numOperands, MachineOperand());
66 }
67
68 void
69 MachineInstr::SetMachineOperandVal(unsigned i,
70                                    MachineOperand::MachineOperandType opType,
71                                    Value* V,
72                                    bool isdef,
73                                    bool isDefAndUse)
74 {
75   assert(i < operands.size());          // may be explicit or implicit op
76   operands[i].opType = opType;
77   operands[i].value = V;
78   operands[i].regNum = -1;
79   operands[i].flags = 0;
80
81   if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
82     operands[i].markDef();
83   if (isDefAndUse)
84     operands[i].markDefAndUse();
85 }
86
87 void
88 MachineInstr::SetMachineOperandConst(unsigned i,
89                                 MachineOperand::MachineOperandType operandType,
90                                      int64_t intValue)
91 {
92   assert(i < getNumOperands());          // must be explicit op
93   assert(TargetInstrDescriptors[opCode].resultPos != (int) i &&
94          "immed. constant cannot be defined");
95
96   operands[i].opType = operandType;
97   operands[i].value = NULL;
98   operands[i].immedVal = intValue;
99   operands[i].regNum = -1;
100   operands[i].flags = 0;
101 }
102
103 void
104 MachineInstr::SetMachineOperandReg(unsigned i,
105                                    int regNum,
106                                    bool isdef) {
107   assert(i < getNumOperands());          // must be explicit op
108
109   operands[i].opType = MachineOperand::MO_MachineRegister;
110   operands[i].value = NULL;
111   operands[i].regNum = regNum;
112   operands[i].flags = 0;
113
114   if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
115     operands[i].markDef();
116   insertUsedReg(regNum);
117 }
118
119 void
120 MachineInstr::SetRegForOperand(unsigned i, int regNum)
121 {
122   assert(i < getNumOperands());          // must be explicit op
123   operands[i].setRegForValue(regNum);
124   insertUsedReg(regNum);
125 }
126
127
128 // Subsitute all occurrences of Value* oldVal with newVal in all operands
129 // and all implicit refs.  If defsOnly == true, substitute defs only.
130 unsigned
131 MachineInstr::substituteValue(const Value* oldVal, Value* newVal, bool defsOnly)
132 {
133   unsigned numSubst = 0;
134
135   // Subsitute operands
136   for (MachineInstr::val_op_iterator O = begin(), E = end(); O != E; ++O)
137     if (*O == oldVal)
138       if (!defsOnly || O.isDef())
139         {
140           O.getMachineOperand().value = newVal;
141           ++numSubst;
142         }
143
144   // Subsitute implicit refs
145   for (unsigned i=0, N=getNumImplicitRefs(); i < N; ++i)
146     if (getImplicitRef(i) == oldVal)
147       if (!defsOnly || implicitRefIsDefined(i))
148         {
149           getImplicitOp(i).value = newVal;
150           ++numSubst;
151         }
152
153   return numSubst;
154 }
155
156
157 void
158 MachineInstr::dump() const 
159 {
160   cerr << "  " << *this;
161 }
162
163 static inline std::ostream&
164 OutputValue(std::ostream &os, const Value* val)
165 {
166   os << "(val ";
167   if (val && val->hasName())
168     return os << val->getName() << ")";
169   else
170     return os << (void*) val << ")";              // print address only
171 }
172
173 static inline std::ostream&
174 OutputReg(std::ostream &os, unsigned int regNum)
175 {
176   return os << "%mreg(" << regNum << ")";
177 }
178
179 std::ostream &operator<<(std::ostream& os, const MachineInstr& minstr)
180 {
181   os << TargetInstrDescriptors[minstr.opCode].Name;
182   
183   for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++) {
184     os << "\t" << minstr.getOperand(i);
185     if( minstr.operandIsDefined(i) ) 
186       os << "*";
187     if( minstr.operandIsDefinedAndUsed(i) ) 
188       os << "*";
189   }
190   
191   // code for printing implict references
192   unsigned NumOfImpRefs =  minstr.getNumImplicitRefs();
193   if(  NumOfImpRefs > 0 ) {
194     os << "\tImplicit: ";
195     for(unsigned z=0; z < NumOfImpRefs; z++) {
196       OutputValue(os, minstr.getImplicitRef(z)); 
197       if( minstr.implicitRefIsDefined(z)) os << "*";
198       if( minstr.implicitRefIsDefinedAndUsed(z)) os << "*";
199       os << "\t";
200     }
201   }
202   
203   return os << "\n";
204 }
205
206 std::ostream &operator<<(std::ostream &os, const MachineOperand &mop)
207 {
208   if (mop.opHiBits32())
209     os << "%lm(";
210   else if (mop.opLoBits32())
211     os << "%lo(";
212   else if (mop.opHiBits64())
213     os << "%hh(";
214   else if (mop.opLoBits64())
215     os << "%hm(";
216   
217   switch(mop.opType)
218     {
219     case MachineOperand::MO_VirtualRegister:
220       os << "%reg";
221       OutputValue(os, mop.getVRegValue());
222       if (mop.hasAllocatedReg())
223         os << "==" << OutputReg(os, mop.getAllocatedRegNum());
224       break;
225     case MachineOperand::MO_CCRegister:
226       os << "%ccreg";
227       OutputValue(os, mop.getVRegValue());
228       if (mop.hasAllocatedReg())
229         os << "==" << OutputReg(os, mop.getAllocatedRegNum());
230       break;
231     case MachineOperand::MO_MachineRegister:
232       OutputReg(os, mop.getMachineRegNum());
233       break;
234     case MachineOperand::MO_SignExtendedImmed:
235       os << (long)mop.immedVal;
236       break;
237     case MachineOperand::MO_UnextendedImmed:
238       os << (long)mop.immedVal;
239       break;
240     case MachineOperand::MO_PCRelativeDisp:
241       {
242         const Value* opVal = mop.getVRegValue();
243         bool isLabel = isa<Function>(opVal) || isa<BasicBlock>(opVal);
244         os << "%disp(" << (isLabel? "label " : "addr-of-val ");
245         if (opVal->hasName())
246           os << opVal->getName();
247         else
248           os << (const void*) opVal;
249         os << ")";
250         break;
251       }
252     default:
253       assert(0 && "Unrecognized operand type");
254       break;
255     }
256   
257   if (mop.flags &
258       (MachineOperand::HIFLAG32 | MachineOperand::LOFLAG32 | 
259        MachineOperand::HIFLAG64 | MachineOperand::LOFLAG64))
260     os << ")";
261   
262   return os;
263 }