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