1 //===-- MachineFunction.cpp -----------------------------------------------===// 2 // 3 // Collect native machine code information for a function. This allows 4 // target-specific information about the generated code to be stored with each 5 // function. 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/CodeGen/MachineInstr.h" // For debug output 10 #include "llvm/CodeGen/MachineFunction.h" 11 #include "llvm/CodeGen/MachineCodeForInstruction.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 "llvm/Pass.h" 18 #include <limits.h> 19 20 const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max(); 21 22 static AnnotationID MF_AID( 23 AnnotationManager::getID("CodeGen::MachineCodeForFunction")); 24 25 26 //===---------------------------------------------------------------------===// 27 // Code generation/destruction passes 28 //===---------------------------------------------------------------------===// 29 30 namespace { 31 class ConstructMachineFunction : public FunctionPass { 32 TargetMachine &Target; 33 public: 34 ConstructMachineFunction(TargetMachine &T) : Target(T) {} 35 36 const char *getPassName() const { 37 return "ConstructMachineFunction"; 38 } 39 40 bool runOnFunction(Function &F) { 41 MachineFunction::construct(&F, Target).CalculateArgSize(); 42 return false; 43 } 44 }; 45 46 struct DestroyMachineFunction : public FunctionPass { 47 const char *getPassName() const { return "FreeMachineFunction"; } 48 49 static void freeMachineCode(Instruction &I) { 50 MachineCodeForInstruction::destroy(&I); 51 } 52 53 bool runOnFunction(Function &F) { 54 for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) 55 for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I) 56 MachineCodeForInstruction::get(I).dropAllReferences(); 57 58 for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) 59 for_each(FI->begin(), FI->end(), freeMachineCode); 60 61 return false; 62 } 63 }; 64 65 struct Printer : public FunctionPass { 66 const char *getPassName() const { return "MachineFunction Printer"; } 67 68 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 69 AU.setPreservesAll(); 70 } 71 72 bool runOnFunction(Function &F) { 73 MachineFunction::get(&F).dump(); 74 return false; 75 } 76 }; 77 } 78 79 Pass *createMachineCodeConstructionPass(TargetMachine &Target) { 80 return new ConstructMachineFunction(Target); 81 } 82 83 Pass *createMachineCodeDestructionPass() { 84 return new DestroyMachineFunction(); 85 } 86 87 Pass *createMachineFunctionPrinterPass() { 88 return new Printer(); 89 } 90 91 92 //===---------------------------------------------------------------------===// 93 // MachineFunction implementation 94 //===---------------------------------------------------------------------===// 95 96 MachineFunction::MachineFunction(const Function *F, 97 const TargetMachine& target) 98 : Annotation(MF_AID), 99 Fn(F), Target(target), staticStackSize(0), 100 automaticVarsSize(0), regSpillsSize(0), 101 maxOptionalArgsSize(0), maxOptionalNumArgs(0), 102 currentTmpValuesSize(0), maxTmpValuesSize(0), compiledAsLeaf(false), 103 spillsAreaFrozen(false), automaticVarsAreaFrozen(false) 104 { 105 SSARegMapping = new SSARegMap(); 106 } 107 108 void MachineFunction::dump() const { print(std::cerr); } 109 110 void MachineFunction::print(std::ostream &OS) const { 111 OS << "\n" << *(Value*)Fn->getReturnType() << " \"" << Fn->getName()<< "\"\n"; 112 113 for (const_iterator BB = begin(); BB != end(); ++BB) { 114 BasicBlock *LBB = BB->getBasicBlock(); 115 OS << "\n" << LBB->getName() << " (" 116 << (const void*)BB->getBasicBlock() << "):\n"; 117 for (MachineBasicBlock::const_iterator I = BB->begin(); I != BB->end();++I){ 118 OS << "\t"; 119 (*I)->print(OS, Target); 120 } 121 } 122 OS << "\nEnd function \"" << Fn->getName() << "\"\n\n"; 123 } 124 125 126 // The next two methods are used to construct and to retrieve 127 // the MachineCodeForFunction object for the given function. 128 // construct() -- Allocates and initializes for a given function and target 129 // get() -- Returns a handle to the object. 130 // This should not be called before "construct()" 131 // for a given Function. 132 // 133 MachineFunction& 134 MachineFunction::construct(const Function *Fn, const TargetMachine &Tar) 135 { 136 assert(Fn->getAnnotation(MF_AID) == 0 && 137 "Object already exists for this function!"); 138 MachineFunction* mcInfo = new MachineFunction(Fn, Tar); 139 Fn->addAnnotation(mcInfo); 140 return *mcInfo; 141 } 142 143 void 144 MachineFunction::destruct(const Function *Fn) 145 { 146 bool Deleted = Fn->deleteAnnotation(MF_AID); 147 assert(Deleted && "Machine code did not exist for function!"); 148 } 149 150 MachineFunction& MachineFunction::get(const Function *F) 151 { 152 MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID); 153 assert(mc && "Call construct() method first to allocate the object"); 154 return *mc; 155 } 156 157 static unsigned 158 ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F, 159 unsigned &maxOptionalNumArgs) 160 { 161 const MachineFrameInfo& frameInfo = target.getFrameInfo(); 162 163 unsigned maxSize = 0; 164 165 for (Function::const_iterator BB = F->begin(), BBE = F->end(); BB !=BBE; ++BB) 166 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) 167 if (const CallInst *callInst = dyn_cast<CallInst>(&*I)) 168 { 169 unsigned numOperands = callInst->getNumOperands() - 1; 170 int numExtra = (int)numOperands-frameInfo.getNumFixedOutgoingArgs(); 171 if (numExtra <= 0) 172 continue; 173 174 unsigned int sizeForThisCall; 175 if (frameInfo.argsOnStackHaveFixedSize()) 176 { 177 int argSize = frameInfo.getSizeOfEachArgOnStack(); 178 sizeForThisCall = numExtra * (unsigned) argSize; 179 } 180 else 181 { 182 assert(0 && "UNTESTED CODE: Size per stack argument is not " 183 "fixed on this architecture: use actual arg sizes to " 184 "compute MaxOptionalArgsSize"); 185 sizeForThisCall = 0; 186 for (unsigned i = 0; i < numOperands; ++i) 187 sizeForThisCall += target.DataLayout.getTypeSize(callInst-> 188 getOperand(i)->getType()); 189 } 190 191 if (maxSize < sizeForThisCall) 192 maxSize = sizeForThisCall; 193 194 if ((int)maxOptionalNumArgs < numExtra) 195 maxOptionalNumArgs = (unsigned) numExtra; 196 } 197 198 return maxSize; 199 } 200 201 // Align data larger than one L1 cache line on L1 cache line boundaries. 202 // Align all smaller data on the next higher 2^x boundary (4, 8, ...), 203 // but not higher than the alignment of the largest type we support 204 // (currently a double word). -- see class TargetData). 205 // 206 // This function is similar to the corresponding function in EmitAssembly.cpp 207 // but they are unrelated. This one does not align at more than a 208 // double-word boundary whereas that one might. 209 // 210 inline unsigned int 211 SizeToAlignment(unsigned int size, const TargetMachine& target) 212 { 213 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); 214 if (size > (unsigned) cacheLineSize / 2) 215 return cacheLineSize; 216 else 217 for (unsigned sz=1; /*no condition*/; sz *= 2) 218 if (sz >= size || sz >= target.DataLayout.getDoubleAlignment()) 219 return sz; 220 } 221 222 223 void MachineFunction::CalculateArgSize() { 224 maxOptionalArgsSize = ComputeMaxOptionalArgsSize(Target, Fn, 225 maxOptionalNumArgs); 226 staticStackSize = maxOptionalArgsSize 227 + Target.getFrameInfo().getMinStackFrameSize(); 228 } 229 230 int 231 MachineFunction::computeOffsetforLocalVar(const TargetMachine& target, 232 const Value* val, 233 unsigned int& getPaddedSize, 234 unsigned int sizeToUse) 235 { 236 if (sizeToUse == 0) 237 sizeToUse = target.findOptimalStorageSize(val->getType()); 238 unsigned int align = SizeToAlignment(sizeToUse, target); 239 240 bool growUp; 241 int firstOffset = target.getFrameInfo().getFirstAutomaticVarOffset(*this, 242 growUp); 243 int offset = growUp? firstOffset + getAutomaticVarsSize() 244 : firstOffset - (getAutomaticVarsSize() + sizeToUse); 245 246 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 247 getPaddedSize = sizeToUse + abs(aligned - offset); 248 249 return aligned; 250 } 251 252 int 253 MachineFunction::allocateLocalVar(const TargetMachine& target, 254 const Value* val, 255 unsigned int sizeToUse) 256 { 257 assert(! automaticVarsAreaFrozen && 258 "Size of auto vars area has been used to compute an offset so " 259 "no more automatic vars should be allocated!"); 260 261 // Check if we've allocated a stack slot for this value already 262 // 263 int offset = getOffset(val); 264 if (offset == INVALID_FRAME_OFFSET) 265 { 266 unsigned int getPaddedSize; 267 offset = computeOffsetforLocalVar(target, val, getPaddedSize, sizeToUse); 268 offsets[val] = offset; 269 incrementAutomaticVarsSize(getPaddedSize); 270 } 271 return offset; 272 } 273 274 int 275 MachineFunction::allocateSpilledValue(const TargetMachine& target, 276 const Type* type) 277 { 278 assert(! spillsAreaFrozen && 279 "Size of reg spills area has been used to compute an offset so " 280 "no more register spill slots should be allocated!"); 281 282 unsigned int size = target.DataLayout.getTypeSize(type); 283 unsigned char align = target.DataLayout.getTypeAlignment(type); 284 285 bool growUp; 286 int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); 287 288 int offset = growUp? firstOffset + getRegSpillsSize() 289 : firstOffset - (getRegSpillsSize() + size); 290 291 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 292 size += abs(aligned - offset); // include alignment padding in size 293 294 incrementRegSpillsSize(size); // update size of reg. spills area 295 296 return aligned; 297 } 298 299 int 300 MachineFunction::pushTempValue(const TargetMachine& target, 301 unsigned int size) 302 { 303 unsigned int align = SizeToAlignment(size, target); 304 305 bool growUp; 306 int firstOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); 307 308 int offset = growUp? firstOffset + currentTmpValuesSize 309 : firstOffset - (currentTmpValuesSize + size); 310 311 int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align); 312 size += abs(aligned - offset); // include alignment padding in size 313 314 incrementTmpAreaSize(size); // update "current" size of tmp area 315 316 return aligned; 317 } 318 319 void 320 MachineFunction::popAllTempValues(const TargetMachine& target) 321 { 322 resetTmpAreaSize(); // clear tmp area to reuse 323 } 324 325 int 326 MachineFunction::getOffset(const Value* val) const 327 { 328 hash_map<const Value*, int>::const_iterator pair = offsets.find(val); 329 return (pair == offsets.end()) ? INVALID_FRAME_OFFSET : pair->second; 330 } 331