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