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