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