blob: 06e0666ec884c22c334b4c8415554c07a237ec7c [file] [log] [blame]
Vikram S. Adve03d33bd2002-04-25 04:30:43 +00001//===-- MachineCodeForMethod.cpp -------------------------------------------=//
Chris Lattnerf2868ce2002-02-03 07:54:50 +00002//
3// Purpose:
Chris Lattner2fbfdcf2002-04-07 20:49:59 +00004// Collect native machine code information for a function.
Chris Lattnerf2868ce2002-02-03 07:54:50 +00005// This allows target-specific information about the generated code
Chris Lattner2fbfdcf2002-04-07 20:49:59 +00006// to be stored with each function.
Vikram S. Adve03d33bd2002-04-25 04:30:43 +00007//===---------------------------------------------------------------------===//
Chris Lattnerf2868ce2002-02-03 07:54:50 +00008
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"
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000014#include "llvm/Function.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(
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000023 AnnotationManager::getID("CodeGen::MachineCodeForFunction"));
Chris Lattnerf2868ce2002-02-03 07:54:50 +000024
25// The next two methods are used to construct and to retrieve
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000026// the MachineCodeForFunction object for the given function.
27// construct() -- Allocates and initializes for a given function and target
Chris Lattnerf2868ce2002-02-03 07:54:50 +000028// get() -- Returns a handle to the object.
29// This should not be called before "construct()"
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000030// for a given Function.
Chris Lattnerf2868ce2002-02-03 07:54:50 +000031//
Vikram S. Adve89e2da02002-03-18 03:36:30 +000032MachineCodeForMethod&
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000033MachineCodeForMethod::construct(const Function *M, const TargetMachine &Tar)
Vikram S. Adve89e2da02002-03-18 03:36:30 +000034{
Chris Lattnerf2868ce2002-02-03 07:54:50 +000035 assert(M->getAnnotation(MCFM_AID) == 0 &&
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000036 "Object already exists for this function!");
Chris Lattnerf2868ce2002-02-03 07:54:50 +000037 MachineCodeForMethod* mcInfo = new MachineCodeForMethod(M, Tar);
38 M->addAnnotation(mcInfo);
39 return *mcInfo;
40}
41
Vikram S. Adve89e2da02002-03-18 03:36:30 +000042void
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000043MachineCodeForMethod::destruct(const Function *M)
Vikram S. Adve89e2da02002-03-18 03:36:30 +000044{
Chris Lattnerf2868ce2002-02-03 07:54:50 +000045 bool Deleted = M->deleteAnnotation(MCFM_AID);
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000046 assert(Deleted && "Machine code did not exist for function!");
Chris Lattnerf2868ce2002-02-03 07:54:50 +000047}
48
Vikram S. Adve89e2da02002-03-18 03:36:30 +000049MachineCodeForMethod&
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000050MachineCodeForMethod::get(const Function *F)
Vikram S. Adve89e2da02002-03-18 03:36:30 +000051{
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000052 MachineCodeForMethod *mc = (MachineCodeForMethod*)F->getAnnotation(MCFM_AID);
Chris Lattnerf2868ce2002-02-03 07:54:50 +000053 assert(mc && "Call construct() method first to allocate the object");
54 return *mc;
55}
56
57static unsigned
Vikram S. Adve03d33bd2002-04-25 04:30:43 +000058ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F,
59 unsigned &maxOptionalNumArgs)
Chris Lattnerf2868ce2002-02-03 07:54:50 +000060{
61 const MachineFrameInfo& frameInfo = target.getFrameInfo();
62
63 unsigned int maxSize = 0;
64
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000065 for (Function::const_iterator MI = F->begin(), ME = F->end(); MI != ME; ++MI)
Vikram S. Adve89e2da02002-03-18 03:36:30 +000066 {
67 const BasicBlock *BB = *MI;
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000068 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I)
Vikram S. Adve89e2da02002-03-18 03:36:30 +000069 if (CallInst *callInst = dyn_cast<CallInst>(*I))
Chris Lattnerf2868ce2002-02-03 07:54:50 +000070 {
Vikram S. Adve89e2da02002-03-18 03:36:30 +000071 unsigned int numOperands = callInst->getNumOperands() - 1;
Vikram S. Adve03d33bd2002-04-25 04:30:43 +000072 int numExtra =(int)numOperands-frameInfo.getNumFixedOutgoingArgs();
Vikram S. Adve89e2da02002-03-18 03:36:30 +000073 if (numExtra <= 0)
74 continue;
75
76 unsigned int sizeForThisCall;
77 if (frameInfo.argsOnStackHaveFixedSize())
78 {
79 int argSize = frameInfo.getSizeOfEachArgOnStack();
80 sizeForThisCall = numExtra * (unsigned) argSize;
81 }
82 else
83 {
Chris Lattner2fbfdcf2002-04-07 20:49:59 +000084 assert(0 && "UNTESTED CODE: Size per stack argument is not "
85 "fixed on this architecture: use actual arg sizes to "
86 "compute MaxOptionalArgsSize");
Vikram S. Adve89e2da02002-03-18 03:36:30 +000087 sizeForThisCall = 0;
88 for (unsigned i=0; i < numOperands; ++i)
89 sizeForThisCall += target.findOptimalStorageSize(callInst->
90 getOperand(i)->getType());
91 }
92
93 if (maxSize < sizeForThisCall)
94 maxSize = sizeForThisCall;
Vikram S. Adve03d33bd2002-04-25 04:30:43 +000095
96 if (((int) maxOptionalNumArgs) < numExtra)
97 maxOptionalNumArgs = (unsigned) numExtra;
Chris Lattnerf2868ce2002-02-03 07:54:50 +000098 }
Vikram S. Adve89e2da02002-03-18 03:36:30 +000099 }
100
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000101 return maxSize;
102}
103
104// Align data larger than one L1 cache line on L1 cache line boundaries.
105// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
106//
107// THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND
108// SHOULD BE USED DIRECTLY THERE
109//
110inline unsigned int
111SizeToAlignment(unsigned int size, const TargetMachine& target)
112{
113 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
114 if (size > (unsigned) cacheLineSize / 2)
115 return cacheLineSize;
116 else
117 for (unsigned sz=1; /*no condition*/; sz *= 2)
118 if (sz >= size)
119 return sz;
120}
121
122
123
124/*ctor*/
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000125MachineCodeForMethod::MachineCodeForMethod(const Function *F,
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000126 const TargetMachine& target)
127 : Annotation(MCFM_AID),
Vikram S. Adve03d33bd2002-04-25 04:30:43 +0000128 method(F), staticStackSize(0),
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000129 automaticVarsSize(0), regSpillsSize(0),
Vikram S. Adve03d33bd2002-04-25 04:30:43 +0000130 maxOptionalArgsSize(0), maxOptionalNumArgs(0),
131 currentTmpValuesSize(0), maxTmpValuesSize(0), compiledAsLeaf(false),
132 spillsAreaFrozen(false), automaticVarsAreaFrozen(false)
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000133{
Vikram S. Adve03d33bd2002-04-25 04:30:43 +0000134 maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method,
135 maxOptionalNumArgs);
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000136 staticStackSize = maxOptionalArgsSize
137 + target.getFrameInfo().getMinStackFrameSize();
138}
139
140int
141MachineCodeForMethod::computeOffsetforLocalVar(const TargetMachine& target,
142 const Value* val,
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000143 unsigned int& getPaddedSize,
144 unsigned int sizeToUse = 0)
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000145{
146 bool growUp;
147 int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this,
148 growUp);
149 unsigned char align;
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000150 if (sizeToUse == 0)
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000151 {
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000152 sizeToUse = target.findOptimalStorageSize(val->getType());
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000153 // align = target.DataLayout.getTypeAlignment(val->getType());
154 }
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000155
156 align = SizeToAlignment(sizeToUse, target);
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000157
158 int offset = getAutomaticVarsSize();
159 if (! growUp)
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000160 offset += sizeToUse;
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000161
162 if (unsigned int mod = offset % align)
163 {
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000164 offset += align - mod;
165 getPaddedSize = sizeToUse + align - mod;
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000166 }
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000167 else
168 getPaddedSize = sizeToUse;
169
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000170 offset = growUp? firstOffset + offset
171 : firstOffset - offset;
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000172
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000173 return offset;
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000174}
175
176int
177MachineCodeForMethod::allocateLocalVar(const TargetMachine& target,
178 const Value* val,
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000179 unsigned int sizeToUse = 0)
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000180{
Vikram S. Adve03d33bd2002-04-25 04:30:43 +0000181 assert(! automaticVarsAreaFrozen &&
182 "Size of auto vars area has been used to compute an offset so "
183 "no more automatic vars should be allocated!");
184
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000185 // Check if we've allocated a stack slot for this value already
186 //
187 int offset = getOffset(val);
188 if (offset == INVALID_FRAME_OFFSET)
189 {
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000190 unsigned int getPaddedSize;
191 offset = this->computeOffsetforLocalVar(target, val, getPaddedSize,
192 sizeToUse);
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000193 offsets[val] = offset;
Vikram S. Advee4e4d4e2002-03-24 03:39:26 +0000194 incrementAutomaticVarsSize(getPaddedSize);
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000195 }
196 return offset;
197}
Vikram S. Adve89e2da02002-03-18 03:36:30 +0000198
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000199int
200MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target,
201 const Type* type)
202{
Vikram S. Adve03d33bd2002-04-25 04:30:43 +0000203 assert(! spillsAreaFrozen &&
204 "Size of reg spills area has been used to compute an offset so "
205 "no more register spill slots should be allocated!");
206
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000207 unsigned int size = target.findOptimalStorageSize(type);
208 unsigned char align = target.DataLayout.getTypeAlignment(type);
209
210 bool growUp;
211 int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp);
212
213 int offset = getRegSpillsSize();
214 if (! growUp)
215 offset += size;
216
217 if (unsigned int mod = offset % align)
218 {
219 offset += align - mod;
220 size += align - mod;
221 }
222
223 offset = growUp? firstOffset + offset
224 : firstOffset - offset;
225
226 incrementRegSpillsSize(size);
227
228 return offset;
229}
230
231int
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000232MachineCodeForMethod::pushTempValue(const TargetMachine& target,
233 unsigned int size)
234{
235 // Compute a power-of-2 alignment according to the possible sizes,
236 // but not greater than the alignment of the largest type we support
237 // (currently a double word -- see class TargetData).
238 unsigned char align = 1;
239 for (; align < size && align < target.DataLayout.getDoubleAlignment();
240 align = 2*align)
241 ;
242
243 bool growUp;
244 int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp);
245
246 int offset = currentTmpValuesSize;
247 if (! growUp)
248 offset += size;
249
250 if (unsigned int mod = offset % align)
251 {
252 offset += align - mod;
253 size += align - mod;
254 }
255
256 offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset;
257
Vikram S. Advefa79e6e2002-03-31 18:57:49 +0000258 incrementTmpAreaSize(size);
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000259 return offset;
260}
261
262void
263MachineCodeForMethod::popAllTempValues(const TargetMachine& target)
264{
Vikram S. Advefa79e6e2002-03-31 18:57:49 +0000265 resetTmpAreaSize();
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000266}
267
268int
269MachineCodeForMethod::getOffset(const Value* val) const
270{
271 std::hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
272 return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second;
273}
274
275void
276MachineCodeForMethod::dump() const
277{
Chris Lattnerb91ca1f2002-02-24 23:01:56 +0000278 std::cerr << "\n" << method->getReturnType()
279 << " \"" << method->getName() << "\"\n";
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000280
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000281 for (Function::const_iterator BI = method->begin(); BI != method->end(); ++BI)
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000282 {
283 BasicBlock* bb = *BI;
Chris Lattnerb91ca1f2002-02-24 23:01:56 +0000284 std::cerr << "\n" << bb->getName() << " (" << bb << ")" << ":\n";
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000285
286 MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
287 for (unsigned i=0; i < mvec.size(); i++)
Chris Lattnerb91ca1f2002-02-24 23:01:56 +0000288 std::cerr << "\t" << *mvec[i];
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000289 }
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000290 std::cerr << "\nEnd function \"" << method->getName() << "\"\n\n";
Chris Lattnerf2868ce2002-02-03 07:54:50 +0000291}