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/MachineFunction.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/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::MachineCodeForFunction")); 23 24 // The next two methods are used to construct and to retrieve 25 // the MachineCodeForFunction object for the given function. 26 // construct() -- Allocates and initializes for a given function and target 27 // get() -- Returns a handle to the object. 28 // This should not be called before "construct()" 29 // for a given Function. 30 // 31 MachineFunction& 32 MachineFunction::construct(const Function *M, const TargetMachine &Tar) 33 { 34 assert(M->getAnnotation(MCFM_AID) == 0 && 35 "Object already exists for this function!"); 36 MachineFunction* mcInfo = new MachineFunction(M, Tar); 37 M->addAnnotation(mcInfo); 38 return *mcInfo; 39 } 40 41 void 42 MachineFunction::destruct(const Function *M) 43 { 44 bool Deleted = M->deleteAnnotation(MCFM_AID); 45 assert(Deleted && "Machine code did not exist for function!"); 46 } 47 48 MachineFunction& 49 MachineFunction::get(const Function *F) 50 { 51 MachineFunction *mc = (MachineFunction*)F->getAnnotation(MCFM_AID); 52 assert(mc && "Call construct() method first to allocate the object"); 53 return *mc; 54 } 55 56 static unsigned 57 ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F, 58 unsigned &maxOptionalNumArgs) 59 { 60 const MachineFrameInfo& frameInfo = target.getFrameInfo(); 61 62 unsigned maxSize = 0; 63 64 for (Function::const_iterator BB = F->begin(), BBE = F->end(); BB !=BBE; ++BB) 65 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) 66 if (const CallInst *callInst = dyn_cast<CallInst>(&*I)) 67 { 68 unsigned numOperands = callInst->getNumOperands() - 1; 69 int numExtra = (int)numOperands-frameInfo.getNumFixedOutgoingArgs(); 70 if (numExtra <= 0) 71 continue; 72 73 unsigned int sizeForThisCall; 74 if (frameInfo.argsOnStackHaveFixedSize()) 75 { 76 int argSize = frameInfo.getSizeOfEachArgOnStack(); 77 sizeForThisCall = numExtra * (unsigned) argSize; 78 } 79 else 80 { 81 assert(0 && "UNTESTED CODE: Size per stack argument is not " 82 "fixed on this architecture: use actual arg sizes to " 83 "compute MaxOptionalArgsSize"); 84 sizeForThisCall = 0; 85 for (unsigned i = 0; i < numOperands; ++i) 86 sizeForThisCall += target.DataLayout.getTypeSize(callInst-> 87 getOperand(i)->getType()); 88 } 89 90 if (maxSize < sizeForThisCall) 91 maxSize = sizeForThisCall; 92 93 if ((int)maxOptionalNumArgs < numExtra) 94 maxOptionalNumArgs = (unsigned) numExtra; 95 } 96 97 return maxSize; 98 } 99 100 // Align data larger than one L1 cache line on L1 cache line boundaries. 101 // Align all smaller data on the next higher 2^x boundary (4, 8, ...), 102 // but not higher than the alignment of the largest type we support 103 // (currently a double word). -- see class TargetData). 104 // 105 // This function is similar to the corresponding function in EmitAssembly.cpp 106 // but they are unrelated. This one does not align at more than a 107 // double-word boundary whereas that one might. 108 // 109 inline unsigned int 110 SizeToAlignment(unsigned int size, const TargetMachine& target) 111 { 112 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); 113 if (size > (unsigned) cacheLineSize / 2) 114 return cacheLineSize; 115 else 116 for (unsigned sz=1; /*no condition*/; sz *= 2) 117 if (sz >= size || sz >= target.DataLayout.getDoubleAlignment()) 118 return sz; 119 } 120 121 122 /*ctor*/ 123 MachineFunction::MachineFunction(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 MachineFunction::computeOffsetforLocalVar(const TargetMachine& target, 140 const Value* val, 141 unsigned int& getPaddedSize, 142 unsigned int sizeToUse) 143 { 144 if (sizeToUse == 0) 145 sizeToUse = target.findOptimalStorageSize(val->getType()); 146 unsigned int align = SizeToAlignment(sizeToUse, target); 147 148 bool growUp; 149 int firstOffset = target.getFrameInfo().getFirstAutomaticVarOffset(*this, 150 growUp); 151 int offset = growUp? firstOffset + getAutomaticVarsSize() 152 : firstOffset - (getAutomaticVarsSize() + sizeToUse); 153 154 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 155 getPaddedSize = sizeToUse + abs(aligned - offset); 156 157 return aligned; 158 } 159 160 int 161 MachineFunction::allocateLocalVar(const TargetMachine& target, 162 const Value* val, 163 unsigned int sizeToUse) 164 { 165 assert(! automaticVarsAreaFrozen && 166 "Size of auto vars area has been used to compute an offset so " 167 "no more automatic vars should be allocated!"); 168 169 // Check if we've allocated a stack slot for this value already 170 // 171 int offset = getOffset(val); 172 if (offset == INVALID_FRAME_OFFSET) 173 { 174 unsigned int getPaddedSize; 175 offset = this->computeOffsetforLocalVar(target, val, getPaddedSize, 176 sizeToUse); 177 offsets[val] = offset; 178 incrementAutomaticVarsSize(getPaddedSize); 179 } 180 return offset; 181 } 182 183 int 184 MachineFunction::allocateSpilledValue(const TargetMachine& target, 185 const Type* type) 186 { 187 assert(! spillsAreaFrozen && 188 "Size of reg spills area has been used to compute an offset so " 189 "no more register spill slots should be allocated!"); 190 191 unsigned int size = target.DataLayout.getTypeSize(type); 192 unsigned char align = target.DataLayout.getTypeAlignment(type); 193 194 bool growUp; 195 int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); 196 197 int offset = growUp? firstOffset + getRegSpillsSize() 198 : firstOffset - (getRegSpillsSize() + size); 199 200 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 201 size += abs(aligned - offset); // include alignment padding in size 202 203 incrementRegSpillsSize(size); // update size of reg. spills area 204 205 return aligned; 206 } 207 208 int 209 MachineFunction::pushTempValue(const TargetMachine& target, 210 unsigned int size) 211 { 212 unsigned int align = SizeToAlignment(size, target); 213 214 bool growUp; 215 int firstOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); 216 217 int offset = growUp? firstOffset + currentTmpValuesSize 218 : firstOffset - (currentTmpValuesSize + size); 219 220 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 221 size += abs(aligned - offset); // include alignment padding in size 222 223 incrementTmpAreaSize(size); // update "current" size of tmp area 224 225 return aligned; 226 } 227 228 void 229 MachineFunction::popAllTempValues(const TargetMachine& target) 230 { 231 resetTmpAreaSize(); // clear tmp area to reuse 232 } 233 234 int 235 MachineFunction::getOffset(const Value* val) const 236 { 237 hash_map<const Value*, int>::const_iterator pair = offsets.find(val); 238 return (pair == offsets.end())? INVALID_FRAME_OFFSET : pair->second; 239 } 240 241 void 242 MachineFunction::dump() const 243 { 244 std::cerr << "\n" << method->getReturnType() 245 << " \"" << method->getName() << "\"\n"; 246 247 for (Function::const_iterator BB = method->begin(); BB != method->end(); ++BB) 248 { 249 std::cerr << std::endl << (*BB).getName() << " (" << (const void*) BB << ")" << ":" << std::endl; 250 MachineCodeForBasicBlock& mvec = MachineCodeForBasicBlock::get(BB); 251 for (unsigned i=0; i < mvec.size(); i++) 252 std::cerr << "\t" << *mvec[i]; 253 } 254 std::cerr << "\nEnd function \"" << method->getName() << "\"\n\n"; 255 } 256