MachineFunction.cpp revision 03d33bd2640806ce8e661acf7bcfa3726a14d606
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 20const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max(); 21 22static 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// 32MachineCodeForMethod& 33MachineCodeForMethod::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 42void 43MachineCodeForMethod::destruct(const Function *M) 44{ 45 bool Deleted = M->deleteAnnotation(MCFM_AID); 46 assert(Deleted && "Machine code did not exist for function!"); 47} 48 49MachineCodeForMethod& 50MachineCodeForMethod::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 57static unsigned 58ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F, 59 unsigned &maxOptionalNumArgs) 60{ 61 const MachineFrameInfo& frameInfo = target.getFrameInfo(); 62 63 unsigned int maxSize = 0; 64 65 for (Function::const_iterator MI = F->begin(), ME = F->end(); MI != ME; ++MI) 66 { 67 const BasicBlock *BB = *MI; 68 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) 69 if (CallInst *callInst = dyn_cast<CallInst>(*I)) 70 { 71 unsigned int numOperands = callInst->getNumOperands() - 1; 72 int numExtra =(int)numOperands-frameInfo.getNumFixedOutgoingArgs(); 73 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 { 84 assert(0 && "UNTESTED CODE: Size per stack argument is not " 85 "fixed on this architecture: use actual arg sizes to " 86 "compute MaxOptionalArgsSize"); 87 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; 95 96 if (((int) maxOptionalNumArgs) < numExtra) 97 maxOptionalNumArgs = (unsigned) numExtra; 98 } 99 } 100 101 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*/ 125MachineCodeForMethod::MachineCodeForMethod(const Function *F, 126 const TargetMachine& target) 127 : Annotation(MCFM_AID), 128 method(F), staticStackSize(0), 129 automaticVarsSize(0), regSpillsSize(0), 130 maxOptionalArgsSize(0), maxOptionalNumArgs(0), 131 currentTmpValuesSize(0), maxTmpValuesSize(0), compiledAsLeaf(false), 132 spillsAreaFrozen(false), automaticVarsAreaFrozen(false) 133{ 134 maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method, 135 maxOptionalNumArgs); 136 staticStackSize = maxOptionalArgsSize 137 + target.getFrameInfo().getMinStackFrameSize(); 138} 139 140int 141MachineCodeForMethod::computeOffsetforLocalVar(const TargetMachine& target, 142 const Value* val, 143 unsigned int& getPaddedSize, 144 unsigned int sizeToUse = 0) 145{ 146 bool growUp; 147 int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this, 148 growUp); 149 unsigned char align; 150 if (sizeToUse == 0) 151 { 152 sizeToUse = target.findOptimalStorageSize(val->getType()); 153 // align = target.DataLayout.getTypeAlignment(val->getType()); 154 } 155 156 align = SizeToAlignment(sizeToUse, target); 157 158 int offset = getAutomaticVarsSize(); 159 if (! growUp) 160 offset += sizeToUse; 161 162 if (unsigned int mod = offset % align) 163 { 164 offset += align - mod; 165 getPaddedSize = sizeToUse + align - mod; 166 } 167 else 168 getPaddedSize = sizeToUse; 169 170 offset = growUp? firstOffset + offset 171 : firstOffset - offset; 172 173 return offset; 174} 175 176int 177MachineCodeForMethod::allocateLocalVar(const TargetMachine& target, 178 const Value* val, 179 unsigned int sizeToUse = 0) 180{ 181 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 185 // 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 { 190 unsigned int getPaddedSize; 191 offset = this->computeOffsetforLocalVar(target, val, getPaddedSize, 192 sizeToUse); 193 offsets[val] = offset; 194 incrementAutomaticVarsSize(getPaddedSize); 195 } 196 return offset; 197} 198 199int 200MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target, 201 const Type* type) 202{ 203 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 207 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 232MachineCodeForMethod::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 258 incrementTmpAreaSize(size); 259 return offset; 260} 261 262void 263MachineCodeForMethod::popAllTempValues(const TargetMachine& target) 264{ 265 resetTmpAreaSize(); 266} 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{ 278 std::cerr << "\n" << method->getReturnType() 279 << " \"" << method->getName() << "\"\n"; 280 281 for (Function::const_iterator BI = method->begin(); BI != method->end(); ++BI) 282 { 283 BasicBlock* bb = *BI; 284 std::cerr << "\n" << bb->getName() << " (" << bb << ")" << ":\n"; 285 286 MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec(); 287 for (unsigned i=0; i < mvec.size(); i++) 288 std::cerr << "\t" << *mvec[i]; 289 } 290 std::cerr << "\nEnd function \"" << method->getName() << "\"\n\n"; 291} 292