Add support for GCC 2.96
[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 using std::cerr;
8
9
10 // Constructor for instructions with fixed #operands (nearly all)
11 MachineInstr::MachineInstr(MachineOpCode _opCode,
12                            OpCodeMask    _opCodeMask)
13   : opCode(_opCode),
14     opCodeMask(_opCodeMask),
15     operands(TargetInstrDescriptors[_opCode].numOperands)
16 {
17   assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
18 }
19
20 // Constructor for instructions with variable #operands
21 MachineInstr::MachineInstr(MachineOpCode _opCode,
22                            unsigned      numOperands,
23                            OpCodeMask    _opCodeMask)
24   : opCode(_opCode),
25     opCodeMask(_opCodeMask),
26     operands(numOperands)
27 {
28 }
29
30 void
31 MachineInstr::SetMachineOperandVal(unsigned int i,
32                                    MachineOperand::MachineOperandType opType,
33                                    Value* _val,
34                                    bool isdef,
35                                    bool isDefAndUse)
36 {
37   assert(i < operands.size());
38   operands[i].Initialize(opType, _val);
39   if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
40     operands[i].markDef();
41   if (isDefAndUse)
42     operands[i].markDefAndUse();
43 }
44
45 void
46 MachineInstr::SetMachineOperandConst(unsigned int i,
47                                 MachineOperand::MachineOperandType operandType,
48                                      int64_t intValue)
49 {
50   assert(i < operands.size());
51   assert(TargetInstrDescriptors[opCode].resultPos != (int) i &&
52          "immed. constant cannot be defined");
53   operands[i].InitializeConst(operandType, intValue);
54 }
55
56 void
57 MachineInstr::SetMachineOperandReg(unsigned int i,
58                                    int regNum,
59                                    bool isdef,
60                                    bool isDefAndUse,
61                                    bool isCCReg)
62 {
63   assert(i < operands.size());
64   operands[i].InitializeReg(regNum, isCCReg);
65   if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
66     operands[i].markDef();
67   if (isDefAndUse)
68     operands[i].markDefAndUse();
69   regsUsed.insert(regNum);
70 }
71
72 void
73 MachineInstr::SetRegForOperand(unsigned i, int regNum)
74 {
75   operands[i].setRegForValue(regNum);
76   regsUsed.insert(regNum);
77 }
78
79
80 // Subsitute all occurrences of Value* oldVal with newVal in all operands
81 // and all implicit refs.  If defsOnly == true, substitute defs only.
82 unsigned
83 MachineInstr::substituteValue(const Value* oldVal, Value* newVal, bool defsOnly)
84 {
85   unsigned numSubst = 0;
86
87   // Subsitute operands
88   for (MachineInstr::val_op_iterator O = begin(), E = end(); O != E; ++O)
89     if (*O == oldVal)
90       if (!defsOnly || O.isDef())
91         {
92           O.getMachineOperand().value = newVal;
93           ++numSubst;
94         }
95
96   // Subsitute implicit refs
97   for (unsigned i=0, N=implicitRefs.size(); i < N; ++i)
98     if (implicitRefs[i] == oldVal)
99       if (!defsOnly || implicitRefIsDefined(i))
100         {
101           implicitRefs[i] = newVal;
102           ++numSubst;
103         }
104
105   return numSubst;
106 }
107
108
109 void
110 MachineInstr::dump() const 
111 {
112   cerr << "  " << *this;
113 }
114
115 static inline std::ostream&
116 OutputValue(std::ostream &os, const Value* val)
117 {
118   os << "(val ";
119   if (val && val->hasName())
120     return os << val->getName() << ")";
121   else
122     return os << (void*) val << ")";              // print address only
123 }
124
125 static inline std::ostream&
126 OutputReg(std::ostream &os, unsigned int regNum)
127 {
128   return os << "%mreg(" << regNum << ")";
129 }
130
131 std::ostream &operator<<(std::ostream& os, const MachineInstr& minstr)
132 {
133   os << TargetInstrDescriptors[minstr.opCode].opCodeString;
134   
135   for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++) {
136     os << "\t" << minstr.getOperand(i);
137     if( minstr.operandIsDefined(i) ) 
138       os << "*";
139     if( minstr.operandIsDefinedAndUsed(i) ) 
140       os << "*";
141   }
142   
143   // code for printing implict references
144   unsigned NumOfImpRefs =  minstr.getNumImplicitRefs();
145   if(  NumOfImpRefs > 0 ) {
146     os << "\tImplicit: ";
147     for(unsigned z=0; z < NumOfImpRefs; z++) {
148       OutputValue(os, minstr.getImplicitRef(z)); 
149       if( minstr.implicitRefIsDefined(z)) os << "*";
150       if( minstr.implicitRefIsDefinedAndUsed(z)) os << "*";
151       os << "\t";
152     }
153   }
154   
155   return os << "\n";
156 }
157
158 std::ostream &operator<<(std::ostream &os, const MachineOperand &mop)
159 {
160   if (mop.opHiBits32())
161     os << "%lm(";
162   else if (mop.opLoBits32())
163     os << "%lo(";
164   else if (mop.opHiBits64())
165     os << "%hh(";
166   else if (mop.opLoBits64())
167     os << "%hm(";
168   
169   switch(mop.opType)
170     {
171     case MachineOperand::MO_VirtualRegister:
172       os << "%reg";
173       OutputValue(os, mop.getVRegValue());
174       if (mop.hasAllocatedReg())
175         os << "==" << OutputReg(os, mop.getAllocatedRegNum());
176       break;
177     case MachineOperand::MO_CCRegister:
178       os << "%ccreg";
179       OutputValue(os, mop.getVRegValue());
180       if (mop.hasAllocatedReg())
181         os << "==" << OutputReg(os, mop.getAllocatedRegNum());
182       break;
183     case MachineOperand::MO_MachineRegister:
184       OutputReg(os, mop.getMachineRegNum());
185       break;
186     case MachineOperand::MO_SignExtendedImmed:
187       os << (long)mop.immedVal;
188       break;
189     case MachineOperand::MO_UnextendedImmed:
190       os << (long)mop.immedVal;
191       break;
192     case MachineOperand::MO_PCRelativeDisp:
193       {
194         const Value* opVal = mop.getVRegValue();
195         bool isLabel = isa<Function>(opVal) || isa<BasicBlock>(opVal);
196         os << "%disp(" << (isLabel? "label " : "addr-of-val ");
197         if (opVal->hasName())
198           os << opVal->getName();
199         else
200           os << (const void*) opVal;
201         os << ")";
202         break;
203       }
204     default:
205       assert(0 && "Unrecognized operand type");
206       break;
207     }
208   
209   if (mop.flags &
210       (MachineOperand::HIFLAG32 | MachineOperand::LOFLAG32 | 
211        MachineOperand::HIFLAG64 | MachineOperand::LOFLAG64))
212     os << ")";
213   
214   return os;
215 }