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