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