MachineFunction.cpp revision 89e2da034a02cd33b306b59dbbf607650cca1c4c
1//===-- MachineCodeForMethod.cpp --------------------------------------------=//
2//
3// Purpose:
4//   Collect native machine code information for a method.
5//   This allows target-specific information about the generated code
6//   to be stored with each method.
7//===----------------------------------------------------------------------===//
8
9#include "llvm/CodeGen/MachineCodeForMethod.h"
10#include "llvm/CodeGen/MachineInstr.h"  // For debug output
11#include "llvm/Target/TargetMachine.h"
12#include "llvm/Target/MachineFrameInfo.h"
13#include "llvm/Target/MachineCacheInfo.h"
14#include "llvm/Method.h"
15#include "llvm/BasicBlock.h"
16#include "llvm/iOther.h"
17#include <limits.h>
18#include <iostream>
19
20const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max();
21
22static AnnotationID MCFM_AID(
23                 AnnotationManager::getID("CodeGen::MachineCodeForMethod"));
24
25// The next two methods are used to construct and to retrieve
26// the MachineCodeForMethod object for the given method.
27// construct() -- Allocates and initializes for a given method and target
28// get()       -- Returns a handle to the object.
29//                This should not be called before "construct()"
30//                for a given Method.
31//
32MachineCodeForMethod&
33MachineCodeForMethod::construct(const Method *M, const TargetMachine &Tar)
34{
35  assert(M->getAnnotation(MCFM_AID) == 0 &&
36         "Object already exists for this method!");
37  MachineCodeForMethod* mcInfo = new MachineCodeForMethod(M, Tar);
38  M->addAnnotation(mcInfo);
39  return *mcInfo;
40}
41
42void
43MachineCodeForMethod::destruct(const Method *M)
44{
45  bool Deleted = M->deleteAnnotation(MCFM_AID);
46  assert(Deleted && "Machine code did not exist for method!");
47}
48
49MachineCodeForMethod&
50MachineCodeForMethod::get(const Method* method)
51{
52  MachineCodeForMethod* mc = (MachineCodeForMethod*)
53    method->getAnnotation(MCFM_AID);
54  assert(mc && "Call construct() method first to allocate the object");
55  return *mc;
56}
57
58static unsigned
59ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method)
60{
61  const MachineFrameInfo& frameInfo = target.getFrameInfo();
62
63  unsigned int maxSize = 0;
64
65  for (Method::const_iterator MI=method->begin(), ME=method->end();
66       MI != ME; ++MI)
67    {
68      const BasicBlock *BB = *MI;
69      for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I)
70        if (CallInst *callInst = dyn_cast<CallInst>(*I))
71          {
72            unsigned int numOperands = callInst->getNumOperands() - 1;
73            int numExtra = (int) numOperands - frameInfo.getNumFixedOutgoingArgs();
74            if (numExtra <= 0)
75              continue;
76
77            unsigned int sizeForThisCall;
78            if (frameInfo.argsOnStackHaveFixedSize())
79              {
80                int argSize = frameInfo.getSizeOfEachArgOnStack();
81                sizeForThisCall = numExtra * (unsigned) argSize;
82              }
83            else
84              {
85                assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual arg sizes to compute MaxOptionalArgsSize");
86                sizeForThisCall = 0;
87                for (unsigned i=0; i < numOperands; ++i)
88                  sizeForThisCall += target.findOptimalStorageSize(callInst->
89                                                       getOperand(i)->getType());
90              }
91
92            if (maxSize < sizeForThisCall)
93              maxSize = sizeForThisCall;
94          }
95    }
96
97  return maxSize;
98}
99
100// Align data larger than one L1 cache line on L1 cache line boundaries.
101// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
102//
103// THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND
104// SHOULD BE USED DIRECTLY THERE
105//
106inline unsigned int
107SizeToAlignment(unsigned int size, const TargetMachine& target)
108{
109  unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
110  if (size > (unsigned) cacheLineSize / 2)
111    return cacheLineSize;
112  else
113    for (unsigned sz=1; /*no condition*/; sz *= 2)
114      if (sz >= size)
115        return sz;
116}
117
118
119
120/*ctor*/
121MachineCodeForMethod::MachineCodeForMethod(const Method* _M,
122                                           const TargetMachine& target)
123  : Annotation(MCFM_AID),
124    method(_M), compiledAsLeaf(false), staticStackSize(0),
125    automaticVarsSize(0), regSpillsSize(0),
126    currentOptionalArgsSize(0), maxOptionalArgsSize(0),
127    currentTmpValuesSize(0)
128{
129  maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method);
130  staticStackSize = maxOptionalArgsSize
131                    + target.getFrameInfo().getMinStackFrameSize();
132}
133
134int
135MachineCodeForMethod::computeOffsetforLocalVar(const TargetMachine& target,
136                                               const Value* val,
137                                               unsigned int size)
138{
139  bool growUp;
140  int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this,
141                                                                    growUp);
142  unsigned char align;
143  if (size == 0)
144    {
145      size  = target.findOptimalStorageSize(val->getType());
146      // align = target.DataLayout.getTypeAlignment(val->getType());
147    }
148
149  align = SizeToAlignment(size, target);
150
151  int offset = getAutomaticVarsSize();
152  if (! growUp)
153    offset += size;
154
155  if (unsigned int mod = offset % align)
156    {
157      offset += align - mod;
158      size   += align - mod;
159    }
160
161  offset = growUp? firstOffset + offset
162    : firstOffset - offset;
163
164  return offset;
165}
166
167int
168MachineCodeForMethod::allocateLocalVar(const TargetMachine& target,
169                                       const Value* val,
170                                       unsigned int size)
171{
172  // Check if we've allocated a stack slot for this value already
173  //
174  int offset = getOffset(val);
175  if (offset == INVALID_FRAME_OFFSET)
176    {
177      offset = this->computeOffsetforLocalVar(target, val, size);
178      offsets[val] = offset;
179      incrementAutomaticVarsSize(size);
180    }
181  return offset;
182}
183
184int
185MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target,
186                                           const Type* type)
187{
188  unsigned int size  = target.findOptimalStorageSize(type);
189  unsigned char align = target.DataLayout.getTypeAlignment(type);
190
191  bool growUp;
192  int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp);
193
194  int offset = getRegSpillsSize();
195  if (! growUp)
196    offset += size;
197
198  if (unsigned int mod = offset % align)
199    {
200      offset    += align - mod;
201      size += align - mod;
202    }
203
204  offset = growUp? firstOffset + offset
205                 : firstOffset - offset;
206
207  incrementRegSpillsSize(size);
208
209  return offset;
210}
211
212int
213MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target,
214                                          const Type* type)
215{
216  const MachineFrameInfo& frameInfo = target.getFrameInfo();
217
218  int size = INT_MAX;
219  if (frameInfo.argsOnStackHaveFixedSize())
220    size = frameInfo.getSizeOfEachArgOnStack();
221  else
222    {
223      size = target.findOptimalStorageSize(type);
224      assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets");
225    }
226  unsigned char align = target.DataLayout.getTypeAlignment(type);
227
228  bool growUp;
229  int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp);
230
231  int offset = getCurrentOptionalArgsSize();
232  if (! growUp)
233    offset += size;
234
235  if (unsigned int mod = offset % align)
236    {
237      offset += align - mod;
238      size   += align - mod;
239    }
240
241  offset = growUp? firstOffset + offset
242                 : firstOffset - offset;
243
244  incrementCurrentOptionalArgsSize(size);
245
246  return offset;
247}
248
249void
250MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target)
251{
252  currentOptionalArgsSize = 0;
253}
254
255int
256MachineCodeForMethod::pushTempValue(const TargetMachine& target,
257                                    unsigned int size)
258{
259  // Compute a power-of-2 alignment according to the possible sizes,
260  // but not greater than the alignment of the largest type we support
261  // (currently a double word -- see class TargetData).
262  unsigned char align = 1;
263  for (; align < size && align < target.DataLayout.getDoubleAlignment();
264         align = 2*align)
265    ;
266
267  bool growUp;
268  int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp);
269
270  int offset = currentTmpValuesSize;
271  if (! growUp)
272    offset += size;
273
274  if (unsigned int mod = offset % align)
275    {
276      offset += align - mod;
277      size   += align - mod;
278    }
279
280  offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset;
281
282  currentTmpValuesSize += size;
283  return offset;
284}
285
286void
287MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
288{
289  currentTmpValuesSize = 0;
290}
291
292int
293MachineCodeForMethod::getOffset(const Value* val) const
294{
295  std::hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
296  return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second;
297}
298
299void
300MachineCodeForMethod::dump() const
301{
302  std::cerr << "\n" << method->getReturnType()
303            << " \"" << method->getName() << "\"\n";
304
305  for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI)
306    {
307      BasicBlock* bb = *BI;
308      std::cerr << "\n" << bb->getName() << " (" << bb << ")" << ":\n";
309
310      MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
311      for (unsigned i=0; i < mvec.size(); i++)
312	std::cerr << "\t" << *mvec[i];
313    }
314  std::cerr << "\nEnd method \"" << method->getName() << "\"\n\n";
315}
316