1 //===-- MipsAsmPrinter.cpp - Mips LLVM Assembly Printer -------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains a printer that converts from our internal representation 11 // of machine-dependent LLVM code to GAS-format MIPS assembly language. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #define DEBUG_TYPE "mips-asm-printer" 16 #include "MipsAsmPrinter.h" 17 #include "Mips.h" 18 #include "MipsInstrInfo.h" 19 #include "InstPrinter/MipsInstPrinter.h" 20 #include "MCTargetDesc/MipsBaseInfo.h" 21 #include "llvm/ADT/SmallString.h" 22 #include "llvm/ADT/StringExtras.h" 23 #include "llvm/ADT/Twine.h" 24 #include "llvm/Analysis/DebugInfo.h" 25 #include "llvm/BasicBlock.h" 26 #include "llvm/Instructions.h" 27 #include "llvm/CodeGen/MachineFunctionPass.h" 28 #include "llvm/CodeGen/MachineConstantPool.h" 29 #include "llvm/CodeGen/MachineFrameInfo.h" 30 #include "llvm/CodeGen/MachineInstr.h" 31 #include "llvm/CodeGen/MachineMemOperand.h" 32 #include "llvm/Instructions.h" 33 #include "llvm/MC/MCStreamer.h" 34 #include "llvm/MC/MCAsmInfo.h" 35 #include "llvm/MC/MCInst.h" 36 #include "llvm/MC/MCSymbol.h" 37 #include "llvm/Support/TargetRegistry.h" 38 #include "llvm/Support/raw_ostream.h" 39 #include "llvm/Target/Mangler.h" 40 #include "llvm/Target/TargetData.h" 41 #include "llvm/Target/TargetLoweringObjectFile.h" 42 #include "llvm/Target/TargetOptions.h" 43 44 using namespace llvm; 45 46 void MipsAsmPrinter::EmitInstrWithMacroNoAT(const MachineInstr *MI) { 47 MCInst TmpInst; 48 49 MCInstLowering.Lower(MI, TmpInst); 50 OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); 51 if (MipsFI->getEmitNOAT()) 52 OutStreamer.EmitRawText(StringRef("\t.set\tat")); 53 OutStreamer.EmitInstruction(TmpInst); 54 if (MipsFI->getEmitNOAT()) 55 OutStreamer.EmitRawText(StringRef("\t.set\tnoat")); 56 OutStreamer.EmitRawText(StringRef("\t.set\tnomacro")); 57 } 58 59 bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 60 MipsFI = MF.getInfo<MipsFunctionInfo>(); 61 AsmPrinter::runOnMachineFunction(MF); 62 return true; 63 } 64 65 void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { 66 if (MI->isDebugValue()) { 67 SmallString<128> Str; 68 raw_svector_ostream OS(Str); 69 70 PrintDebugValueComment(MI, OS); 71 return; 72 } 73 74 unsigned Opc = MI->getOpcode(); 75 MCInst TmpInst0; 76 SmallVector<MCInst, 4> MCInsts; 77 78 switch (Opc) { 79 case Mips::ULW: 80 case Mips::ULH: 81 case Mips::ULHu: 82 case Mips::USW: 83 case Mips::USH: 84 case Mips::ULW_P8: 85 case Mips::ULH_P8: 86 case Mips::ULHu_P8: 87 case Mips::USW_P8: 88 case Mips::USH_P8: 89 case Mips::ULD: 90 case Mips::ULW64: 91 case Mips::ULH64: 92 case Mips::ULHu64: 93 case Mips::USD: 94 case Mips::USW64: 95 case Mips::USH64: 96 case Mips::ULD_P8: 97 case Mips::ULW64_P8: 98 case Mips::ULH64_P8: 99 case Mips::ULHu64_P8: 100 case Mips::USD_P8: 101 case Mips::USW64_P8: 102 case Mips::USH64_P8: { 103 if (OutStreamer.hasRawTextSupport()) { 104 EmitInstrWithMacroNoAT(MI); 105 return; 106 } 107 108 MCInstLowering.LowerUnalignedLoadStore(MI, MCInsts); 109 for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); I 110 != MCInsts.end(); ++I) 111 OutStreamer.EmitInstruction(*I); 112 113 return; 114 } 115 case Mips::CPRESTORE: { 116 const MachineOperand &MO = MI->getOperand(0); 117 assert(MO.isImm() && "CPRESTORE's operand must be an immediate."); 118 int64_t Offset = MO.getImm(); 119 120 if (OutStreamer.hasRawTextSupport()) { 121 if (!isInt<16>(Offset)) { 122 EmitInstrWithMacroNoAT(MI); 123 return; 124 } 125 } else { 126 MCInstLowering.LowerCPRESTORE(Offset, MCInsts); 127 128 for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); 129 I != MCInsts.end(); ++I) 130 OutStreamer.EmitInstruction(*I); 131 132 return; 133 } 134 135 break; 136 } 137 case Mips::SETGP01: { 138 MCInstLowering.LowerSETGP01(MI, MCInsts); 139 140 for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); 141 I != MCInsts.end(); ++I) 142 OutStreamer.EmitInstruction(*I); 143 144 return; 145 } 146 default: 147 break; 148 } 149 150 MCInstLowering.Lower(MI, TmpInst0); 151 OutStreamer.EmitInstruction(TmpInst0); 152 } 153 154 //===----------------------------------------------------------------------===// 155 // 156 // Mips Asm Directives 157 // 158 // -- Frame directive "frame Stackpointer, Stacksize, RARegister" 159 // Describe the stack frame. 160 // 161 // -- Mask directives "(f)mask bitmask, offset" 162 // Tells the assembler which registers are saved and where. 163 // bitmask - contain a little endian bitset indicating which registers are 164 // saved on function prologue (e.g. with a 0x80000000 mask, the 165 // assembler knows the register 31 (RA) is saved at prologue. 166 // offset - the position before stack pointer subtraction indicating where 167 // the first saved register on prologue is located. (e.g. with a 168 // 169 // Consider the following function prologue: 170 // 171 // .frame $fp,48,$ra 172 // .mask 0xc0000000,-8 173 // addiu $sp, $sp, -48 174 // sw $ra, 40($sp) 175 // sw $fp, 36($sp) 176 // 177 // With a 0xc0000000 mask, the assembler knows the register 31 (RA) and 178 // 30 (FP) are saved at prologue. As the save order on prologue is from 179 // left to right, RA is saved first. A -8 offset means that after the 180 // stack pointer subtration, the first register in the mask (RA) will be 181 // saved at address 48-8=40. 182 // 183 //===----------------------------------------------------------------------===// 184 185 //===----------------------------------------------------------------------===// 186 // Mask directives 187 //===----------------------------------------------------------------------===// 188 189 // Create a bitmask with all callee saved registers for CPU or Floating Point 190 // registers. For CPU registers consider RA, GP and FP for saving if necessary. 191 void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { 192 // CPU and FPU Saved Registers Bitmasks 193 unsigned CPUBitmask = 0, FPUBitmask = 0; 194 int CPUTopSavedRegOff, FPUTopSavedRegOff; 195 196 // Set the CPU and FPU Bitmasks 197 const MachineFrameInfo *MFI = MF->getFrameInfo(); 198 const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); 199 // size of stack area to which FP callee-saved regs are saved. 200 unsigned CPURegSize = Mips::CPURegsRegisterClass->getSize(); 201 unsigned FGR32RegSize = Mips::FGR32RegisterClass->getSize(); 202 unsigned AFGR64RegSize = Mips::AFGR64RegisterClass->getSize(); 203 bool HasAFGR64Reg = false; 204 unsigned CSFPRegsSize = 0; 205 unsigned i, e = CSI.size(); 206 207 // Set FPU Bitmask. 208 for (i = 0; i != e; ++i) { 209 unsigned Reg = CSI[i].getReg(); 210 if (Mips::CPURegsRegisterClass->contains(Reg)) 211 break; 212 213 unsigned RegNum = getMipsRegisterNumbering(Reg); 214 if (Mips::AFGR64RegisterClass->contains(Reg)) { 215 FPUBitmask |= (3 << RegNum); 216 CSFPRegsSize += AFGR64RegSize; 217 HasAFGR64Reg = true; 218 continue; 219 } 220 221 FPUBitmask |= (1 << RegNum); 222 CSFPRegsSize += FGR32RegSize; 223 } 224 225 // Set CPU Bitmask. 226 for (; i != e; ++i) { 227 unsigned Reg = CSI[i].getReg(); 228 unsigned RegNum = getMipsRegisterNumbering(Reg); 229 CPUBitmask |= (1 << RegNum); 230 } 231 232 // FP Regs are saved right below where the virtual frame pointer points to. 233 FPUTopSavedRegOff = FPUBitmask ? 234 (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0; 235 236 // CPU Regs are saved below FP Regs. 237 CPUTopSavedRegOff = CPUBitmask ? -CSFPRegsSize - CPURegSize : 0; 238 239 // Print CPUBitmask 240 O << "\t.mask \t"; printHex32(CPUBitmask, O); 241 O << ',' << CPUTopSavedRegOff << '\n'; 242 243 // Print FPUBitmask 244 O << "\t.fmask\t"; printHex32(FPUBitmask, O); 245 O << "," << FPUTopSavedRegOff << '\n'; 246 } 247 248 // Print a 32 bit hex number with all numbers. 249 void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) { 250 O << "0x"; 251 for (int i = 7; i >= 0; i--) 252 O.write_hex((Value & (0xF << (i*4))) >> (i*4)); 253 } 254 255 //===----------------------------------------------------------------------===// 256 // Frame and Set directives 257 //===----------------------------------------------------------------------===// 258 259 /// Frame Directive 260 void MipsAsmPrinter::emitFrameDirective() { 261 const TargetRegisterInfo &RI = *TM.getRegisterInfo(); 262 263 unsigned stackReg = RI.getFrameRegister(*MF); 264 unsigned returnReg = RI.getRARegister(); 265 unsigned stackSize = MF->getFrameInfo()->getStackSize(); 266 267 if (OutStreamer.hasRawTextSupport()) 268 OutStreamer.EmitRawText("\t.frame\t$" + 269 StringRef(MipsInstPrinter::getRegisterName(stackReg)).lower() + 270 "," + Twine(stackSize) + ",$" + 271 StringRef(MipsInstPrinter::getRegisterName(returnReg)).lower()); 272 } 273 274 /// Emit Set directives. 275 const char *MipsAsmPrinter::getCurrentABIString() const { 276 switch (Subtarget->getTargetABI()) { 277 case MipsSubtarget::O32: return "abi32"; 278 case MipsSubtarget::N32: return "abiN32"; 279 case MipsSubtarget::N64: return "abi64"; 280 case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 281 default: llvm_unreachable("Unknown Mips ABI");; 282 } 283 } 284 285 void MipsAsmPrinter::EmitFunctionEntryLabel() { 286 if (OutStreamer.hasRawTextSupport()) 287 OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); 288 OutStreamer.EmitLabel(CurrentFnSym); 289 } 290 291 /// EmitFunctionBodyStart - Targets can override this to emit stuff before 292 /// the first basic block in the function. 293 void MipsAsmPrinter::EmitFunctionBodyStart() { 294 MCInstLowering.Initialize(Mang, &MF->getContext()); 295 296 emitFrameDirective(); 297 298 bool EmitCPLoad = (MF->getTarget().getRelocationModel() == Reloc::PIC_) && 299 Subtarget->isABI_O32() && MipsFI->globalBaseRegSet() && 300 MipsFI->globalBaseRegFixed(); 301 302 if (OutStreamer.hasRawTextSupport()) { 303 SmallString<128> Str; 304 raw_svector_ostream OS(Str); 305 printSavedRegsBitmask(OS); 306 OutStreamer.EmitRawText(OS.str()); 307 308 OutStreamer.EmitRawText(StringRef("\t.set\tnoreorder")); 309 310 // Emit .cpload directive if needed. 311 if (EmitCPLoad) 312 OutStreamer.EmitRawText(StringRef("\t.cpload\t$25")); 313 314 OutStreamer.EmitRawText(StringRef("\t.set\tnomacro")); 315 if (MipsFI->getEmitNOAT()) 316 OutStreamer.EmitRawText(StringRef("\t.set\tnoat")); 317 } else if (EmitCPLoad) { 318 SmallVector<MCInst, 4> MCInsts; 319 MCInstLowering.LowerCPLOAD(MCInsts); 320 for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); 321 I != MCInsts.end(); ++I) 322 OutStreamer.EmitInstruction(*I); 323 } 324 } 325 326 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after 327 /// the last basic block in the function. 328 void MipsAsmPrinter::EmitFunctionBodyEnd() { 329 // There are instruction for this macros, but they must 330 // always be at the function end, and we can't emit and 331 // break with BB logic. 332 if (OutStreamer.hasRawTextSupport()) { 333 if (MipsFI->getEmitNOAT()) 334 OutStreamer.EmitRawText(StringRef("\t.set\tat")); 335 336 OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); 337 OutStreamer.EmitRawText(StringRef("\t.set\treorder")); 338 OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); 339 } 340 } 341 342 /// isBlockOnlyReachableByFallthough - Return true if the basic block has 343 /// exactly one predecessor and the control transfer mechanism between 344 /// the predecessor and this block is a fall-through. 345 bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* 346 MBB) const { 347 // The predecessor has to be immediately before this block. 348 const MachineBasicBlock *Pred = *MBB->pred_begin(); 349 350 // If the predecessor is a switch statement, assume a jump table 351 // implementation, so it is not a fall through. 352 if (const BasicBlock *bb = Pred->getBasicBlock()) 353 if (isa<SwitchInst>(bb->getTerminator())) 354 return false; 355 356 // If this is a landing pad, it isn't a fall through. If it has no preds, 357 // then nothing falls through to it. 358 if (MBB->isLandingPad() || MBB->pred_empty()) 359 return false; 360 361 // If there isn't exactly one predecessor, it can't be a fall through. 362 MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; 363 ++PI2; 364 365 if (PI2 != MBB->pred_end()) 366 return false; 367 368 // The predecessor has to be immediately before this block. 369 if (!Pred->isLayoutSuccessor(MBB)) 370 return false; 371 372 // If the block is completely empty, then it definitely does fall through. 373 if (Pred->empty()) 374 return true; 375 376 // Otherwise, check the last instruction. 377 // Check if the last terminator is an unconditional branch. 378 MachineBasicBlock::const_iterator I = Pred->end(); 379 while (I != Pred->begin() && !(--I)->isTerminator()) ; 380 381 return !I->isBarrier(); 382 } 383 384 // Print out an operand for an inline asm expression. 385 bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 386 unsigned AsmVariant,const char *ExtraCode, 387 raw_ostream &O) { 388 // Does this asm operand have a single letter operand modifier? 389 if (ExtraCode && ExtraCode[0]) 390 return true; // Unknown modifier. 391 392 printOperand(MI, OpNo, O); 393 return false; 394 } 395 396 bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 397 unsigned OpNum, unsigned AsmVariant, 398 const char *ExtraCode, 399 raw_ostream &O) { 400 if (ExtraCode && ExtraCode[0]) 401 return true; // Unknown modifier. 402 403 const MachineOperand &MO = MI->getOperand(OpNum); 404 assert(MO.isReg() && "unexpected inline asm memory operand"); 405 O << "0($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; 406 return false; 407 } 408 409 void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, 410 raw_ostream &O) { 411 const MachineOperand &MO = MI->getOperand(opNum); 412 bool closeP = false; 413 414 if (MO.getTargetFlags()) 415 closeP = true; 416 417 switch(MO.getTargetFlags()) { 418 case MipsII::MO_GPREL: O << "%gp_rel("; break; 419 case MipsII::MO_GOT_CALL: O << "%call16("; break; 420 case MipsII::MO_GOT: O << "%got("; break; 421 case MipsII::MO_ABS_HI: O << "%hi("; break; 422 case MipsII::MO_ABS_LO: O << "%lo("; break; 423 case MipsII::MO_TLSGD: O << "%tlsgd("; break; 424 case MipsII::MO_GOTTPREL: O << "%gottprel("; break; 425 case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; 426 case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break; 427 case MipsII::MO_GPOFF_HI: O << "%hi(%neg(%gp_rel("; break; 428 case MipsII::MO_GPOFF_LO: O << "%lo(%neg(%gp_rel("; break; 429 case MipsII::MO_GOT_DISP: O << "%got_disp("; break; 430 case MipsII::MO_GOT_PAGE: O << "%got_page("; break; 431 case MipsII::MO_GOT_OFST: O << "%got_ofst("; break; 432 } 433 434 switch (MO.getType()) { 435 case MachineOperand::MO_Register: 436 O << '$' 437 << StringRef(MipsInstPrinter::getRegisterName(MO.getReg())).lower(); 438 break; 439 440 case MachineOperand::MO_Immediate: 441 O << MO.getImm(); 442 break; 443 444 case MachineOperand::MO_MachineBasicBlock: 445 O << *MO.getMBB()->getSymbol(); 446 return; 447 448 case MachineOperand::MO_GlobalAddress: 449 O << *Mang->getSymbol(MO.getGlobal()); 450 break; 451 452 case MachineOperand::MO_BlockAddress: { 453 MCSymbol* BA = GetBlockAddressSymbol(MO.getBlockAddress()); 454 O << BA->getName(); 455 break; 456 } 457 458 case MachineOperand::MO_ExternalSymbol: 459 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 460 break; 461 462 case MachineOperand::MO_JumpTableIndex: 463 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 464 << '_' << MO.getIndex(); 465 break; 466 467 case MachineOperand::MO_ConstantPoolIndex: 468 O << MAI->getPrivateGlobalPrefix() << "CPI" 469 << getFunctionNumber() << "_" << MO.getIndex(); 470 if (MO.getOffset()) 471 O << "+" << MO.getOffset(); 472 break; 473 474 default: 475 llvm_unreachable("<unknown operand type>"); 476 } 477 478 if (closeP) O << ")"; 479 } 480 481 void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, 482 raw_ostream &O) { 483 const MachineOperand &MO = MI->getOperand(opNum); 484 if (MO.isImm()) 485 O << (unsigned short int)MO.getImm(); 486 else 487 printOperand(MI, opNum, O); 488 } 489 490 void MipsAsmPrinter:: 491 printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { 492 // Load/Store memory operands -- imm($reg) 493 // If PIC target the target is loaded as the 494 // pattern lw $25,%call16($28) 495 printOperand(MI, opNum+1, O); 496 O << "("; 497 printOperand(MI, opNum, O); 498 O << ")"; 499 } 500 501 void MipsAsmPrinter:: 502 printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) { 503 // when using stack locations for not load/store instructions 504 // print the same way as all normal 3 operand instructions. 505 printOperand(MI, opNum, O); 506 O << ", "; 507 printOperand(MI, opNum+1, O); 508 return; 509 } 510 511 void MipsAsmPrinter:: 512 printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 513 const char *Modifier) { 514 const MachineOperand& MO = MI->getOperand(opNum); 515 O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); 516 } 517 518 void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { 519 // FIXME: Use SwitchSection. 520 521 // Tell the assembler which ABI we are using 522 if (OutStreamer.hasRawTextSupport()) 523 OutStreamer.EmitRawText("\t.section .mdebug." + 524 Twine(getCurrentABIString())); 525 526 // TODO: handle O64 ABI 527 if (OutStreamer.hasRawTextSupport()) { 528 if (Subtarget->isABI_EABI()) { 529 if (Subtarget->isGP32bit()) 530 OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); 531 else 532 OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); 533 } 534 } 535 536 // return to previous section 537 if (OutStreamer.hasRawTextSupport()) 538 OutStreamer.EmitRawText(StringRef("\t.previous")); 539 } 540 541 MachineLocation 542 MipsAsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { 543 // Handles frame addresses emitted in MipsInstrInfo::emitFrameIndexDebugValue. 544 assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); 545 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() && 546 "Unexpected MachineOperand types"); 547 return MachineLocation(MI->getOperand(0).getReg(), 548 MI->getOperand(1).getImm()); 549 } 550 551 void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, 552 raw_ostream &OS) { 553 // TODO: implement 554 } 555 556 // Force static initialization. 557 extern "C" void LLVMInitializeMipsAsmPrinter() { 558 RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget); 559 RegisterAsmPrinter<MipsAsmPrinter> Y(TheMipselTarget); 560 RegisterAsmPrinter<MipsAsmPrinter> A(TheMips64Target); 561 RegisterAsmPrinter<MipsAsmPrinter> B(TheMips64elTarget); 562 } 563