+//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
+//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
#define DEBUG_TYPE "asm-printer"
#include "ARM.h"
#include "ARMBuildAttrs.h"
-#include "ARMTargetMachine.h"
#include "ARMAddressingModes.h"
#include "ARMConstantPoolValue.h"
+#include "ARMInstPrinter.h"
#include "ARMMachineFunctionInfo.h"
+#include "ARMMCInstLower.h"
+#include "ARMTargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/FormattedStream.h"
#include <cctype>
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
+static cl::opt<bool>
+EnableMCInst("enable-arm-mcinst-printer", cl::Hidden,
+ cl::desc("enable experimental asmprinter gunk in the arm backend"));
+
namespace {
- class VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
- DwarfWriter *DW;
+ class ARMAsmPrinter : public AsmPrinter {
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
/// make the right decision when printing asm code for different targets.
/// MachineFunction.
const MachineConstantPool *MCP;
- /// We name each basic block in a Function with a unique number, so
- /// that we can consistently refer to them later. This is cleared
- /// at the beginning of each call to runOnMachineFunction().
- ///
- typedef std::map<const Value *, unsigned> ValueMapTy;
- ValueMapTy NumberForBB;
-
- /// GVNonLazyPtrs - Keeps the set of GlobalValues that require
- /// non-lazy-pointers for indirect access.
- StringMap<std::string> GVNonLazyPtrs;
-
- /// HiddenGVNonLazyPtrs - Keeps the set of GlobalValues with hidden
- /// visibility that require non-lazy-pointers for indirect access.
- StringMap<std::string> HiddenGVNonLazyPtrs;
-
- /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
- bool InCPMode;
public:
explicit ARMAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
const MCAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V), DW(0), AFI(NULL), MCP(NULL),
- InCPMode(false) {
+ : AsmPrinter(O, TM, T, V), AFI(NULL), MCP(NULL) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
}
virtual const char *getPassName() const {
return "ARM Assembly Printer";
}
+
+ void printMCInst(const MCInst *MI) {
+ ARMInstPrinter(O, *MAI).printInstruction(MI);
+ }
+
+ void printInstructionThroughMCStreamer(const MachineInstr *MI);
+
void printOperand(const MachineInstr *MI, int OpNum,
const char *Modifier = 0);
void PrintGlobalVariable(const GlobalVariable* GVar);
void printInstruction(const MachineInstr *MI); // autogenerated.
+ static const char *getRegisterName(unsigned RegNo);
+
void printMachineInstruction(const MachineInstr *MI);
bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
+ void EmitStartOfAsmFile(Module &M);
+ void EmitEndOfAsmFile(Module &M);
/// EmitMachineConstantPoolValue - Print a machine constantpool value to
/// the .s file.
Name = Mang->getMangledName(GV);
else {
// FIXME: Remove this when Darwin transition to @GOT like syntax.
- std::string SymName = Mang->getMangledName(GV);
Name = Mang->getMangledName(GV, "$non_lazy_ptr", true);
- if (GV->hasHiddenVisibility())
- HiddenGVNonLazyPtrs[SymName] = Name;
- else
- GVNonLazyPtrs[SymName] = Name;
+ MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name.c_str());
+
+ MachineModuleInfoMachO &MMIMachO =
+ MMI->getObjFileInfo<MachineModuleInfoMachO>();
+ const MCSymbol *&StubSym =
+ GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
+ MMIMachO.getGVStubEntry(Sym);
+ if (StubSym == 0) {
+ SmallString<128> NameStr;
+ Mang->getNameWithPrefix(NameStr, GV, false);
+ StubSym = OutContext.GetOrCreateSymbol(NameStr.str());
+ }
}
} else
Name = Mang->makeNameProper(ACPV->getSymbol());
printVisibility(CurrentFnName, F->getVisibility());
+ unsigned FnAlign = 1 << MF.getAlignment(); // MF alignment is log2.
if (AFI->isThumbFunction()) {
- EmitAlignment(MF.getAlignment(), F, AFI->getAlign());
+ EmitAlignment(FnAlign, F, AFI->getAlign());
O << "\t.code\t16\n";
O << "\t.thumb_func";
if (Subtarget->isTargetDarwin())
O << "\t" << CurrentFnName;
O << "\n";
- InCPMode = false;
} else {
- EmitAlignment(MF.getAlignment(), F);
+ EmitAlignment(FnAlign, F);
}
O << CurrentFnName << ":\n";
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
- if (I != MF.begin()) {
- printBasicBlockLabel(I, true, true, VerboseAsm);
- O << '\n';
- }
+ if (I != MF.begin())
+ EmitBasicBlockStart(I);
+
+ // Print the assembly for the instruction.
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
- // Print the assembly for the instruction.
+ II != E; ++II)
printMachineInstruction(II);
- }
}
if (MAI->hasDotTypeDotSizeDirective())
const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNum);
switch (MO.getType()) {
+ default:
+ assert(0 && "<unknown operand type>");
case MachineOperand::MO_Register: {
unsigned Reg = MO.getReg();
- if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
- if (Modifier && strcmp(Modifier, "dregpair") == 0) {
- unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0
- unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1
- O << '{'
- << TRI->getAsmName(DRegLo) << ',' << TRI->getAsmName(DRegHi)
- << '}';
- } else if (Modifier && strcmp(Modifier, "lane") == 0) {
- unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
- unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 0 : 1,
- &ARM::DPRRegClass);
- O << TRI->getAsmName(DReg) << '[' << (RegNum & 1) << ']';
- } else {
- O << TRI->getAsmName(Reg);
- }
- } else
- llvm_unreachable("not implemented");
+ assert(TargetRegisterInfo::isPhysicalRegister(Reg));
+ if (Modifier && strcmp(Modifier, "dregpair") == 0) {
+ unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0
+ unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1
+ O << '{'
+ << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
+ << '}';
+ } else if (Modifier && strcmp(Modifier, "lane") == 0) {
+ unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
+ unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1,
+ &ARM::DPR_VFP2RegClass);
+ O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
+ } else {
+ O << getRegisterName(Reg);
+ }
break;
}
case MachineOperand::MO_Immediate: {
- O << '#' << MO.getImm();
+ int64_t Imm = MO.getImm();
+ O << '#';
+ if (Modifier) {
+ if (strcmp(Modifier, "lo16") == 0)
+ O << ":lower16:";
+ else if (strcmp(Modifier, "hi16") == 0)
+ O << ":upper16:";
+ }
+ O << Imm;
break;
}
case MachineOperand::MO_MachineBasicBlock:
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << MO.getIndex();
break;
- default:
- O << "<unknown operand type>"; abort (); break;
}
}
const MachineOperand &MO2 = MI->getOperand(Op+1);
const MachineOperand &MO3 = MI->getOperand(Op+2);
- assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
- O << TRI->getAsmName(MO1.getReg());
+ O << getRegisterName(MO1.getReg());
// Print the shift opc.
O << ", "
<< " ";
if (MO2.getReg()) {
- assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
- O << TRI->getAsmName(MO2.getReg());
+ O << getRegisterName(MO2.getReg());
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
} else {
O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
return;
}
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
if (!MO2.getReg()) {
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
O << ", "
<< (char)ARM_AM::getAM2Op(MO3.getImm())
- << TRI->getAsmName(MO2.getReg());
+ << getRegisterName(MO2.getReg());
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
O << ", "
}
O << (char)ARM_AM::getAM2Op(MO2.getImm())
- << TRI->getAsmName(MO1.getReg());
+ << getRegisterName(MO1.getReg());
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
O << ", "
const MachineOperand &MO3 = MI->getOperand(Op+2);
assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
if (MO2.getReg()) {
O << ", "
<< (char)ARM_AM::getAM3Op(MO3.getImm())
- << TRI->getAsmName(MO2.getReg())
+ << getRegisterName(MO2.getReg())
<< "]";
return;
}
if (MO1.getReg()) {
O << (char)ARM_AM::getAM3Op(MO2.getImm())
- << TRI->getAsmName(MO1.getReg());
+ << getRegisterName(MO1.getReg());
return;
}
return;
} else if (Modifier && strcmp(Modifier, "base") == 0) {
// Used for FSTM{D|S} and LSTM{D|S} operations.
- O << TRI->getAsmName(MO1.getReg());
+ O << getRegisterName(MO1.getReg());
if (ARM_AM::getAM5WBFlag(MO2.getImm()))
O << "!";
return;
}
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
O << ", #"
const MachineOperand &MO3 = MI->getOperand(Op+2);
// FIXME: No support yet for specifying alignment.
- O << "[" << TRI->getAsmName(MO1.getReg()) << "]";
+ O << "[" << getRegisterName(MO1.getReg()) << "]";
if (ARM_AM::getAM6WBFlag(MO3.getImm())) {
if (MO2.getReg() == 0)
O << "!";
else
- O << ", " << TRI->getAsmName(MO2.getReg());
+ O << ", " << getRegisterName(MO2.getReg());
}
}
const MachineOperand &MO1 = MI->getOperand(Op);
assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
- O << "[pc, +" << TRI->getAsmName(MO1.getReg()) << "]";
+ O << "[pc, +" << getRegisterName(MO1.getReg()) << "]";
}
void
ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
const MachineOperand &MO1 = MI->getOperand(Op);
const MachineOperand &MO2 = MI->getOperand(Op+1);
- O << "[" << TRI->getAsmName(MO1.getReg());
- O << ", " << TRI->getAsmName(MO2.getReg()) << "]";
+ O << "[" << getRegisterName(MO1.getReg());
+ O << ", " << getRegisterName(MO2.getReg()) << "]";
}
void
return;
}
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
if (MO3.getReg())
- O << ", " << TRI->getAsmName(MO3.getReg());
+ O << ", " << getRegisterName(MO3.getReg());
else if (unsigned ImmOffs = MO2.getImm()) {
O << ", #" << ImmOffs;
if (Scale > 1)
void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
const MachineOperand &MO1 = MI->getOperand(Op);
const MachineOperand &MO2 = MI->getOperand(Op+1);
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
if (unsigned ImmOffs = MO2.getImm())
O << ", #" << ImmOffs << " * 4";
O << "]";
unsigned Reg = MO1.getReg();
assert(TargetRegisterInfo::isPhysicalRegister(Reg));
- O << TRI->getAsmName(Reg);
+ O << getRegisterName(Reg);
// Print the shift opc.
O << ", "
const MachineOperand &MO1 = MI->getOperand(OpNum);
const MachineOperand &MO2 = MI->getOperand(OpNum+1);
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
unsigned OffImm = MO2.getImm();
if (OffImm) // Don't print +0.
const MachineOperand &MO1 = MI->getOperand(OpNum);
const MachineOperand &MO2 = MI->getOperand(OpNum+1);
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
int32_t OffImm = (int32_t)MO2.getImm();
// Don't print +0.
const MachineOperand &MO1 = MI->getOperand(OpNum);
const MachineOperand &MO2 = MI->getOperand(OpNum+1);
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
int32_t OffImm = (int32_t)MO2.getImm() / 4;
// Don't print +0.
const MachineOperand &MO2 = MI->getOperand(OpNum+1);
const MachineOperand &MO3 = MI->getOperand(OpNum+2);
- O << "[" << TRI->getAsmName(MO1.getReg());
+ O << "[" << getRegisterName(MO1.getReg());
assert(MO2.getReg() && "Invalid so_reg load / store address!");
- O << ", " << TRI->getAsmName(MO2.getReg());
+ O << ", " << getRegisterName(MO2.getReg());
unsigned ShAmt = MO3.getImm();
if (ShAmt) {
void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) {
O << "{";
- for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
+ // Always skip the first operand, it's the optional (and implicit writeback).
+ for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
if (MI->getOperand(i).isImplicit())
continue;
- if ((int)i != OpNum) O << ", ";
+ if ((int)i != OpNum+1) O << ", ";
printOperand(MI, i);
}
O << "}";
}
void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum) {
- O << "[pc, " << TRI->getAsmName(MI->getOperand(OpNum).getReg());
+ O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
if (MI->getOpcode() == ARM::t2TBH)
O << ", lsl #1";
O << ']';
default: return true; // Unknown modifier.
case 'a': // Print as a memory address.
if (MI->getOperand(OpNum).isReg()) {
- O << "[" << TRI->getAsmName(MI->getOperand(OpNum).getReg()) << "]";
+ O << "[" << getRegisterName(MI->getOperand(OpNum).getReg()) << "]";
return false;
}
// Fallthrough
const char *ExtraCode) {
if (ExtraCode && ExtraCode[0])
return true; // Unknown modifier.
- printAddrMode2Operand(MI, OpNum);
+
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ assert(MO.isReg() && "unexpected inline asm memory operand");
+ O << "[" << getRegisterName(MO.getReg()) << "]";
return false;
}
++EmittedInsts;
int Opc = MI->getOpcode();
- switch (Opc) {
- case ARM::CONSTPOOL_ENTRY:
- if (!InCPMode && AFI->isThumbFunction()) {
- EmitAlignment(2);
- InCPMode = true;
- }
- break;
- default: {
- if (InCPMode && AFI->isThumbFunction())
- InCPMode = false;
- }}
+ if (Opc == ARM::CONSTPOOL_ENTRY)
+ EmitAlignment(2);
// Call the autogenerated instruction printer routines.
- processDebugLoc(MI->getDebugLoc());
- printInstruction(MI);
+ processDebugLoc(MI, true);
+
+ if (EnableMCInst) {
+ printInstructionThroughMCStreamer(MI);
+ } else {
+ printInstruction(MI);
+ }
+
if (VerboseAsm && !MI->getDebugLoc().isUnknown())
EmitComments(*MI);
O << '\n';
+ processDebugLoc(MI, false);
}
-bool ARMAsmPrinter::doInitialization(Module &M) {
-
- bool Result = AsmPrinter::doInitialization(M);
- DW = getAnalysisIfAvailable<DwarfWriter>();
+void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
+ if (Subtarget->isTargetDarwin()) {
+ Reloc::Model RelocM = TM.getRelocationModel();
+ if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
+ // Declare all the text sections up front (before the DWARF sections
+ // emitted by AsmPrinter::doInitialization) so the assembler will keep
+ // them together at the beginning of the object file. This helps
+ // avoid out-of-range branches that are due a fundamental limitation of
+ // the way symbol offsets are encoded with the current Darwin ARM
+ // relocations.
+ TargetLoweringObjectFileMachO &TLOFMacho =
+ static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
+ OutStreamer.SwitchSection(TLOFMacho.getTextSection());
+ OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
+ OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
+ if (RelocM == Reloc::DynamicNoPIC) {
+ const MCSection *sect =
+ TLOFMacho.getMachOSection("__TEXT", "__symbol_stub4",
+ MCSectionMachO::S_SYMBOL_STUBS,
+ 12, SectionKind::getText());
+ OutStreamer.SwitchSection(sect);
+ } else {
+ const MCSection *sect =
+ TLOFMacho.getMachOSection("__TEXT", "__picsymbolstub4",
+ MCSectionMachO::S_SYMBOL_STUBS,
+ 16, SectionKind::getText());
+ OutStreamer.SwitchSection(sect);
+ }
+ }
+ }
// Use unified assembler syntax mode for Thumb.
if (Subtarget->isThumb())
// FIXME: Should we signal R9 usage?
}
-
- return Result;
}
void ARMAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
}
-bool ARMAsmPrinter::doFinalization(Module &M) {
+void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
if (Subtarget->isTargetDarwin()) {
// All darwin targets use mach-o.
TargetLoweringObjectFileMachO &TLOFMacho =
static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
+ MachineModuleInfoMachO &MMIMacho =
+ MMI->getObjFileInfo<MachineModuleInfoMachO>();
O << '\n';
// Output non-lazy-pointers for external and common global variables.
- if (!GVNonLazyPtrs.empty()) {
+ MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
+
+ if (!Stubs.empty()) {
// Switch with ".non_lazy_symbol_pointer" directive.
OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
EmitAlignment(2);
- for (StringMap<std::string>::iterator I = GVNonLazyPtrs.begin(),
- E = GVNonLazyPtrs.end(); I != E; ++I) {
- O << I->second << ":\n";
- O << "\t.indirect_symbol " << I->getKeyData() << "\n";
- O << "\t.long\t0\n";
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
+ Stubs[i].first->print(O, MAI);
+ O << ":\n\t.indirect_symbol ";
+ Stubs[i].second->print(O, MAI);
+ O << "\n\t.long\t0\n";
}
}
- if (!HiddenGVNonLazyPtrs.empty()) {
+ Stubs = MMIMacho.GetHiddenGVStubList();
+ if (!Stubs.empty()) {
OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
EmitAlignment(2);
- for (StringMap<std::string>::iterator I = HiddenGVNonLazyPtrs.begin(),
- E = HiddenGVNonLazyPtrs.end(); I != E; ++I) {
- O << I->second << ":\n";
- O << "\t.long " << I->getKeyData() << "\n";
+ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
+ Stubs[i].first->print(O, MAI);
+ O << ":\n\t.long ";
+ Stubs[i].second->print(O, MAI);
+ O << "\n";
}
}
// implementation of multiple entry points). If this doesn't occur, the
// linker can safely perform dead code stripping. Since LLVM never
// generates code that does this, it is always safe to set.
- O << "\t.subsections_via_symbols\n";
+ OutStreamer.EmitAssemblerFlag(MCStreamer::SubsectionsViaSymbols);
}
-
- return AsmPrinter::doFinalization(M);
}
// Force static initialization.
RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget);
RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget);
}
+
+
+//===----------------------------------------------------------------------===//
+
+void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) {
+ ARMMCInstLower MCInstLowering(OutContext, Mang);
+ switch (MI->getOpcode()) {
+ case TargetInstrInfo::DBG_LABEL:
+ case TargetInstrInfo::EH_LABEL:
+ case TargetInstrInfo::GC_LABEL:
+ printLabel(MI);
+ return;
+ case TargetInstrInfo::KILL:
+ return;
+ case TargetInstrInfo::INLINEASM:
+ O << '\t';
+ printInlineAsm(MI);
+ return;
+ case TargetInstrInfo::IMPLICIT_DEF:
+ printImplicitDef(MI);
+ return;
+ default: break;
+ }
+
+ MCInst TmpInst;
+ MCInstLowering.Lower(MI, TmpInst);
+
+ printMCInst(&TmpInst);
+}