MachineFunction.cpp revision 1318bed20c52792913405c0d41766f69829cf944
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/CodeGen/MachineCodeForBasicBlock.h" 12#include "llvm/Target/TargetMachine.h" 13#include "llvm/Target/MachineFrameInfo.h" 14#include "llvm/Target/MachineCacheInfo.h" 15#include "llvm/Function.h" 16#include "llvm/BasicBlock.h" 17#include "llvm/iOther.h" 18#include <limits.h> 19#include <iostream> 20 21const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max(); 22 23static AnnotationID MCFM_AID( 24 AnnotationManager::getID("CodeGen::MachineCodeForFunction")); 25 26// The next two methods are used to construct and to retrieve 27// the MachineCodeForFunction object for the given function. 28// construct() -- Allocates and initializes for a given function and target 29// get() -- Returns a handle to the object. 30// This should not be called before "construct()" 31// for a given Function. 32// 33MachineCodeForMethod& 34MachineCodeForMethod::construct(const Function *M, const TargetMachine &Tar) 35{ 36 assert(M->getAnnotation(MCFM_AID) == 0 && 37 "Object already exists for this function!"); 38 MachineCodeForMethod* mcInfo = new MachineCodeForMethod(M, Tar); 39 M->addAnnotation(mcInfo); 40 return *mcInfo; 41} 42 43void 44MachineCodeForMethod::destruct(const Function *M) 45{ 46 bool Deleted = M->deleteAnnotation(MCFM_AID); 47 assert(Deleted && "Machine code did not exist for function!"); 48} 49 50MachineCodeForMethod& 51MachineCodeForMethod::get(const Function *F) 52{ 53 MachineCodeForMethod *mc = (MachineCodeForMethod*)F->getAnnotation(MCFM_AID); 54 assert(mc && "Call construct() method first to allocate the object"); 55 return *mc; 56} 57 58static unsigned 59ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F, 60 unsigned &maxOptionalNumArgs) 61{ 62 const MachineFrameInfo& frameInfo = target.getFrameInfo(); 63 64 unsigned maxSize = 0; 65 66 for (Function::const_iterator BB = F->begin(), BBE = F->end(); BB !=BBE; ++BB) 67 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) 68 if (const CallInst *callInst = dyn_cast<CallInst>(&*I)) 69 { 70 unsigned numOperands = callInst->getNumOperands() - 1; 71 int numExtra = (int)numOperands-frameInfo.getNumFixedOutgoingArgs(); 72 if (numExtra <= 0) 73 continue; 74 75 unsigned int sizeForThisCall; 76 if (frameInfo.argsOnStackHaveFixedSize()) 77 { 78 int argSize = frameInfo.getSizeOfEachArgOnStack(); 79 sizeForThisCall = numExtra * (unsigned) argSize; 80 } 81 else 82 { 83 assert(0 && "UNTESTED CODE: Size per stack argument is not " 84 "fixed on this architecture: use actual arg sizes to " 85 "compute MaxOptionalArgsSize"); 86 sizeForThisCall = 0; 87 for (unsigned i = 0; i < numOperands; ++i) 88 sizeForThisCall += target.findOptimalStorageSize(callInst-> 89 getOperand(i)->getType()); 90 } 91 92 if (maxSize < sizeForThisCall) 93 maxSize = sizeForThisCall; 94 95 if ((int)maxOptionalNumArgs < numExtra) 96 maxOptionalNumArgs = (unsigned) numExtra; 97 } 98 99 return maxSize; 100} 101 102// Align data larger than one L1 cache line on L1 cache line boundaries. 103// Align all smaller data on the next higher 2^x boundary (4, 8, ...), 104// but not higher than the alignment of the largest type we support 105// (currently a double word). -- see class TargetData). 106// 107// This function is similar to the corresponding function in EmitAssembly.cpp 108// but they are unrelated. This one does not align at more than a 109// double-word boundary whereas that one might. 110// 111inline unsigned int 112SizeToAlignment(unsigned int size, const TargetMachine& target) 113{ 114 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); 115 if (size > (unsigned) cacheLineSize / 2) 116 return cacheLineSize; 117 else 118 for (unsigned sz=1; /*no condition*/; sz *= 2) 119 if (sz >= size || sz >= target.DataLayout.getDoubleAlignment()) 120 return sz; 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) 145{ 146 if (sizeToUse == 0) 147 sizeToUse = target.findOptimalStorageSize(val->getType()); 148 unsigned int align = SizeToAlignment(sizeToUse, target); 149 150 bool growUp; 151 int firstOffset = target.getFrameInfo().getFirstAutomaticVarOffset(*this, 152 growUp); 153 int offset = growUp? firstOffset + getAutomaticVarsSize() 154 : firstOffset - (getAutomaticVarsSize() + sizeToUse); 155 156 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 157 getPaddedSize = sizeToUse + abs(aligned - offset); 158 159 return aligned; 160} 161 162int 163MachineCodeForMethod::allocateLocalVar(const TargetMachine& target, 164 const Value* val, 165 unsigned int sizeToUse) 166{ 167 assert(! automaticVarsAreaFrozen && 168 "Size of auto vars area has been used to compute an offset so " 169 "no more automatic vars should be allocated!"); 170 171 // Check if we've allocated a stack slot for this value already 172 // 173 int offset = getOffset(val); 174 if (offset == INVALID_FRAME_OFFSET) 175 { 176 unsigned int getPaddedSize; 177 offset = this->computeOffsetforLocalVar(target, val, getPaddedSize, 178 sizeToUse); 179 offsets[val] = offset; 180 incrementAutomaticVarsSize(getPaddedSize); 181 } 182 return offset; 183} 184 185int 186MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target, 187 const Type* type) 188{ 189 assert(! spillsAreaFrozen && 190 "Size of reg spills area has been used to compute an offset so " 191 "no more register spill slots should be allocated!"); 192 193 unsigned int size = target.findOptimalStorageSize(type); 194 unsigned char align = target.DataLayout.getTypeAlignment(type); 195 196 bool growUp; 197 int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); 198 199 int offset = growUp? firstOffset + getRegSpillsSize() 200 : firstOffset - (getRegSpillsSize() + size); 201 202 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 203 size += abs(aligned - offset); // include alignment padding in size 204 205 incrementRegSpillsSize(size); // update size of reg. spills area 206 207 return aligned; 208} 209 210int 211MachineCodeForMethod::pushTempValue(const TargetMachine& target, 212 unsigned int size) 213{ 214 unsigned int align = SizeToAlignment(size, target); 215 216 bool growUp; 217 int firstOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); 218 219 int offset = growUp? firstOffset + currentTmpValuesSize 220 : firstOffset - (currentTmpValuesSize + size); 221 222 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 223 size += abs(aligned - offset); // include alignment padding in size 224 225 incrementTmpAreaSize(size); // update "current" size of tmp area 226 227 return aligned; 228} 229 230void 231MachineCodeForMethod::popAllTempValues(const TargetMachine& target) 232{ 233 resetTmpAreaSize(); // clear tmp area to reuse 234} 235 236int 237MachineCodeForMethod::getOffset(const Value* val) const 238{ 239 hash_map<const Value*, int>::const_iterator pair = offsets.find(val); 240 return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second; 241} 242 243void 244MachineCodeForMethod::dump() const 245{ 246 std::cerr << "\n" << method->getReturnType() 247 << " \"" << method->getName() << "\"\n"; 248 249 for (Function::const_iterator BB = method->begin(); BB != method->end(); ++BB) 250 { 251 std::cerr << std::endl << (*BB).getName() << " (" << (const void*) BB << ")" << ":" << std::endl; 252 MachineCodeForBasicBlock& mvec = MachineCodeForBasicBlock::get(BB); 253 for (unsigned i=0; i < mvec.size(); i++) 254 std::cerr << "\t" << *mvec[i]; 255 } 256 std::cerr << "\nEnd function \"" << method->getName() << "\"\n\n"; 257} 258