MachineInstr.cpp revision d9beb975f20cea2d3e9c3f528068cd25b80a1b72
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      unsigned int  size  = target.findOptimalStorageSize(val->getType());
255      unsigned char align = target.DataLayout.getTypeAlignment(val->getType());
256
257      offset = getAutomaticVarsSize();
258      if (unsigned int mod = offset % align)
259        {
260          offset += align - mod;
261          size   += align - mod;
262        }
263
264      bool growUp;
265      int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this,
266                                                                       growUp);
267      offset = growUp? firstOffset + offset
268                     : firstOffset - offset - size;
269
270      offsets[val] = offset;
271
272      incrementAutomaticVarsSize(size);
273    }
274  return offset;
275}
276
277int
278MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target,
279                                           const Type* type)
280{
281  unsigned int size  = target.findOptimalStorageSize(type);
282  unsigned char align = target.DataLayout.getTypeAlignment(type);
283
284  int offset = getRegSpillsSize();
285  if (unsigned int mod = offset % align)
286    {
287      offset += align - mod;
288      size   += align - mod;
289    }
290
291  bool growUp;
292  int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp);
293  offset = growUp? firstOffset + offset
294                 : firstOffset - offset - size;
295
296  incrementRegSpillsSize(size);
297
298  return offset;
299}
300
301int
302MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target,
303                                          const Type* type)
304{
305  const MachineFrameInfo& frameInfo = target.getFrameInfo();
306
307  int size = MAXINT;
308  if (frameInfo.argsOnStackHaveFixedSize())
309    size = frameInfo.getSizeOfEachArgOnStack();
310  else
311    {
312      size = target.findOptimalStorageSize(type);
313      assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets");
314    }
315  unsigned char align = target.DataLayout.getTypeAlignment(type);
316
317  int offset = getCurrentOptionalArgsSize();
318  if (unsigned int mod = offset % align)
319    {
320      offset += align - mod;
321      size   += align - mod;
322    }
323
324  bool growUp;
325  int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp);
326  offset = growUp? firstOffset + offset
327                 : firstOffset - offset - size;
328
329  incrementCurrentOptionalArgsSize(size);
330
331  return offset;
332}
333
334void
335MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target)
336{
337  currentOptionalArgsSize = 0;
338}
339
340int
341MachineCodeForMethod::pushTempValue(const TargetMachine& target,
342                                    unsigned int size)
343{
344  // Compute a power-of-2 alignment according to the possible sizes,
345  // but not greater than the alignment of the largest type we support
346  // (currently a double word -- see class TargetData).
347  unsigned char align = 1;
348  for (; align < size && align < target.DataLayout.getDoubleAlignment();
349         align = 2*align)
350    ;
351
352  int offset = currentTmpValuesSize;
353  if (unsigned int mod = offset % align)
354    {
355      offset += align - mod;
356      size   += align - mod;
357    }
358
359  bool growUp;
360  int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp);
361  offset = growUp? firstTmpOffset + offset
362                 : firstTmpOffset - offset - size;
363
364  currentTmpValuesSize += size;
365  return offset;
366}
367
368void
369MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
370{
371  currentTmpValuesSize = 0;
372}
373
374
375// void
376// MachineCodeForMethod::putLocalVarAtOffsetFromSP(const Value* local,
377//                                                 int offset,
378//                                                 unsigned int size)
379// {
380//   offsetsFromSP[local] = offset;
381//   incrementAutomaticVarsSize(size);
382// }
383//
384
385int
386MachineCodeForMethod::getOffset(const Value* val) const
387{
388  hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
389  return (pair == offsets.end())? INVALID_FRAME_OFFSET : (*pair).second;
390}
391
392
393// int
394// MachineCodeForMethod::getOffsetFromSP(const Value* local) const
395// {
396//   hash_map<const Value*, int>::const_iterator pair = offsetsFromSP.find(local);
397//   return (pair == offsetsFromSP.end())? INVALID_FRAME_OFFSET : (*pair).second;
398// }
399
400
401void
402MachineCodeForMethod::dump() const
403{
404  cout << "\n" << method->getReturnType()
405       << " \"" << method->getName() << "\"" << endl;
406
407  for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI)
408    {
409      BasicBlock* bb = *BI;
410      cout << "\n"
411	   << (bb->hasName()? bb->getName() : "Label")
412	   << " (" << bb << ")" << ":"
413	   << endl;
414
415      MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
416      for (unsigned i=0; i < mvec.size(); i++)
417	cout << "\t" << *mvec[i];
418    }
419  cout << endl << "End method \"" << method->getName() << "\""
420       << endl << endl;
421}
422