1 // $Id$ 2 //*************************************************************************** 3 // File: 4 // MachineInstr.cpp 5 // 6 // Purpose: 7 // 8 // 9 // Strategy: 10 // 11 // History: 12 // 7/2/01 - Vikram Adve - Created 13 //**************************************************************************/ 14 15 16 #include "llvm/CodeGen/MachineInstr.h" 17 #include "llvm/Target/MachineFrameInfo.h" 18 #include "llvm/Target/MachineRegInfo.h" 19 #include "llvm/Target/MachineCacheInfo.h" 20 #include "llvm/Method.h" 21 #include "llvm/iOther.h" 22 #include "llvm/Instruction.h" 23 24 AnnotationID MachineCodeForMethod::AID( 25 AnnotationManager::getID("MachineCodeForMethodAnnotation")); 26 27 28 //************************ Class Implementations **************************/ 29 30 // Constructor for instructions with fixed #operands (nearly all) 31 MachineInstr::MachineInstr(MachineOpCode _opCode, 32 OpCodeMask _opCodeMask) 33 : opCode(_opCode), 34 opCodeMask(_opCodeMask), 35 operands(TargetInstrDescriptors[_opCode].numOperands) 36 { 37 assert(TargetInstrDescriptors[_opCode].numOperands >= 0); 38 } 39 40 // Constructor for instructions with variable #operands 41 MachineInstr::MachineInstr(MachineOpCode _opCode, 42 unsigned numOperands, 43 OpCodeMask _opCodeMask) 44 : opCode(_opCode), 45 opCodeMask(_opCodeMask), 46 operands(numOperands) 47 { 48 } 49 50 void 51 MachineInstr::SetMachineOperand(unsigned int i, 52 MachineOperand::MachineOperandType operandType, 53 Value* _val, bool isdef=false) 54 { 55 assert(i < operands.size()); 56 operands[i].Initialize(operandType, _val); 57 operands[i].isDef = isdef || 58 TargetInstrDescriptors[opCode].resultPos == (int) i; 59 } 60 61 void 62 MachineInstr::SetMachineOperand(unsigned int i, 63 MachineOperand::MachineOperandType operandType, 64 int64_t intValue, bool isdef=false) 65 { 66 assert(i < operands.size()); 67 operands[i].InitializeConst(operandType, intValue); 68 operands[i].isDef = isdef || 69 TargetInstrDescriptors[opCode].resultPos == (int) i; 70 } 71 72 void 73 MachineInstr::SetMachineOperand(unsigned int i, 74 int regNum, bool isdef=false) 75 { 76 assert(i < operands.size()); 77 operands[i].InitializeReg(regNum); 78 operands[i].isDef = isdef || 79 TargetInstrDescriptors[opCode].resultPos == (int) i; 80 } 81 82 void 83 MachineInstr::dump(unsigned int indent) const 84 { 85 for (unsigned i=0; i < indent; i++) 86 cout << " "; 87 88 cout << *this; 89 } 90 91 ostream& 92 operator<< (ostream& os, const MachineInstr& minstr) 93 { 94 os << TargetInstrDescriptors[minstr.opCode].opCodeString; 95 96 for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++) { 97 os << "\t" << minstr.getOperand(i); 98 if( minstr.getOperand(i).opIsDef() ) 99 os << "*"; 100 } 101 102 #undef DEBUG_VAL_OP_ITERATOR 103 #ifdef DEBUG_VAL_OP_ITERATOR 104 os << endl << "\tValue operands are: "; 105 for (MachineInstr::val_const_op_iterator vo(&minstr); ! vo.done(); ++vo) 106 { 107 const Value* val = *vo; 108 os << val << (vo.isDef()? "(def), " : ", "); 109 } 110 #endif 111 112 113 114 #if 1 115 // code for printing implict references 116 117 unsigned NumOfImpRefs = minstr.getNumImplicitRefs(); 118 if( NumOfImpRefs > 0 ) { 119 120 os << "\tImplicit:"; 121 122 for(unsigned z=0; z < NumOfImpRefs; z++) { 123 os << minstr.getImplicitRef(z); 124 if( minstr.implicitRefIsDefined(z)) os << "*"; 125 os << "\t"; 126 } 127 } 128 129 #endif 130 131 132 os << endl; 133 134 return os; 135 } 136 137 static inline ostream& 138 OutputOperand(ostream &os, const MachineOperand &mop) 139 { 140 Value* val; 141 switch (mop.getOperandType()) 142 { 143 case MachineOperand::MO_CCRegister: 144 case MachineOperand::MO_VirtualRegister: 145 val = mop.getVRegValue(); 146 os << "(val "; 147 if (val && val->hasName()) 148 os << val->getName().c_str(); 149 else 150 os << val; 151 return os << ")"; 152 case MachineOperand::MO_MachineRegister: 153 return os << "(" << mop.getMachineRegNum() << ")"; 154 default: 155 assert(0 && "Unknown operand type"); 156 return os; 157 } 158 } 159 160 161 ostream& 162 operator<<(ostream &os, const MachineOperand &mop) 163 { 164 switch(mop.opType) 165 { 166 case MachineOperand::MO_VirtualRegister: 167 case MachineOperand::MO_MachineRegister: 168 os << "%reg"; 169 return OutputOperand(os, mop); 170 case MachineOperand::MO_CCRegister: 171 os << "%ccreg"; 172 return OutputOperand(os, mop); 173 case MachineOperand::MO_SignExtendedImmed: 174 return os << mop.immedVal; 175 case MachineOperand::MO_UnextendedImmed: 176 return os << mop.immedVal; 177 case MachineOperand::MO_PCRelativeDisp: 178 { 179 const Value* opVal = mop.getVRegValue(); 180 bool isLabel = isa<Method>(opVal) || isa<BasicBlock>(opVal); 181 os << "%disp(" << (isLabel? "label " : "addr-of-val "); 182 if (opVal->hasName()) 183 os << opVal->getName().c_str(); 184 else 185 os << opVal; 186 return os << ")"; 187 } 188 default: 189 assert(0 && "Unrecognized operand type"); 190 break; 191 } 192 193 return os; 194 } 195 196 // Align data larger than one L1 cache line on L1 cache line boundaries. 197 // Align all smaller data on the next higher 2^x boundary (4, 8, ...). 198 // 199 // THIS FUNCTION HAS BEEN COPIED FROM EMITASSEMBLY.CPP AND 200 // SHOULD BE USED DIRECTLY THERE 201 // 202 inline unsigned int 203 SizeToAlignment(unsigned int size, const TargetMachine& target) 204 { 205 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); 206 if (size > (unsigned) cacheLineSize / 2) 207 return cacheLineSize; 208 else 209 for (unsigned sz=1; /*no condition*/; sz *= 2) 210 if (sz >= size) 211 return sz; 212 } 213 214 static unsigned int 215 ComputeMaxOptionalArgsSize(const TargetMachine& target, const Method* method) 216 { 217 const MachineFrameInfo& frameInfo = target.getFrameInfo(); 218 219 unsigned int maxSize = 0; 220 221 for (Method::const_inst_iterator I=method->inst_begin(),E=method->inst_end(); 222 I != E; ++I) 223 if ((*I)->getOpcode() == Instruction::Call) 224 { 225 CallInst* callInst = cast<CallInst>(*I); 226 unsigned int numOperands = callInst->getNumOperands() - 1; 227 int numExtra = (int) numOperands - frameInfo.getNumFixedOutgoingArgs(); 228 if (numExtra <= 0) 229 continue; 230 231 unsigned int sizeForThisCall; 232 if (frameInfo.argsOnStackHaveFixedSize()) 233 { 234 int argSize = frameInfo.getSizeOfEachArgOnStack(); 235 sizeForThisCall = numExtra * (unsigned) argSize; 236 } 237 else 238 { 239 assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual arg sizes to compute MaxOptionalArgsSize"); 240 sizeForThisCall = 0; 241 for (unsigned i=0; i < numOperands; ++i) 242 sizeForThisCall += target.findOptimalStorageSize(callInst-> 243 getOperand(i)->getType()); 244 } 245 246 if (maxSize < sizeForThisCall) 247 maxSize = sizeForThisCall; 248 } 249 250 return maxSize; 251 } 252 253 254 /*ctor*/ 255 MachineCodeForMethod::MachineCodeForMethod(const Method* _M, 256 const TargetMachine& target) 257 : Annotation(AID), 258 method(_M), compiledAsLeaf(false), staticStackSize(0), 259 automaticVarsSize(0), regSpillsSize(0), 260 currentOptionalArgsSize(0), maxOptionalArgsSize(0), 261 currentTmpValuesSize(0) 262 { 263 maxOptionalArgsSize = ComputeMaxOptionalArgsSize(target, method); 264 staticStackSize = maxOptionalArgsSize + 265 target.getFrameInfo().getMinStackFrameSize(); 266 } 267 268 int 269 MachineCodeForMethod::allocateLocalVar(const TargetMachine& target, 270 const Value* val, 271 unsigned int size) 272 { 273 // Check if we've allocated a stack slot for this value already 274 // 275 int offset = getOffset(val); 276 if (offset == INVALID_FRAME_OFFSET) 277 { 278 bool growUp; 279 int firstOffset =target.getFrameInfo().getFirstAutomaticVarOffset(*this, 280 growUp); 281 unsigned char align; 282 if (size == 0) 283 { 284 size = target.findOptimalStorageSize(val->getType()); 285 // align = target.DataLayout.getTypeAlignment(val->getType()); 286 } 287 288 align = SizeToAlignment(size, target); 289 290 offset = getAutomaticVarsSize(); 291 if (! growUp) 292 offset += size; 293 294 if (unsigned int mod = offset % align) 295 { 296 offset += align - mod; 297 size += align - mod; 298 } 299 300 offset = growUp? firstOffset + offset 301 : firstOffset - offset; 302 303 offsets[val] = offset; 304 305 incrementAutomaticVarsSize(size); 306 } 307 return offset; 308 } 309 310 int 311 MachineCodeForMethod::allocateSpilledValue(const TargetMachine& target, 312 const Type* type) 313 { 314 unsigned int size = target.findOptimalStorageSize(type); 315 unsigned char align = target.DataLayout.getTypeAlignment(type); 316 317 bool growUp; 318 int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp); 319 320 int offset = getRegSpillsSize(); 321 if (! growUp) 322 offset += size; 323 324 if (unsigned int mod = offset % align) 325 { 326 offset += align - mod; 327 size += align - mod; 328 } 329 330 offset = growUp? firstOffset + offset 331 : firstOffset - offset; 332 333 incrementRegSpillsSize(size); 334 335 return offset; 336 } 337 338 int 339 MachineCodeForMethod::allocateOptionalArg(const TargetMachine& target, 340 const Type* type) 341 { 342 const MachineFrameInfo& frameInfo = target.getFrameInfo(); 343 344 int size = MAXINT; 345 if (frameInfo.argsOnStackHaveFixedSize()) 346 size = frameInfo.getSizeOfEachArgOnStack(); 347 else 348 { 349 size = target.findOptimalStorageSize(type); 350 assert(0 && "UNTESTED CODE: Size per stack argument is not fixed on this architecture: use actual argument sizes for computing optional arg offsets"); 351 } 352 unsigned char align = target.DataLayout.getTypeAlignment(type); 353 354 bool growUp; 355 int firstOffset = frameInfo.getFirstOptionalOutgoingArgOffset(*this, growUp); 356 357 int offset = getCurrentOptionalArgsSize(); 358 if (! growUp) 359 offset += size; 360 361 if (unsigned int mod = offset % align) 362 { 363 offset += align - mod; 364 size += align - mod; 365 } 366 367 offset = growUp? firstOffset + offset 368 : firstOffset - offset; 369 370 incrementCurrentOptionalArgsSize(size); 371 372 return offset; 373 } 374 375 void 376 MachineCodeForMethod::resetOptionalArgs(const TargetMachine& target) 377 { 378 currentOptionalArgsSize = 0; 379 } 380 381 int 382 MachineCodeForMethod::pushTempValue(const TargetMachine& target, 383 unsigned int size) 384 { 385 // Compute a power-of-2 alignment according to the possible sizes, 386 // but not greater than the alignment of the largest type we support 387 // (currently a double word -- see class TargetData). 388 unsigned char align = 1; 389 for (; align < size && align < target.DataLayout.getDoubleAlignment(); 390 align = 2*align) 391 ; 392 393 bool growUp; 394 int firstTmpOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp); 395 396 int offset = currentTmpValuesSize; 397 if (! growUp) 398 offset += size; 399 400 if (unsigned int mod = offset % align) 401 { 402 offset += align - mod; 403 size += align - mod; 404 } 405 406 offset = growUp? firstTmpOffset + offset 407 : firstTmpOffset - offset; 408 409 currentTmpValuesSize += size; 410 return offset; 411 } 412 413 void 414 MachineCodeForMethod::popAllTempValues(const TargetMachine& target) 415 { 416 currentTmpValuesSize = 0; 417 } 418 419 int 420 MachineCodeForMethod::getOffset(const Value* val) const 421 { 422 hash_map<const Value*, int>::const_iterator pair = offsets.find(val); 423 return (pair == offsets.end())? INVALID_FRAME_OFFSET : (*pair).second; 424 } 425 426 void 427 MachineCodeForMethod::dump() const 428 { 429 cout << "\n" << method->getReturnType() 430 << " \"" << method->getName() << "\"" << endl; 431 432 for (Method::const_iterator BI = method->begin(); BI != method->end(); ++BI) 433 { 434 BasicBlock* bb = *BI; 435 cout << "\n" 436 << (bb->hasName()? bb->getName() : "Label") 437 << " (" << bb << ")" << ":" 438 << endl; 439 440 MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec(); 441 for (unsigned i=0; i < mvec.size(); i++) 442 cout << "\t" << *mvec[i]; 443 } 444 cout << endl << "End method \"" << method->getName() << "\"" 445 << endl << endl; 446 } 447