1 //===-- MachineCodeForMethod.cpp --------------------------------------------=// 2 // 3 // Purpose: 4 // Collect native machine code information for a method. 5 // This allows target-specific information about the generated code 6 // to be stored with each method. 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/Method.h" 15 #include "llvm/BasicBlock.h" 16 #include "llvm/iOther.h" 17 #include <limits.h> 18 19 const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max(); 20 21 static AnnotationID MCFM_AID( 22 AnnotationManager::getID("CodeGen::MachineCodeForMethod")); 23 24 // The next two methods are used to construct and to retrieve 25 // the MachineCodeForMethod object for the given method. 26 // construct() -- Allocates and initializes for a given method and target 27 // get() -- Returns a handle to the object. 28 // This should not be called before "construct()" 29 // for a given Method. 30 // 31 MachineCodeForMethod &MachineCodeForMethod::construct(const Method *M, 32 const TargetMachine &Tar){ 33 assert(M->getAnnotation(MCFM_AID) == 0 && 34 "Object already exists for this method!"); 35 MachineCodeForMethod* mcInfo = new MachineCodeForMethod(M, Tar); 36 M->addAnnotation(mcInfo); 37 return *mcInfo; 38 } 39 40 void MachineCodeForMethod::destruct(const Method *M) { 41 bool Deleted = M->deleteAnnotation(MCFM_AID); 42 assert(Deleted && "Machine code did not exist for method!"); 43 } 44 45 46 MachineCodeForMethod &MachineCodeForMethod::get(const Method* method) { 47 MachineCodeForMethod* mc = (MachineCodeForMethod*) 48 method->getAnnotation(MCFM_AID); 49 assert(mc && "Call construct() method first to allocate the object"); 50 return *mc; 51 } 52 53 static unsigned 54 ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method) 55 { 56 const MachineFrameInfo& frameInfo = target.getFrameInfo(); 57 58 unsigned int maxSize = 0; 59 60 for (Method::const_iterator MI=method->begin(), ME=method->end(); 61 MI != ME; ++MI) { 62 const BasicBlock *BB = *MI; 63 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) 64 if (CallInst *callInst = dyn_cast<CallInst>(*I)) { 65 unsigned int numOperands = callInst->getNumOperands() - 1; 66 int numExtra = (int) numOperands - frameInfo.getNumFixedOutgoingArgs(); 67 if (numExtra <= 0) 68 continue; 69 70 unsigned int sizeForThisCall; 71 if (frameInfo.argsOnStackHaveFixedSize()) 72 { 73 int argSize = frameInfo.getSizeOfEachArgOnStack(); 74 sizeForThisCall = numExtra * (unsigned) argSize; 75 } 76 else 77 { 78 assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual arg sizes to compute MaxOptionalArgsSize"); 79 sizeForThisCall = 0; 80 for (unsigned i=0; i < numOperands; ++i) 81 sizeForThisCall += target.findOptimalStorageSize(callInst-> 82 getOperand(i)->getType()); 83 } 84 85 if (maxSize < sizeForThisCall) 86 maxSize = sizeForThisCall; 87 } 88 } 89 return maxSize; 90 } 91 92 // Align data larger than one L1 cache line on L1 cache line boundaries. 93 // Align all smaller data on the next higher 2^x boundary (4, 8, ...). 94 // 95 // THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND 96 // SHOULD BE USED DIRECTLY THERE 97 // 98 inline unsigned int 99 SizeToAlignment(unsigned int size, const TargetMachine& target) 100 { 101 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); 102 if (size > (unsigned) cacheLineSize / 2) 103 return cacheLineSize; 104 else 105 for (unsigned sz=1; /*no condition*/; sz *= 2) 106 if (sz >= size) 107 return sz; 108 } 109 110 111 112 /*ctor*/ 113 MachineCodeForMethod::MachineCodeForMethod(const Method* _M, 114 const TargetMachine& target) 115 : Annotation(MCFM_AID), 116 method(_M), compiledAsLeaf(false), staticStackSize(0), 117 automaticVarsSize(0), regSpillsSize(0), 118 currentOptionalArgsSize(0), maxOptionalArgsSize(0), 119 currentTmpValuesSize(0) 120 { 121 maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method); 122 staticStackSize = maxOptionalArgsSize + 123 target.getFrameInfo().getMinStackFrameSize(); 124 } 125 126 int 127 MachineCodeForMethod::allocateLocalVar(const TargetMachine& target, 128 const Value* val, 129 unsigned int size) 130 { 131 // Check if we've allocated a stack slot for this value already 132 // 133 int offset = getOffset(val); 134 if (offset == INVALID_FRAME_OFFSET) 135 { 136 bool growUp; 137 int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this, 138 growUp); 139 unsigned char align; 140 if (size == 0) 141 { 142 size = target.findOptimalStorageSize(val->getType()); 143 // align = target.DataLayout.getTypeAlignment(val->getType()); 144 } 145 146 align = SizeToAlignment(size, target); 147 148 offset = getAutomaticVarsSize(); 149 if (! growUp) 150 offset += size; 151 152 if (unsigned int mod = offset % align) 153 { 154 offset += align - mod; 155 size += align - mod; 156 } 157 158 offset = growUp? firstOffset + offset 159 : firstOffset - offset; 160 161 offsets[val] = offset; 162 163 incrementAutomaticVarsSize(size); 164 } 165 return offset; 166 } 167 168 int 169 MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target, 170 const Type* type) 171 { 172 unsigned int size = target.findOptimalStorageSize(type); 173 unsigned char align = target.DataLayout.getTypeAlignment(type); 174 175 bool growUp; 176 int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); 177 178 int offset = getRegSpillsSize(); 179 if (! growUp) 180 offset += size; 181 182 if (unsigned int mod = offset % align) 183 { 184 offset += align - mod; 185 size += align - mod; 186 } 187 188 offset = growUp? firstOffset + offset 189 : firstOffset - offset; 190 191 incrementRegSpillsSize(size); 192 193 return offset; 194 } 195 196 int 197 MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target, 198 const Type* type) 199 { 200 const MachineFrameInfo& frameInfo = target.getFrameInfo(); 201 202 int size = INT_MAX; 203 if (frameInfo.argsOnStackHaveFixedSize()) 204 size = frameInfo.getSizeOfEachArgOnStack(); 205 else 206 { 207 size = target.findOptimalStorageSize(type); 208 assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets"); 209 } 210 unsigned char align = target.DataLayout.getTypeAlignment(type); 211 212 bool growUp; 213 int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp); 214 215 int offset = getCurrentOptionalArgsSize(); 216 if (! growUp) 217 offset += size; 218 219 if (unsigned int mod = offset % align) 220 { 221 offset += align - mod; 222 size += align - mod; 223 } 224 225 offset = growUp? firstOffset + offset 226 : firstOffset - offset; 227 228 incrementCurrentOptionalArgsSize(size); 229 230 return offset; 231 } 232 233 void 234 MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target) 235 { 236 currentOptionalArgsSize = 0; 237 } 238 239 int 240 MachineCodeForMethod::pushTempValue(const TargetMachine& target, 241 unsigned int size) 242 { 243 // Compute a power-of-2 alignment according to the possible sizes, 244 // but not greater than the alignment of the largest type we support 245 // (currently a double word -- see class TargetData). 246 unsigned char align = 1; 247 for (; align < size && align < target.DataLayout.getDoubleAlignment(); 248 align = 2*align) 249 ; 250 251 bool growUp; 252 int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); 253 254 int offset = currentTmpValuesSize; 255 if (! growUp) 256 offset += size; 257 258 if (unsigned int mod = offset % align) 259 { 260 offset += align - mod; 261 size += align - mod; 262 } 263 264 offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset; 265 266 currentTmpValuesSize += size; 267 return offset; 268 } 269 270 void 271 MachineCodeForMethod::popAllTempValues(const TargetMachine& target) 272 { 273 currentTmpValuesSize = 0; 274 } 275 276 int 277 MachineCodeForMethod::getOffset(const Value* val) const 278 { 279 std::hash_map<const Value*, int>::const_iterator pair = offsets.find(val); 280 return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second; 281 } 282 283 void 284 MachineCodeForMethod::dump() const 285 { 286 cerr << "\n" << method->getReturnType() 287 << " \"" << method->getName() << "\"\n"; 288 289 for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI) 290 { 291 BasicBlock* bb = *BI; 292 cerr << "\n" 293 << (bb->hasName()? bb->getName() : "Label") 294 << " (" << bb << ")" << ":\n"; 295 296 MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec(); 297 for (unsigned i=0; i < mvec.size(); i++) 298 cerr << "\t" << *mvec[i]; 299 } 300 cerr << "\nEnd method \"" << method->getName() << "\"\n\n"; 301 } 302