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