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 maxSize = 0; 64 65 for (Function::const_iterator BB = F->begin(), BBE = F->end(); BB !=BBE; ++BB) 66 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) 67 if (const CallInst *callInst = dyn_cast<CallInst>(&*I)) 68 { 69 unsigned numOperands = callInst->getNumOperands() - 1; 70 int numExtra = (int)numOperands-frameInfo.getNumFixedOutgoingArgs(); 71 if (numExtra <= 0) 72 continue; 73 74 unsigned int sizeForThisCall; 75 if (frameInfo.argsOnStackHaveFixedSize()) 76 { 77 int argSize = frameInfo.getSizeOfEachArgOnStack(); 78 sizeForThisCall = numExtra * (unsigned) argSize; 79 } 80 else 81 { 82 assert(0 && "UNTESTED CODE: Size per stack argument is not " 83 "fixed on this architecture: use actual arg sizes to " 84 "compute MaxOptionalArgsSize"); 85 sizeForThisCall = 0; 86 for (unsigned i = 0; i < numOperands; ++i) 87 sizeForThisCall += target.findOptimalStorageSize(callInst-> 88 getOperand(i)->getType()); 89 } 90 91 if (maxSize < sizeForThisCall) 92 maxSize = sizeForThisCall; 93 94 if ((int)maxOptionalNumArgs < numExtra) 95 maxOptionalNumArgs = (unsigned) numExtra; 96 } 97 98 return maxSize; 99 } 100 101 // Align data larger than one L1 cache line on L1 cache line boundaries. 102 // Align all smaller data on the next higher 2^x boundary (4, 8, ...). 103 // 104 // THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND 105 // SHOULD BE USED DIRECTLY THERE 106 // 107 inline unsigned int 108 SizeToAlignment(unsigned int size, const TargetMachine& target) 109 { 110 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); 111 if (size > (unsigned) cacheLineSize / 2) 112 return cacheLineSize; 113 else 114 for (unsigned sz=1; /*no condition*/; sz *= 2) 115 if (sz >= size) 116 return sz; 117 } 118 119 120 121 /*ctor*/ 122 MachineCodeForMethod::MachineCodeForMethod(const Function *F, 123 const TargetMachine& target) 124 : Annotation(MCFM_AID), 125 method(F), staticStackSize(0), 126 automaticVarsSize(0), regSpillsSize(0), 127 maxOptionalArgsSize(0), maxOptionalNumArgs(0), 128 currentTmpValuesSize(0), maxTmpValuesSize(0), compiledAsLeaf(false), 129 spillsAreaFrozen(false), automaticVarsAreaFrozen(false) 130 { 131 maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method, 132 maxOptionalNumArgs); 133 staticStackSize = maxOptionalArgsSize 134 + target.getFrameInfo().getMinStackFrameSize(); 135 } 136 137 int 138 MachineCodeForMethod::computeOffsetforLocalVar(const TargetMachine& target, 139 const Value* val, 140 unsigned int& getPaddedSize, 141 unsigned int sizeToUse = 0) 142 { 143 bool growUp; 144 int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this, 145 growUp); 146 unsigned char align; 147 if (sizeToUse == 0) 148 { 149 sizeToUse = target.findOptimalStorageSize(val->getType()); 150 // align = target.DataLayout.getTypeAlignment(val->getType()); 151 } 152 153 align = SizeToAlignment(sizeToUse, target); 154 155 int offset = getAutomaticVarsSize(); 156 if (! growUp) 157 offset += sizeToUse; 158 159 if (unsigned int mod = offset % align) 160 { 161 offset += align - mod; 162 getPaddedSize = sizeToUse + align - mod; 163 } 164 else 165 getPaddedSize = sizeToUse; 166 167 offset = growUp? firstOffset + offset 168 : firstOffset - offset; 169 170 return offset; 171 } 172 173 int 174 MachineCodeForMethod::allocateLocalVar(const TargetMachine& target, 175 const Value* val, 176 unsigned int sizeToUse = 0) 177 { 178 assert(! automaticVarsAreaFrozen && 179 "Size of auto vars area has been used to compute an offset so " 180 "no more automatic vars should be allocated!"); 181 182 // Check if we've allocated a stack slot for this value already 183 // 184 int offset = getOffset(val); 185 if (offset == INVALID_FRAME_OFFSET) 186 { 187 unsigned int getPaddedSize; 188 offset = this->computeOffsetforLocalVar(target, val, getPaddedSize, 189 sizeToUse); 190 offsets[val] = offset; 191 incrementAutomaticVarsSize(getPaddedSize); 192 } 193 return offset; 194 } 195 196 int 197 MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target, 198 const Type* type) 199 { 200 assert(! spillsAreaFrozen && 201 "Size of reg spills area has been used to compute an offset so " 202 "no more register spill slots should be allocated!"); 203 204 unsigned int size = target.findOptimalStorageSize(type); 205 unsigned char align = target.DataLayout.getTypeAlignment(type); 206 207 bool growUp; 208 int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); 209 210 int offset = getRegSpillsSize(); 211 if (! growUp) 212 offset += size; 213 214 if (unsigned int mod = offset % align) 215 { 216 offset += align - mod; 217 size += align - mod; 218 } 219 220 offset = growUp? firstOffset + offset 221 : firstOffset - offset; 222 223 incrementRegSpillsSize(size); 224 225 return offset; 226 } 227 228 int 229 MachineCodeForMethod::pushTempValue(const TargetMachine& target, 230 unsigned int size) 231 { 232 // Compute a power-of-2 alignment according to the possible sizes, 233 // but not greater than the alignment of the largest type we support 234 // (currently a double word -- see class TargetData). 235 unsigned char align = 1; 236 for (; align < size && align < target.DataLayout.getDoubleAlignment(); 237 align = 2*align) 238 ; 239 240 bool growUp; 241 int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); 242 243 int offset = currentTmpValuesSize; 244 if (! growUp) 245 offset += size; 246 247 if (unsigned int mod = offset % align) 248 { 249 offset += align - mod; 250 size += align - mod; 251 } 252 253 offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset; 254 255 incrementTmpAreaSize(size); 256 return offset; 257 } 258 259 void 260 MachineCodeForMethod::popAllTempValues(const TargetMachine& target) 261 { 262 resetTmpAreaSize(); 263 } 264 265 int 266 MachineCodeForMethod::getOffset(const Value* val) const 267 { 268 std::hash_map<const Value*, int>::const_iterator pair = offsets.find(val); 269 return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second; 270 } 271 272 void 273 MachineCodeForMethod::dump() const 274 { 275 std::cerr << "\n" << method->getReturnType() 276 << " \"" << method->getName() << "\"\n"; 277 278 for (Function::const_iterator BB = method->begin(); BB != method->end(); ++BB) 279 { 280 std::cerr << "\n" << BB->getName() << " (" << *BB << ")" << ":\n"; 281 282 MachineCodeForBasicBlock& mvec = BB->getMachineInstrVec(); 283 for (unsigned i=0; i < mvec.size(); i++) 284 std::cerr << "\t" << *mvec[i]; 285 } 286 std::cerr << "\nEnd function \"" << method->getName() << "\"\n\n"; 287 } 288