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