Added function computeOffsetforLocalVar to check how big the
[oota-llvm.git] / lib / CodeGen / MachineFunction.cpp
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
20 const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max();
21
22 static 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 // 
32 MachineCodeForMethod&
33 MachineCodeForMethod::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
42 void
43 MachineCodeForMethod::destruct(const Method *M)
44 {
45   bool Deleted = M->deleteAnnotation(MCFM_AID);
46   assert(Deleted && "Machine code did not exist for method!");
47 }
48
49 MachineCodeForMethod&
50 MachineCodeForMethod::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
58 static unsigned
59 ComputeMaxOptionalArgsSize(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 // 
106 inline unsigned int
107 SizeToAlignment(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*/
121 MachineCodeForMethod::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
134 int
135 MachineCodeForMethod::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
167 int
168 MachineCodeForMethod::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   
184 int
185 MachineCodeForMethod::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
212 int
213 MachineCodeForMethod::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
249 void
250 MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target)
251 {
252   currentOptionalArgsSize = 0;
253 }
254
255 int
256 MachineCodeForMethod::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
286 void
287 MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
288 {
289   currentTmpValuesSize = 0;
290 }
291
292 int
293 MachineCodeForMethod::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
299 void
300 MachineCodeForMethod::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 }