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 }
302