blob: 7eb90ab70b25e8f7b1cfd4d88cea6853e876cd83 [file] [log] [blame]
Chris Lattnerf2868ce2002-02-03 07:54:50 +00001//===-- 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"
Chris Lattner221d6882002-02-12 21:07:25 +000015#include "llvm/BasicBlock.h"
Chris Lattnerf2868ce2002-02-03 07:54:50 +000016#include "llvm/iOther.h"
17#include <limits.h>
Chris Lattnerb91ca1f2002-02-24 23:01:56 +000018#include <iostream>
Chris Lattnerf2868ce2002-02-03 07:54:50 +000019
20const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max();
21
22static 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//
32MachineCodeForMethod &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
41void 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
47MachineCodeForMethod &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
54static unsigned
55ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method)
56{
57 const MachineFrameInfo& frameInfo = target.getFrameInfo();
58
59 unsigned int maxSize = 0;
60
Chris Lattner221d6882002-02-12 21:07:25 +000061 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)) {
Chris Lattnerf2868ce2002-02-03 07:54:50 +000066 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 }
Chris Lattner221d6882002-02-12 21:07:25 +000089 }
Chris Lattnerf2868ce2002-02-03 07:54:50 +000090 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//
99inline unsigned int
100SizeToAlignment(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*/
114MachineCodeForMethod::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
127int
128MachineCodeForMethod::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
169int
170MachineCodeForMethod::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
197int
198MachineCodeForMethod::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
234void
235MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target)
236{
237 currentOptionalArgsSize = 0;
238}
239
240int
241MachineCodeForMethod::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
271void
272MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
273{
274 currentTmpValuesSize = 0;
275}
276
277int
278MachineCodeForMethod::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
284void
285MachineCodeForMethod::dump() const
286{
Chris Lattnerb91ca1f2002-02-24 23:01:56 +0000287 std::cerr << "\n" << method->getReturnType()
288 << " \"" << method->getName() << "\"\n";
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000289
290 for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI)
291 {
292 BasicBlock* bb = *BI;
Chris Lattnerb91ca1f2002-02-24 23:01:56 +0000293 std::cerr << "\n" << bb->getName() << " (" << bb << ")" << ":\n";
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000294
295 MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
296 for (unsigned i=0; i < mvec.size(); i++)
Chris Lattnerb91ca1f2002-02-24 23:01:56 +0000297 std::cerr << "\t" << *mvec[i];
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000298 }
Chris Lattnerb91ca1f2002-02-24 23:01:56 +0000299 std::cerr << "\nEnd method \"" << method->getName() << "\"\n\n";
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000300}