Home | History | Annotate | Download | only in Mips
      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