Optional args are no longer allocated as they are discovered.
[oota-llvm.git] / lib / CodeGen / MachineFunction.cpp
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
20 const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max();
21
22 static 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 // 
32 MachineCodeForMethod&
33 MachineCodeForMethod::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
42 void
43 MachineCodeForMethod::destruct(const Function *M)
44 {
45   bool Deleted = M->deleteAnnotation(MCFM_AID);
46   assert(Deleted && "Machine code did not exist for function!");
47 }
48
49 MachineCodeForMethod&
50 MachineCodeForMethod::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
57 static unsigned
58 ComputeMaxOptionalArgsSize(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 // 
110 inline unsigned int
111 SizeToAlignment(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*/
125 MachineCodeForMethod::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
140 int
141 MachineCodeForMethod::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
176 int
177 MachineCodeForMethod::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   
199 int
200 MachineCodeForMethod::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
231 int
232 MachineCodeForMethod::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
262 void
263 MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
264 {
265   resetTmpAreaSize();
266 }
267
268 int
269 MachineCodeForMethod::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
275 void
276 MachineCodeForMethod::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 }