MachineInstr.cpp revision e492c9d4d1a161cd0972bfb8bab33f073fb018b4
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
23AnnotationID MachineCodeForMethod::AID(
24                 AnnotationManager::getID("MachineCodeForMethodAnnotation"));
25
26
27//************************ Class Implementations **************************/
28
29// Constructor for instructions with fixed #operands (nearly all)
30MachineInstr::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
40MachineInstr::MachineInstr(MachineOpCode _opCode,
41			   unsigned	 numOperands,
42			   OpCodeMask    _opCodeMask)
43  : opCode(_opCode),
44    opCodeMask(_opCodeMask),
45    operands(numOperands)
46{
47}
48
49void
50MachineInstr::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
60void
61MachineInstr::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
71void
72MachineInstr::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
81void
82MachineInstr::dump(unsigned int indent) const
83{
84  for (unsigned i=0; i < indent; i++)
85    cout << "    ";
86
87  cout << *this;
88}
89
90ostream&
91operator<< (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
132static inline ostream&
133OutputOperand(ostream &os, const MachineOperand &mop)
134{
135  Value* val;
136  switch (mop.getOperandType())
137    {
138    case MachineOperand::MO_CCRegister:
139    case MachineOperand::MO_VirtualRegister:
140      val = mop.getVRegValue();
141      os << "(val ";
142      if (val && val->hasName())
143        os << val->getName().c_str();
144      else
145        os << val;
146      return os << ")";
147    case MachineOperand::MO_MachineRegister:
148      return os << "("     << mop.getMachineRegNum() << ")";
149    default:
150      assert(0 && "Unknown operand type");
151      return os;
152    }
153}
154
155
156ostream&
157operator<<(ostream &os, const MachineOperand &mop)
158{
159  switch(mop.opType)
160    {
161    case MachineOperand::MO_VirtualRegister:
162    case MachineOperand::MO_MachineRegister:
163      os << "%reg";
164      return OutputOperand(os, mop);
165    case MachineOperand::MO_CCRegister:
166      os << "%ccreg";
167      return OutputOperand(os, mop);
168    case MachineOperand::MO_SignExtendedImmed:
169      return os << mop.immedVal;
170    case MachineOperand::MO_UnextendedImmed:
171      return os << mop.immedVal;
172    case MachineOperand::MO_PCRelativeDisp:
173      {
174        const Value* opVal = mop.getVRegValue();
175        bool isLabel = isa<Method>(opVal) || isa<BasicBlock>(opVal);
176        os << "%disp(" << (isLabel? "label " : "addr-of-val ");
177        if (opVal->hasName())
178          os << opVal->getName().c_str();
179        else
180          os << opVal;
181        return os << ")";
182      }
183    default:
184      assert(0 && "Unrecognized operand type");
185      break;
186    }
187
188  return os;
189}
190
191static unsigned int
192ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method)
193{
194  const MachineFrameInfo& frameInfo = target.getFrameInfo();
195
196  unsigned int maxSize = 0;
197
198  for (Method::inst_const_iterator I=method->inst_begin(),E=method->inst_end();
199       I != E; ++I)
200    if ((*I)->getOpcode() == Instruction::Call)
201      {
202        CallInst* callInst = cast<CallInst>(*I);
203        unsigned int numOperands = callInst->getNumOperands() - 1;
204        int numExtra = (int) numOperands - frameInfo.getNumFixedOutgoingArgs();
205        if (numExtra <= 0)
206          continue;
207
208        unsigned int sizeForThisCall;
209        if (frameInfo.argsOnStackHaveFixedSize())
210          {
211            int argSize = frameInfo.getSizeOfEachArgOnStack();
212            sizeForThisCall = numExtra * (unsigned) argSize;
213          }
214        else
215          {
216            assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual arg sizes to compute MaxOptionalArgsSize");
217            sizeForThisCall = 0;
218            for (unsigned i=0; i < numOperands; ++i)
219              sizeForThisCall += target.findOptimalStorageSize(callInst->
220                                                    getOperand(i)->getType());
221          }
222
223        if (maxSize < sizeForThisCall)
224          maxSize = sizeForThisCall;
225      }
226
227  return maxSize;
228}
229
230
231/*ctor*/
232MachineCodeForMethod::MachineCodeForMethod(const Method* _M,
233                                           const TargetMachine& target)
234  : Annotation(AID),
235    method(_M), compiledAsLeaf(false), staticStackSize(0),
236    automaticVarsSize(0), regSpillsSize(0),
237    currentOptionalArgsSize(0), maxOptionalArgsSize(0),
238    currentTmpValuesSize(0)
239{
240  maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method);
241  staticStackSize = maxOptionalArgsSize +
242                    target.getFrameInfo().getMinStackFrameSize();
243}
244
245int
246MachineCodeForMethod::allocateLocalVar(const TargetMachine& target,
247                                       const Value* val)
248{
249  // Check if we've allocated a stack slot for this value already
250  //
251  int offset = getOffset(val);
252  if (offset == INVALID_FRAME_OFFSET)
253    {
254      bool growUp;
255      int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this,
256                                                                       growUp);
257      unsigned int  size  = target.findOptimalStorageSize(val->getType());
258      unsigned char align = target.DataLayout.getTypeAlignment(val->getType());
259
260      offset = getAutomaticVarsSize();
261      if (! growUp)
262        offset += size;
263
264      if (unsigned int mod = offset % align)
265        {
266          offset += align - mod;
267          size   += align - mod;
268        }
269
270      offset = growUp? firstOffset + offset
271                     : firstOffset - offset;
272
273      offsets[val] = offset;
274
275      incrementAutomaticVarsSize(size);
276    }
277  return offset;
278}
279
280int
281MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target,
282                                           const Type* type)
283{
284  unsigned int size  = target.findOptimalStorageSize(type);
285  unsigned char align = target.DataLayout.getTypeAlignment(type);
286
287  bool growUp;
288  int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp);
289
290  int offset = getRegSpillsSize();
291  if (! growUp)
292    offset += size;
293
294  if (unsigned int mod = offset % align)
295    {
296      offset    += align - mod;
297      size += align - mod;
298    }
299
300  offset = growUp? firstOffset + offset
301                 : firstOffset - offset;
302
303  incrementRegSpillsSize(size);
304
305  return offset;
306}
307
308int
309MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target,
310                                          const Type* type)
311{
312  const MachineFrameInfo& frameInfo = target.getFrameInfo();
313
314  int size = MAXINT;
315  if (frameInfo.argsOnStackHaveFixedSize())
316    size = frameInfo.getSizeOfEachArgOnStack();
317  else
318    {
319      size = target.findOptimalStorageSize(type);
320      assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets");
321    }
322  unsigned char align = target.DataLayout.getTypeAlignment(type);
323
324  bool growUp;
325  int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp);
326
327  int offset = getCurrentOptionalArgsSize();
328  if (! growUp)
329    offset += size;
330
331  if (unsigned int mod = offset % align)
332    {
333      offset += align - mod;
334      size   += align - mod;
335    }
336
337  offset = growUp? firstOffset + offset
338                 : firstOffset - offset;
339
340  incrementCurrentOptionalArgsSize(size);
341
342  return offset;
343}
344
345void
346MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target)
347{
348  currentOptionalArgsSize = 0;
349}
350
351int
352MachineCodeForMethod::pushTempValue(const TargetMachine& target,
353                                    unsigned int size)
354{
355  // Compute a power-of-2 alignment according to the possible sizes,
356  // but not greater than the alignment of the largest type we support
357  // (currently a double word -- see class TargetData).
358  unsigned char align = 1;
359  for (; align < size && align < target.DataLayout.getDoubleAlignment();
360         align = 2*align)
361    ;
362
363  bool growUp;
364  int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp);
365
366  int offset = currentTmpValuesSize;
367  if (! growUp)
368    offset += size;
369
370  if (unsigned int mod = offset % align)
371    {
372      offset += align - mod;
373      size   += align - mod;
374    }
375
376  offset = growUp? firstTmpOffset + offset
377                 : firstTmpOffset - offset;
378
379  currentTmpValuesSize += size;
380  return offset;
381}
382
383void
384MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
385{
386  currentTmpValuesSize = 0;
387}
388
389int
390MachineCodeForMethod::getOffset(const Value* val) const
391{
392  hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
393  return (pair == offsets.end())? INVALID_FRAME_OFFSET : (*pair).second;
394}
395
396void
397MachineCodeForMethod::dump() const
398{
399  cout << "\n" << method->getReturnType()
400       << " \"" << method->getName() << "\"" << endl;
401
402  for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI)
403    {
404      BasicBlock* bb = *BI;
405      cout << "\n"
406	   << (bb->hasName()? bb->getName() : "Label")
407	   << " (" << bb << ")" << ":"
408	   << endl;
409
410      MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
411      for (unsigned i=0; i < mvec.size(); i++)
412	cout << "\t" << *mvec[i];
413    }
414  cout << endl << "End method \"" << method->getName() << "\""
415       << endl << endl;
416}
417