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 21 const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max(); 22 23 static 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 // 33 MachineCodeForMethod& 34 MachineCodeForMethod::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 43 void 44 MachineCodeForMethod::destruct(const Function *M) 45 { 46 bool Deleted = M->deleteAnnotation(MCFM_AID); 47 assert(Deleted && "Machine code did not exist for function!"); 48 } 49 50 MachineCodeForMethod& 51 MachineCodeForMethod::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 58 static unsigned 59 ComputeMaxOptionalArgsSize(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 // 105 // THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND 106 // SHOULD BE USED DIRECTLY THERE 107 // 108 inline unsigned int 109 SizeToAlignment(unsigned int size, const TargetMachine& target) 110 { 111 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); 112 if (size > (unsigned) cacheLineSize / 2) 113 return cacheLineSize; 114 else 115 for (unsigned sz=1; /*no condition*/; sz *= 2) 116 if (sz >= size) 117 return sz; 118 } 119 120 121 122 /*ctor*/ 123 MachineCodeForMethod::MachineCodeForMethod(const Function *F, 124 const TargetMachine& target) 125 : Annotation(MCFM_AID), 126 method(F), staticStackSize(0), 127 automaticVarsSize(0), regSpillsSize(0), 128 maxOptionalArgsSize(0), maxOptionalNumArgs(0), 129 currentTmpValuesSize(0), maxTmpValuesSize(0), compiledAsLeaf(false), 130 spillsAreaFrozen(false), automaticVarsAreaFrozen(false) 131 { 132 maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method, 133 maxOptionalNumArgs); 134 staticStackSize = maxOptionalArgsSize 135 + target.getFrameInfo().getMinStackFrameSize(); 136 } 137 138 int 139 MachineCodeForMethod::computeOffsetforLocalVar(const TargetMachine& target, 140 const Value* val, 141 unsigned int& getPaddedSize, 142 unsigned int sizeToUse = 0) 143 { 144 bool growUp; 145 int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this, 146 growUp); 147 unsigned char align; 148 if (sizeToUse == 0) 149 { 150 sizeToUse = target.findOptimalStorageSize(val->getType()); 151 // align = target.DataLayout.getTypeAlignment(val->getType()); 152 } 153 154 align = SizeToAlignment(sizeToUse, target); 155 156 int offset = getAutomaticVarsSize(); 157 if (! growUp) 158 offset += sizeToUse; 159 160 if (unsigned int mod = offset % align) 161 { 162 offset += align - mod; 163 getPaddedSize = sizeToUse + align - mod; 164 } 165 else 166 getPaddedSize = sizeToUse; 167 168 offset = growUp? firstOffset + offset 169 : firstOffset - offset; 170 171 return offset; 172 } 173 174 int 175 MachineCodeForMethod::allocateLocalVar(const TargetMachine& target, 176 const Value* val, 177 unsigned int sizeToUse = 0) 178 { 179 assert(! automaticVarsAreaFrozen && 180 "Size of auto vars area has been used to compute an offset so " 181 "no more automatic vars should be allocated!"); 182 183 // Check if we've allocated a stack slot for this value already 184 // 185 int offset = getOffset(val); 186 if (offset == INVALID_FRAME_OFFSET) 187 { 188 unsigned int getPaddedSize; 189 offset = this->computeOffsetforLocalVar(target, val, getPaddedSize, 190 sizeToUse); 191 offsets[val] = offset; 192 incrementAutomaticVarsSize(getPaddedSize); 193 } 194 return offset; 195 } 196 197 int 198 MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target, 199 const Type* type) 200 { 201 assert(! spillsAreaFrozen && 202 "Size of reg spills area has been used to compute an offset so " 203 "no more register spill slots should be allocated!"); 204 205 unsigned int size = target.findOptimalStorageSize(type); 206 unsigned char align = target.DataLayout.getTypeAlignment(type); 207 208 bool growUp; 209 int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); 210 211 int offset = getRegSpillsSize(); 212 if (! growUp) 213 offset += size; 214 215 if (unsigned int mod = offset % align) 216 { 217 offset += align - mod; 218 size += align - mod; 219 } 220 221 offset = growUp? firstOffset + offset 222 : firstOffset - offset; 223 224 incrementRegSpillsSize(size); 225 226 return offset; 227 } 228 229 int 230 MachineCodeForMethod::pushTempValue(const TargetMachine& target, 231 unsigned int size) 232 { 233 // Compute a power-of-2 alignment according to the possible sizes, 234 // but not greater than the alignment of the largest type we support 235 // (currently a double word -- see class TargetData). 236 unsigned char align = 1; 237 for (; align < size && align < target.DataLayout.getDoubleAlignment(); 238 align = 2*align) 239 ; 240 241 bool growUp; 242 int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); 243 244 int offset = currentTmpValuesSize; 245 if (! growUp) 246 offset += size; 247 248 if (unsigned int mod = offset % align) 249 { 250 offset += align - mod; 251 size += align - mod; 252 } 253 254 offset = growUp ? firstTmpOffset + offset : firstTmpOffset - offset; 255 256 incrementTmpAreaSize(size); 257 return offset; 258 } 259 260 void 261 MachineCodeForMethod::popAllTempValues(const TargetMachine& target) 262 { 263 resetTmpAreaSize(); 264 } 265 266 int 267 MachineCodeForMethod::getOffset(const Value* val) const 268 { 269 hash_map<const Value*, int>::const_iterator pair = offsets.find(val); 270 return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second; 271 } 272 273 void 274 MachineCodeForMethod::dump() const 275 { 276 std::cerr << "\n" << method->getReturnType() 277 << " \"" << method->getName() << "\"\n"; 278 279 for (Function::const_iterator BB = method->begin(); BB != method->end(); ++BB) 280 { 281 std::cerr << std::endl << (*BB).getName() << " (" << (const void*) BB << ")" << ":" << std::endl; 282 MachineCodeForBasicBlock& mvec = MachineCodeForBasicBlock::get(BB); 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