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 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 // 110 inline unsigned int 111 SizeToAlignment(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*/ 125 MachineCodeForMethod::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 140 int 141 MachineCodeForMethod::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 176 int 177 MachineCodeForMethod::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 199 int 200 MachineCodeForMethod::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 231 int 232 MachineCodeForMethod::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 262 void 263 MachineCodeForMethod::popAllTempValues(const TargetMachine& target) 264 { 265 resetTmpAreaSize(); 266 } 267 268 int 269 MachineCodeForMethod::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 275 void 276 MachineCodeForMethod::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