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), maxTmpValuesSize(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& getPaddedSize,
138                                                unsigned int  sizeToUse = 0)
139 {
140   bool growUp;
141   int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this,
142                                                                     growUp);
143   unsigned char align;
144   if (sizeToUse == 0)
145     {
146       sizeToUse = target.findOptimalStorageSize(val->getType());
147       // align = target.DataLayout.getTypeAlignment(val->getType());
148     }
149 
150   align = SizeToAlignment(sizeToUse, target);
151 
152   int offset = getAutomaticVarsSize();
153   if (! growUp)
154     offset += sizeToUse;
155 
156   if (unsigned int mod = offset % align)
157     {
158       offset        += align - mod;
159       getPaddedSize  = sizeToUse + align - mod;
160     }
161   else
162     getPaddedSize  = sizeToUse;
163 
164   offset = growUp? firstOffset + offset
165     : firstOffset - offset;
166 
167   return offset;
168 }
169 
170 int
171 MachineCodeForMethod::allocateLocalVar(const TargetMachine& target,
172                                        const Value* val,
173                                        unsigned int sizeToUse = 0)
174 {
175   // Check if we've allocated a stack slot for this value already
176   //
177   int offset = getOffset(val);
178   if (offset == INVALID_FRAME_OFFSET)
179     {
180       unsigned int getPaddedSize;
181       offset = this->computeOffsetforLocalVar(target, val, getPaddedSize,
182                                               sizeToUse);
183       offsets[val] = offset;
184       incrementAutomaticVarsSize(getPaddedSize);
185     }
186   return offset;
187 }
188 
189 int
190 MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target,
191                                            const Type* type)
192 {
193   unsigned int size  = target.findOptimalStorageSize(type);
194   unsigned char align = target.DataLayout.getTypeAlignment(type);
195 
196   bool growUp;
197   int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp);
198 
199   int offset = getRegSpillsSize();
200   if (! growUp)
201     offset += size;
202 
203   if (unsigned int mod = offset % align)
204     {
205       offset    += align - mod;
206       size += align - mod;
207     }
208 
209   offset = growUp? firstOffset + offset
210                  : firstOffset - offset;
211 
212   incrementRegSpillsSize(size);
213 
214   return offset;
215 }
216 
217 int
218 MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target,
219                                           const Type* type)
220 {
221   const MachineFrameInfo& frameInfo = target.getFrameInfo();
222 
223   int size = INT_MAX;
224   if (frameInfo.argsOnStackHaveFixedSize())
225     size = frameInfo.getSizeOfEachArgOnStack();
226   else
227     {
228       size = target.findOptimalStorageSize(type);
229       assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets");
230     }
231   unsigned char align = target.DataLayout.getTypeAlignment(type);
232 
233   bool growUp;
234   int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp);
235 
236   int offset = getCurrentOptionalArgsSize();
237   if (! growUp)
238     offset += size;
239 
240   if (unsigned int mod = offset % align)
241     {
242       offset += align - mod;
243       size   += align - mod;
244     }
245 
246   offset = growUp? firstOffset + offset
247                  : firstOffset - offset;
248 
249   incrementCurrentOptionalArgsSize(size);
250 
251   return offset;
252 }
253 
254 void
255 MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target)
256 {
257   currentOptionalArgsSize = 0;
258 }
259 
260 int
261 MachineCodeForMethod::pushTempValue(const TargetMachine& target,
262                                     unsigned int size)
263 {
264   // Compute a power-of-2 alignment according to the possible sizes,
265   // but not greater than the alignment of the largest type we support
266   // (currently a double word -- see class TargetData).
267   unsigned char align = 1;
268   for (; align < size && align < target.DataLayout.getDoubleAlignment();
269          align = 2*align)
270     ;
271 
272   bool growUp;
273   int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp);
274 
275   int offset = currentTmpValuesSize;
276   if (! growUp)
277     offset += size;
278 
279   if (unsigned int mod = offset % align)
280     {
281       offset += align - mod;
282       size   += align - mod;
283     }
284 
285   offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset;
286 
287   incrementTmpAreaSize(size);
288   return offset;
289 }
290 
291 void
292 MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
293 {
294   resetTmpAreaSize();
295 }
296 
297 int
298 MachineCodeForMethod::getOffset(const Value* val) const
299 {
300   std::hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
301   return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second;
302 }
303 
304 void
305 MachineCodeForMethod::dump() const
306 {
307   std::cerr << "\n" << method->getReturnType()
308             << " \"" << method->getName() << "\"\n";
309 
310   for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI)
311     {
312       BasicBlock* bb = *BI;
313       std::cerr << "\n" << bb->getName() << " (" << bb << ")" << ":\n";
314 
315       MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
316       for (unsigned i=0; i < mvec.size(); i++)
317 	std::cerr << "\t" << *mvec[i];
318     }
319   std::cerr << "\nEnd method \"" << method->getName() << "\"\n\n";
320 }
321