X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsAsmPrinter.cpp;h=a5ac2ab8bc485e65671a1b6928f67f30ffa24964;hb=4396f5d9d2c215988f9368e94bfd5e1eb1cced58;hp=a44d97ff8d166511c121147cda8e704161d68287;hpb=590853667345d6fb191764b9d0bd2ff13589e3a3;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index a44d97ff8d1..a5ac2ab8bc4 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -1,4 +1,4 @@ -//===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===// +//===-- MipsAsmPrinter.cpp - Mips LLVM Assembly Printer -------------------===// // // The LLVM Compiler Infrastructure // @@ -13,69 +13,126 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mips-asm-printer" -#include "MipsAsmPrinter.h" +#include "InstPrinter/MipsInstPrinter.h" +#include "MCTargetDesc/MipsBaseInfo.h" #include "Mips.h" +#include "MipsAsmPrinter.h" #include "MipsInstrInfo.h" -#include "MipsMachineFunction.h" #include "MipsMCInstLower.h" -#include "MipsMCSymbolRefExpr.h" -#include "InstPrinter/MipsInstPrinter.h" -#include "llvm/BasicBlock.h" -#include "llvm/Instructions.h" -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "MipsTargetStreamer.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/MC/MCStreamer.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Mangler.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/Twine.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetOptions.h" using namespace llvm; -static bool isUnalignedLoadStore(unsigned Opc) { - return Opc == Mips::ULW || Opc == Mips::ULH || Opc == Mips::ULHu || - Opc == Mips::USW || Opc == Mips::USH || - Opc == Mips::ULW_P8 || Opc == Mips::ULH_P8 || Opc == Mips::ULHu_P8 || - Opc == Mips::USW_P8 || Opc == Mips::USH_P8; +MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() { + return static_cast(*OutStreamer.getTargetStreamer()); } -void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); +bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + // Initialize TargetLoweringObjectFile. + if (Subtarget->allowMixed16_32()) + const_cast(getObjFileLowering()) + .Initialize(OutContext, TM); + MipsFI = MF.getInfo(); + MCP = MF.getConstantPool(); + AsmPrinter::runOnMachineFunction(MF); + return true; +} + +bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) { + MCOp = MCInstLowering.LowerOperand(MO); + return MCOp.isValid(); +} + +#include "MipsGenMCPseudoLowering.inc" +void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { if (MI->isDebugValue()) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + PrintDebugValueComment(MI, OS); return; } - MipsMCInstLower MCInstLowering(Mang, *MF, *this); - unsigned Opc = MI->getOpcode(); - MCInst TmpInst0; - MCInstLowering.Lower(MI, TmpInst0); - - // Enclose unaligned load or store with .macro & .nomacro directives. - if (isUnalignedLoadStore(Opc)) { - MCInst Directive; - Directive.setOpcode(Mips::MACRO); - OutStreamer.EmitInstruction(Directive); - OutStreamer.EmitInstruction(TmpInst0); - Directive.setOpcode(Mips::NOMACRO); - OutStreamer.EmitInstruction(Directive); + // If we just ended a constant pool, mark it as such. + if (InConstantPool && MI->getOpcode() != Mips::CONSTPOOL_ENTRY) { + OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); + InConstantPool = false; + } + if (MI->getOpcode() == Mips::CONSTPOOL_ENTRY) { + // CONSTPOOL_ENTRY - This instruction represents a floating + //constant pool in the function. The first operand is the ID# + // for this instruction, the second is the index into the + // MachineConstantPool that this is, the third is the size in + // bytes of this constant pool entry. + // The required alignment is specified on the basic block holding this MI. + // + unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); + unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); + + // If this is the first entry of the pool, mark it. + if (!InConstantPool) { + OutStreamer.EmitDataRegion(MCDR_DataRegion); + InConstantPool = true; + } + + OutStreamer.EmitLabel(GetCPISymbol(LabelId)); + + const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; + if (MCPE.isMachineConstantPoolEntry()) + EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); + else + EmitGlobalConstant(MCPE.Val.ConstVal); return; } - OutStreamer.EmitInstruction(TmpInst0); + + MachineBasicBlock::const_instr_iterator I = MI; + MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); + + do { + // Do any auto-generated pseudo lowerings. + if (emitPseudoExpansionLowering(OutStreamer, &*I)) + continue; + + // The inMips16Mode() test is not permanent. + // Some instructions are marked as pseudo right now which + // would make the test fail for the wrong reason but + // that will be fixed soon. We need this here because we are + // removing another test for this situation downstream in the + // callchain. + // + if (I->isPseudo() && !Subtarget->inMips16Mode()) + llvm_unreachable("Pseudo opcode found in EmitInstruction()"); + + MCInst TmpInst0; + MCInstLowering.Lower(I, TmpInst0); + EmitToStreamer(OutStreamer, TmpInst0); + } while ((++I != E) && I->isInsideBundle()); // Delay slot check } //===----------------------------------------------------------------------===// @@ -115,7 +172,7 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { // Create a bitmask with all callee saved registers for CPU or Floating Point // registers. For CPU registers consider RA, GP and FP for saving if necessary. -void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { +void MipsAsmPrinter::printSavedRegsBitmask() { // CPU and FPU Saved Registers Bitmasks unsigned CPUBitmask = 0, FPUBitmask = 0; int CPUTopSavedRegOff, FPUTopSavedRegOff; @@ -124,9 +181,9 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { const MachineFrameInfo *MFI = MF->getFrameInfo(); const std::vector &CSI = MFI->getCalleeSavedInfo(); // size of stack area to which FP callee-saved regs are saved. - unsigned CPURegSize = Mips::CPURegsRegisterClass->getSize(); - unsigned FGR32RegSize = Mips::FGR32RegisterClass->getSize(); - unsigned AFGR64RegSize = Mips::AFGR64RegisterClass->getSize(); + unsigned CPURegSize = Mips::GPR32RegClass.getSize(); + unsigned FGR32RegSize = Mips::FGR32RegClass.getSize(); + unsigned AFGR64RegSize = Mips::AFGR64RegClass.getSize(); bool HasAFGR64Reg = false; unsigned CSFPRegsSize = 0; unsigned i, e = CSI.size(); @@ -134,11 +191,11 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { // Set FPU Bitmask. for (i = 0; i != e; ++i) { unsigned Reg = CSI[i].getReg(); - if (Mips::CPURegsRegisterClass->contains(Reg)) + if (Mips::GPR32RegClass.contains(Reg)) break; - unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(Reg); - if (Mips::AFGR64RegisterClass->contains(Reg)) { + unsigned RegNum = TM.getRegisterInfo()->getEncodingValue(Reg); + if (Mips::AFGR64RegClass.contains(Reg)) { FPUBitmask |= (3 << RegNum); CSFPRegsSize += AFGR64RegSize; HasAFGR64Reg = true; @@ -152,7 +209,7 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { // Set CPU Bitmask. for (; i != e; ++i) { unsigned Reg = CSI[i].getReg(); - unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(Reg); + unsigned RegNum = TM.getRegisterInfo()->getEncodingValue(Reg); CPUBitmask |= (1 << RegNum); } @@ -163,20 +220,12 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { // CPU Regs are saved below FP Regs. CPUTopSavedRegOff = CPUBitmask ? -CSFPRegsSize - CPURegSize : 0; + MipsTargetStreamer &TS = getTargetStreamer(); // Print CPUBitmask - O << "\t.mask \t"; printHex32(CPUBitmask, O); - O << ',' << CPUTopSavedRegOff << '\n'; + TS.emitMask(CPUBitmask, CPUTopSavedRegOff); // Print FPUBitmask - O << "\t.fmask\t"; printHex32(FPUBitmask, O); - O << "," << FPUTopSavedRegOff << '\n'; -} - -// Print a 32 bit hex number with all numbers. -void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) { - O << "0x"; - for (int i = 7; i >= 0; i--) - O.write_hex((Value & (0xF << (i*4))) >> (i*4)); + TS.emitFMask(FPUBitmask, FPUTopSavedRegOff); } //===----------------------------------------------------------------------===// @@ -191,10 +240,7 @@ void MipsAsmPrinter::emitFrameDirective() { unsigned returnReg = RI.getRARegister(); unsigned stackSize = MF->getFrameInfo()->getStackSize(); - OutStreamer.EmitRawText("\t.frame\t$" + - StringRef(MipsInstPrinter::getRegisterName(stackReg)).lower() + - "," + Twine(stackSize) + ",$" + - StringRef(MipsInstPrinter::getRegisterName(returnReg)).lower()); + getTargetStreamer().emitFrame(stackReg, stackSize, returnReg); } /// Emit Set directives. @@ -204,41 +250,73 @@ const char *MipsAsmPrinter::getCurrentABIString() const { case MipsSubtarget::N32: return "abiN32"; case MipsSubtarget::N64: return "abi64"; case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 - default: break; + default: llvm_unreachable("Unknown Mips ABI"); } - - llvm_unreachable("Unknown Mips ABI"); - return NULL; } void MipsAsmPrinter::EmitFunctionEntryLabel() { - OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); + MipsTargetStreamer &TS = getTargetStreamer(); + if (Subtarget->inMicroMipsMode()) + TS.emitDirectiveSetMicroMips(); + // leave out until FSF available gas has micromips changes + // else + // TS.emitDirectiveSetNoMicroMips(); + + if (Subtarget->inMips16Mode()) + TS.emitDirectiveSetMips16(); + else + TS.emitDirectiveSetNoMips16(); + + TS.emitDirectiveEnt(*CurrentFnSym); OutStreamer.EmitLabel(CurrentFnSym); } /// EmitFunctionBodyStart - Targets can override this to emit stuff before /// the first basic block in the function. void MipsAsmPrinter::EmitFunctionBodyStart() { - emitFrameDirective(); + MipsTargetStreamer &TS = getTargetStreamer(); + + MCInstLowering.Initialize(&MF->getContext()); + + bool IsNakedFunction = + MF->getFunction()-> + getAttributes().hasAttribute(AttributeSet::FunctionIndex, + Attribute::Naked); + if (!IsNakedFunction) + emitFrameDirective(); + + if (!IsNakedFunction) + printSavedRegsBitmask(); - SmallString<128> Str; - raw_svector_ostream OS(Str); - printSavedRegsBitmask(OS); - OutStreamer.EmitRawText(OS.str()); + if (!Subtarget->inMips16Mode()) { + TS.emitDirectiveSetNoReorder(); + TS.emitDirectiveSetNoMacro(); + TS.emitDirectiveSetNoAt(); + } } /// EmitFunctionBodyEnd - Targets can override this to emit stuff after /// the last basic block in the function. void MipsAsmPrinter::EmitFunctionBodyEnd() { + MipsTargetStreamer &TS = getTargetStreamer(); + // There are instruction for this macros, but they must // always be at the function end, and we can't emit and // break with BB logic. - OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); - OutStreamer.EmitRawText(StringRef("\t.set\treorder")); - OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); + if (!Subtarget->inMips16Mode()) { + TS.emitDirectiveSetAt(); + TS.emitDirectiveSetMacro(); + TS.emitDirectiveSetReorder(); + } + TS.emitDirectiveEnd(CurrentFnSym->getName()); + // Make sure to terminate any constant pools that were at the end + // of the function. + if (!InConstantPool) + return; + InConstantPool = false; + OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); } - /// isBlockOnlyReachableByFallthough - Return true if the basic block has /// exactly one predecessor and the control transfer mechanism between /// the predecessor and this block is a fall-through. @@ -261,35 +339,125 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* // If there isn't exactly one predecessor, it can't be a fall through. MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; ++PI2; - + if (PI2 != MBB->pred_end()) - return false; + return false; // The predecessor has to be immediately before this block. if (!Pred->isLayoutSuccessor(MBB)) return false; - + // If the block is completely empty, then it definitely does fall through. if (Pred->empty()) return true; - + // Otherwise, check the last instruction. // Check if the last terminator is an unconditional branch. MachineBasicBlock::const_iterator I = Pred->end(); - while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) ; + while (I != Pred->begin() && !(--I)->isTerminator()) ; - return !I->getDesc().isBarrier(); + return !I->isBarrier(); } // Print out an operand for an inline asm expression. -bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, +bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + const MachineOperand &MO = MI->getOperand(OpNum); + switch (ExtraCode[0]) { + default: + // See if this is a generic print operand + return AsmPrinter::PrintAsmOperand(MI,OpNum,AsmVariant,ExtraCode,O); + case 'X': // hex const int + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + O << "0x" << StringRef(utohexstr(MO.getImm())).lower(); + return false; + case 'x': // hex const int (low 16 bits) + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + O << "0x" << StringRef(utohexstr(MO.getImm() & 0xffff)).lower(); + return false; + case 'd': // decimal const int + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + O << MO.getImm(); + return false; + case 'm': // decimal const int minus 1 + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + O << MO.getImm() - 1; + return false; + case 'z': { + // $0 if zero, regular printing otherwise + if (MO.getType() != MachineOperand::MO_Immediate) + return true; + int64_t Val = MO.getImm(); + if (Val) + O << Val; + else + O << "$0"; + return false; + } + case 'D': // Second part of a double word register operand + case 'L': // Low order register of a double word register operand + case 'M': // High order register of a double word register operand + { + if (OpNum == 0) + return true; + const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); + if (!FlagsOP.isImm()) + return true; + unsigned Flags = FlagsOP.getImm(); + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + // Number of registers represented by this operand. We are looking + // for 2 for 32 bit mode and 1 for 64 bit mode. + if (NumVals != 2) { + if (Subtarget->isGP64bit() && NumVals == 1 && MO.isReg()) { + unsigned Reg = MO.getReg(); + O << '$' << MipsInstPrinter::getRegisterName(Reg); + return false; + } + return true; + } + + unsigned RegOp = OpNum; + if (!Subtarget->isGP64bit()){ + // Endianess reverses which register holds the high or low value + // between M and L. + switch(ExtraCode[0]) { + case 'M': + RegOp = (Subtarget->isLittle()) ? OpNum + 1 : OpNum; + break; + case 'L': + RegOp = (Subtarget->isLittle()) ? OpNum : OpNum + 1; + break; + case 'D': // Always the second part + RegOp = OpNum + 1; + } + if (RegOp >= MI->getNumOperands()) + return true; + const MachineOperand &MO = MI->getOperand(RegOp); + if (!MO.isReg()) + return true; + unsigned Reg = MO.getReg(); + O << '$' << MipsInstPrinter::getRegisterName(Reg); + return false; + } + } + case 'w': + // Print MSA registers for the 'f' constraint + // In LLVM, the 'w' modifier doesn't need to do anything. + // We can just call printOperand as normal. + break; + } + } - printOperand(MI, OpNo, O); + printOperand(MI, OpNum, O); return false; } @@ -297,17 +465,25 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. - + int Offset = 0; + // Currently we are expecting either no ExtraCode or 'D' + if (ExtraCode) { + if (ExtraCode[0] == 'D') + Offset = 4; + else + return true; // Unknown modifier. + } + const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isReg() && "unexpected inline asm memory operand"); - O << "0($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; + O << Offset << "($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; + return false; } void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { + const DataLayout *DL = TM.getDataLayout(); const MachineOperand &MO = MI->getOperand(opNum); bool closeP = false; @@ -346,26 +522,17 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, return; case MachineOperand::MO_GlobalAddress: - O << *Mang->getSymbol(MO.getGlobal()); + O << *getSymbol(MO.getGlobal()); break; case MachineOperand::MO_BlockAddress: { - MCSymbol* BA = GetBlockAddressSymbol(MO.getBlockAddress()); + MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); O << BA->getName(); break; } - case MachineOperand::MO_ExternalSymbol: - O << *GetExternalSymbolSymbol(MO.getSymbolName()); - break; - - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - break; - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" + O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" << MO.getIndex(); if (MO.getOffset()) O << "+" << MO.getOffset(); @@ -387,6 +554,15 @@ void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, printOperand(MI, opNum, O); } +void MipsAsmPrinter::printUnsignedImm8(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.isImm()) + O << (unsigned short int)(unsigned char)MO.getImm(); + else + printOperand(MI, opNum, O); +} + void MipsAsmPrinter:: printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { // Load/Store memory operands -- imm($reg) @@ -411,36 +587,44 @@ printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) { void MipsAsmPrinter:: printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier) { - const MachineOperand& MO = MI->getOperand(opNum); + const MachineOperand &MO = MI->getOperand(opNum); O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); } void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { - // FIXME: Use SwitchSection. + // TODO: Need to add -mabicalls and -mno-abicalls flags. + // Currently we assume that -mabicalls is the default. + getTargetStreamer().emitDirectiveAbiCalls(); + Reloc::Model RM = Subtarget->getRelocationModel(); + if (RM == Reloc::Static && !Subtarget->hasMips64()) + getTargetStreamer().emitDirectiveOptionPic0(); // Tell the assembler which ABI we are using - OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); + std::string SectionName = std::string(".mdebug.") + getCurrentABIString(); + OutStreamer.SwitchSection(OutContext.getELFSection( + SectionName, ELF::SHT_PROGBITS, 0, SectionKind::getDataRel())); // TODO: handle O64 ABI + if (Subtarget->isABI_EABI()) { if (Subtarget->isGP32bit()) - OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); + OutStreamer.SwitchSection( + OutContext.getELFSection(".gcc_compiled_long32", ELF::SHT_PROGBITS, 0, + SectionKind::getDataRel())); else - OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); + OutStreamer.SwitchSection( + OutContext.getELFSection(".gcc_compiled_long64", ELF::SHT_PROGBITS, 0, + SectionKind::getDataRel())); } - // return to previous section - OutStreamer.EmitRawText(StringRef("\t.previous")); + // return to the text section + OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); } -MachineLocation -MipsAsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { - // Handles frame addresses emitted in MipsInstrInfo::emitFrameIndexDebugValue. - assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); - assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() && - "Unexpected MachineOperand types"); - return MachineLocation(MI->getOperand(0).getReg(), - MI->getOperand(1).getImm()); +void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { + // Emit Mips ELF register info + Subtarget->getMReginfo().emitMipsReginfoSectionCG( + OutStreamer, getObjFileLowering(), *Subtarget); } void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,