Major overhaul of stack frame management.
[oota-llvm.git] / lib / CodeGen / MachineInstr.cpp
1 // $Id$
2 //***************************************************************************
3 // File:
4 //      MachineInstr.cpp
5 // 
6 // Purpose:
7 //      
8 // 
9 // Strategy:
10 // 
11 // History:
12 //      7/2/01   -  Vikram Adve  -  Created
13 //**************************************************************************/
14
15
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/Target/MachineFrameInfo.h"
18 #include "llvm/Target/MachineRegInfo.h"
19 #include "llvm/Method.h"
20 #include "llvm/iOther.h"
21 #include "llvm/Instruction.h"
22
23 AnnotationID MachineCodeForMethod::AID(
24                  AnnotationManager::getID("MachineCodeForMethodAnnotation"));
25
26
27 //************************ Class Implementations **************************/
28
29 // Constructor for instructions with fixed #operands (nearly all)
30 MachineInstr::MachineInstr(MachineOpCode _opCode,
31                            OpCodeMask    _opCodeMask)
32   : opCode(_opCode),
33     opCodeMask(_opCodeMask),
34     operands(TargetInstrDescriptors[_opCode].numOperands)
35 {
36   assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
37 }
38
39 // Constructor for instructions with variable #operands
40 MachineInstr::MachineInstr(MachineOpCode _opCode,
41                            unsigned      numOperands,
42                            OpCodeMask    _opCodeMask)
43   : opCode(_opCode),
44     opCodeMask(_opCodeMask),
45     operands(numOperands)
46 {
47 }
48
49 void
50 MachineInstr::SetMachineOperand(unsigned int i,
51                                 MachineOperand::MachineOperandType operandType,
52                                 Value* _val, bool isdef=false)
53 {
54   assert(i < operands.size());
55   operands[i].Initialize(operandType, _val);
56   operands[i].isDef = isdef ||
57     TargetInstrDescriptors[opCode].resultPos == (int) i;
58 }
59
60 void
61 MachineInstr::SetMachineOperand(unsigned int i,
62                                 MachineOperand::MachineOperandType operandType,
63                                 int64_t intValue, bool isdef=false)
64 {
65   assert(i < operands.size());
66   operands[i].InitializeConst(operandType, intValue);
67   operands[i].isDef = isdef ||
68     TargetInstrDescriptors[opCode].resultPos == (int) i;
69 }
70
71 void
72 MachineInstr::SetMachineOperand(unsigned int i,
73                                 int regNum, bool isdef=false)
74 {
75   assert(i < operands.size());
76   operands[i].InitializeReg(regNum);
77   operands[i].isDef = isdef ||
78     TargetInstrDescriptors[opCode].resultPos == (int) i;
79 }
80
81 void
82 MachineInstr::dump(unsigned int indent) const 
83 {
84   for (unsigned i=0; i < indent; i++)
85     cout << "    ";
86   
87   cout << *this;
88 }
89
90 ostream&
91 operator<< (ostream& os, const MachineInstr& minstr)
92 {
93   os << TargetInstrDescriptors[minstr.opCode].opCodeString;
94   
95   for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++)
96     os << "\t" << minstr.getOperand(i);
97   
98 #undef DEBUG_VAL_OP_ITERATOR
99 #ifdef DEBUG_VAL_OP_ITERATOR
100   os << endl << "\tValue operands are: ";
101   for (MachineInstr::val_op_const_iterator vo(&minstr); ! vo.done(); ++vo)
102     {
103       const Value* val = *vo;
104       os << val << (vo.isDef()? "(def), " : ", ");
105     }
106 #endif
107   
108  
109
110 #if 1
111   // code for printing implict references
112
113   unsigned NumOfImpRefs =  minstr.getNumImplicitRefs();
114   if(  NumOfImpRefs > 0 ) {
115         
116     os << "\tImplicit:";
117
118     for(unsigned z=0; z < NumOfImpRefs; z++) {
119       os << minstr.getImplicitRef(z);
120           cout << "\t";
121     }
122   }
123
124 #endif
125
126
127   os << endl;
128   
129   return os;
130 }
131
132 static inline ostream&
133 OutputOperand(ostream &os, const MachineOperand &mop)
134 {
135   switch (mop.getOperandType())
136     {
137     case MachineOperand::MO_CCRegister:
138     case MachineOperand::MO_VirtualRegister:
139       return os << "(val " << mop.getVRegValue() << ")";
140     case MachineOperand::MO_MachineRegister:
141       return os << "("     << mop.getMachineRegNum() << ")";
142     default:
143       assert(0 && "Unknown operand type");
144       return os;
145     }
146 }
147
148
149 ostream&
150 operator<<(ostream &os, const MachineOperand &mop)
151 {
152   switch(mop.opType)
153     {
154     case MachineOperand::MO_VirtualRegister:
155     case MachineOperand::MO_MachineRegister:
156       os << "%reg";
157       return OutputOperand(os, mop);
158     case MachineOperand::MO_CCRegister:
159       os << "%ccreg";
160       return OutputOperand(os, mop);
161     case MachineOperand::MO_SignExtendedImmed:
162       return os << mop.immedVal;
163     case MachineOperand::MO_UnextendedImmed:
164       return os << mop.immedVal;
165     case MachineOperand::MO_PCRelativeDisp:
166       {
167         const Value* opVal = mop.getVRegValue();
168         bool isLabel = isa<Method>(opVal) || isa<BasicBlock>(opVal);
169         return os << "%disp("
170                   << (isLabel? "label " : "addr-of-val ")
171                   << opVal << ")";
172       }
173     default:
174       assert(0 && "Unrecognized operand type");
175       break;
176     }
177   
178   return os;
179 }
180
181 static unsigned int
182 ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method)
183 {
184   const MachineFrameInfo& frameInfo = target.getFrameInfo();
185   
186   unsigned int maxSize = 0;
187   
188   for (Method::inst_const_iterator I=method->inst_begin(),E=method->inst_end();
189        I != E; ++I)
190     if ((*I)->getOpcode() == Instruction::Call)
191       {
192         CallInst* callInst = cast<CallInst>(*I);
193         unsigned int numOperands = callInst->getNumOperands() - 1;
194         unsigned int numExtra = numOperands
195                                 - frameInfo.getNumFixedOutgoingArgs();
196         
197         unsigned int sizeForThisCall;
198         if (frameInfo.argsOnStackHaveFixedSize())
199           {
200             int argSize = frameInfo.getSizeOfEachArgOnStack(); 
201             sizeForThisCall = numExtra * (unsigned) argSize;
202           }
203         else
204           {
205             assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual arg sizes to compute MaxOptionalArgsSize");
206             sizeForThisCall = 0;
207             for (unsigned i=0; i < numOperands; ++i)
208               sizeForThisCall += target.findOptimalStorageSize(callInst->
209                                                     getOperand(i)->getType());
210           }
211         
212         if (maxSize < sizeForThisCall)
213           maxSize = sizeForThisCall;
214       }
215   
216   return maxSize;
217 }
218
219
220 /*ctor*/
221 MachineCodeForMethod::MachineCodeForMethod(const Method* _M,
222                                            const TargetMachine& target)
223   : Annotation(AID),
224     method(_M), compiledAsLeaf(false), staticStackSize(0),
225     automaticVarsSize(0), regSpillsSize(0),
226     currentOptionalArgsSize(0), maxOptionalArgsSize(0),
227     currentTmpValuesSize(0)
228 {
229   maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method);
230   staticStackSize = maxOptionalArgsSize +
231                     target.getFrameInfo().getMinStackFrameSize();
232 }
233
234 int
235 MachineCodeForMethod::allocateLocalVar(const TargetMachine& target,
236                                        const Value* val)
237 {
238   // Check if we've allocated a stack slot for this value already
239   // 
240   int offset = getOffset(val);
241   if (offset == INVALID_FRAME_OFFSET)
242     {
243       bool growUp;
244       int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this,
245                                                                        growUp);
246       offset = growUp? firstOffset + getAutomaticVarsSize()
247                      : firstOffset - getAutomaticVarsSize();
248       offsets[val] = offset;
249       
250       unsigned int size = target.findOptimalStorageSize(val->getType());
251       incrementAutomaticVarsSize(size);
252     }
253   return offset;
254 }
255
256 int
257 MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target,
258                                            const Type* type)
259 {
260   bool growUp;
261   int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp);
262   int offset = growUp? firstOffset + getRegSpillsSize()
263                      : firstOffset - getRegSpillsSize();
264   
265   unsigned int size = target.findOptimalStorageSize(type);
266   incrementRegSpillsSize(size);
267   
268   return offset;
269 }
270   
271 int
272 MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target,
273                                           const Type* type)
274 {
275   const MachineFrameInfo& frameInfo = target.getFrameInfo();
276   bool growUp;
277   int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp);
278   int offset = growUp? firstOffset + getCurrentOptionalArgsSize()
279                      : firstOffset - getCurrentOptionalArgsSize();
280   
281   int size = MAXINT;
282   if (frameInfo.argsOnStackHaveFixedSize())
283     size = frameInfo.getSizeOfEachArgOnStack(); 
284   else
285     {
286       assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets");
287       size = target.findOptimalStorageSize(type);
288     }
289   
290   incrementCurrentOptionalArgsSize(size);
291   
292   return offset;
293 }
294
295 void
296 MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target)
297 {
298   currentOptionalArgsSize = 0;
299 }
300
301 int
302 MachineCodeForMethod::pushTempValue(const TargetMachine& target,
303                                     unsigned int size)
304 {
305   bool growUp;
306   int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp);
307   int offset = growUp? firstTmpOffset + currentTmpValuesSize
308                      : firstTmpOffset - currentTmpValuesSize;
309   currentTmpValuesSize += size;
310   return offset;
311 }
312
313 void
314 MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
315 {
316   currentTmpValuesSize = 0;
317 }
318
319
320 // void
321 // MachineCodeForMethod::putLocalVarAtOffsetFromSP(const Value* local,
322 //                                                 int offset,
323 //                                                 unsigned int size)
324 // {
325 //   offsetsFromSP[local] = offset;
326 //   incrementAutomaticVarsSize(size);
327 // }
328 // 
329
330 int
331 MachineCodeForMethod::getOffset(const Value* val) const
332 {
333   hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
334   return (pair == offsets.end())? INVALID_FRAME_OFFSET : (*pair).second;
335 }
336
337
338 // int
339 // MachineCodeForMethod::getOffsetFromSP(const Value* local) const
340 // {
341 //   hash_map<const Value*, int>::const_iterator pair = offsetsFromSP.find(local);
342 //   return (pair == offsetsFromSP.end())? INVALID_FRAME_OFFSET : (*pair).second;
343 // }
344
345
346 void
347 MachineCodeForMethod::dump() const
348 {
349   cout << "\n" << method->getReturnType()
350        << " \"" << method->getName() << "\"" << endl;
351   
352   for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI)
353     {
354       BasicBlock* bb = *BI;
355       cout << "\n"
356            << (bb->hasName()? bb->getName() : "Label")
357            << " (" << bb << ")" << ":"
358            << endl;
359       
360       MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
361       for (unsigned i=0; i < mvec.size(); i++)
362         cout << "\t" << *mvec[i];
363     } 
364   cout << endl << "End method \"" << method->getName() << "\""
365        << endl << endl;
366 }