LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

X86AsmPrinter.cpp

Go to the documentation of this file.
00001 //===-- X86AsmPrinter.cpp - Convert X86 LLVM code to Intel assembly -------===//
00002 // 
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 // 
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains a printer that converts from our internal representation
00011 // of machine-dependent LLVM code to Intel and AT&T format assembly
00012 // language. This printer is the output mechanism used by `llc' and `lli
00013 // -print-machineinstrs' on X86.
00014 //
00015 //===----------------------------------------------------------------------===//
00016 
00017 #include "X86.h"
00018 #include "X86TargetMachine.h"
00019 #include "llvm/Module.h"
00020 #include "llvm/Assembly/Writer.h"
00021 #include "llvm/CodeGen/AsmPrinter.h"
00022 #include "llvm/CodeGen/MachineConstantPool.h"
00023 #include "llvm/CodeGen/MachineFunctionPass.h"
00024 #include "llvm/CodeGen/ValueTypes.h"
00025 #include "llvm/Target/TargetMachine.h"
00026 #include "llvm/Support/Mangler.h"
00027 #include "llvm/ADT/Statistic.h"
00028 #include "llvm/Support/CommandLine.h"
00029 using namespace llvm;
00030 
00031 namespace {
00032   Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
00033   enum AsmWriterFlavor { att, intel };
00034 
00035   cl::opt<AsmWriterFlavor>
00036   AsmWriterFlavor("x86-asm-syntax",
00037                   cl::desc("Choose style of code to emit from X86 backend:"),
00038                   cl::values(
00039                              clEnumVal(att,   "  Emit AT&T-style assembly"),
00040                              clEnumVal(intel, "  Emit Intel-style assembly"),
00041                              clEnumValEnd),
00042                   cl::init(att));
00043 
00044   struct X86SharedAsmPrinter : public AsmPrinter {
00045     X86SharedAsmPrinter(std::ostream &O, TargetMachine &TM)
00046       : AsmPrinter(O, TM) { }
00047 
00048     void printConstantPool(MachineConstantPool *MCP);
00049     bool doFinalization(Module &M);
00050   };
00051 }
00052 
00053 static bool isScale(const MachineOperand &MO) {
00054   return MO.isImmediate() &&
00055     (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 ||
00056      MO.getImmedValue() == 4 || MO.getImmedValue() == 8);
00057 }
00058 
00059 static bool isMem(const MachineInstr *MI, unsigned Op) {
00060   if (MI->getOperand(Op).isFrameIndex()) return true;
00061   if (MI->getOperand(Op).isConstantPoolIndex()) return true;
00062   return Op+4 <= MI->getNumOperands() &&
00063     MI->getOperand(Op  ).isRegister() && isScale(MI->getOperand(Op+1)) &&
00064     MI->getOperand(Op+2).isRegister() && (MI->getOperand(Op+3).isImmediate() ||
00065         MI->getOperand(Op+3).isGlobalAddress());
00066 }
00067 
00068 // SwitchSection - Switch to the specified section of the executable if we are
00069 // not already in it!
00070 //
00071 static void SwitchSection(std::ostream &OS, std::string &CurSection,
00072                           const char *NewSection) {
00073   if (CurSection != NewSection) {
00074     CurSection = NewSection;
00075     if (!CurSection.empty())
00076       OS << "\t" << NewSection << "\n";
00077   }
00078 }
00079 
00080 /// printConstantPool - Print to the current output stream assembly
00081 /// representations of the constants in the constant pool MCP. This is
00082 /// used to print out constants which have been "spilled to memory" by
00083 /// the code generator.
00084 ///
00085 void X86SharedAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
00086   const std::vector<Constant*> &CP = MCP->getConstants();
00087   const TargetData &TD = TM.getTargetData();
00088  
00089   if (CP.empty()) return;
00090 
00091   for (unsigned i = 0, e = CP.size(); i != e; ++i) {
00092     O << "\t.section .rodata\n";
00093     emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType()));
00094     O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString
00095       << *CP[i] << "\n";
00096     emitGlobalConstant(CP[i]);
00097   }
00098 }
00099 
00100 bool X86SharedAsmPrinter::doFinalization(Module &M) {
00101   const TargetData &TD = TM.getTargetData();
00102   std::string CurSection;
00103 
00104   // Print out module-level global variables here.
00105   for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
00106     if (I->hasInitializer()) {   // External global require no code
00107       O << "\n\n";
00108       std::string name = Mang->getValueName(I);
00109       Constant *C = I->getInitializer();
00110       unsigned Size = TD.getTypeSize(C->getType());
00111       unsigned Align = TD.getTypeAlignmentShift(C->getType());
00112 
00113       if (C->isNullValue() && 
00114           (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
00115            I->hasWeakLinkage() /* FIXME: Verify correct */)) {
00116         SwitchSection(O, CurSection, ".data");
00117         if (I->hasInternalLinkage())
00118           O << "\t.local " << name << "\n";
00119         
00120         O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
00121           << "," << (1 << Align);
00122         O << "\t\t# ";
00123         WriteAsOperand(O, I, true, true, &M);
00124         O << "\n";
00125       } else {
00126         switch (I->getLinkage()) {
00127         case GlobalValue::LinkOnceLinkage:
00128         case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
00129           // Nonnull linkonce -> weak
00130           O << "\t.weak " << name << "\n";
00131           SwitchSection(O, CurSection, "");
00132           O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
00133           break;
00134         case GlobalValue::AppendingLinkage:
00135           // FIXME: appending linkage variables should go into a section of
00136           // their name or something.  For now, just emit them as external.
00137         case GlobalValue::ExternalLinkage:
00138           // If external or appending, declare as a global symbol
00139           O << "\t.globl " << name << "\n";
00140           // FALL THROUGH
00141         case GlobalValue::InternalLinkage:
00142           if (C->isNullValue())
00143             SwitchSection(O, CurSection, ".bss");
00144           else
00145             SwitchSection(O, CurSection, ".data");
00146           break;
00147         case GlobalValue::GhostLinkage:
00148           std::cerr << "GhostLinkage cannot appear in X86AsmPrinter!\n";
00149           abort();
00150         }
00151 
00152         emitAlignment(Align);
00153         O << "\t.type " << name << ",@object\n";
00154         O << "\t.size " << name << "," << Size << "\n";
00155         O << name << ":\t\t\t\t# ";
00156         WriteAsOperand(O, I, true, true, &M);
00157         O << " = ";
00158         WriteAsOperand(O, C, false, false, &M);
00159         O << "\n";
00160         emitGlobalConstant(C);
00161       }
00162     }
00163 
00164   AsmPrinter::doFinalization(M);
00165   return false; // success
00166 }
00167 
00168 namespace {
00169   struct X86IntelAsmPrinter : public X86SharedAsmPrinter {
00170     X86IntelAsmPrinter(std::ostream &O, TargetMachine &TM)
00171       : X86SharedAsmPrinter(O, TM) { }
00172 
00173     virtual const char *getPassName() const {
00174       return "X86 Intel-Style Assembly Printer";
00175     }
00176 
00177     /// printInstruction - This method is automatically generated by tablegen
00178     /// from the instruction set description.  This method returns true if the
00179     /// machine instruction was sufficiently described to print it, otherwise it
00180     /// returns false.
00181     bool printInstruction(const MachineInstr *MI);
00182 
00183     // This method is used by the tablegen'erated instruction printer.
00184     void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
00185       const MachineOperand &MO = MI->getOperand(OpNo);
00186       if (MO.getType() == MachineOperand::MO_MachineRegister) {
00187         assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physref??");
00188         // Bug Workaround: See note in Printer::doInitialization about %.
00189         O << "%" << TM.getRegisterInfo()->get(MO.getReg()).Name;
00190       } else {
00191         printOp(MO);
00192       }
00193     }
00194 
00195     void printCallOperand(const MachineInstr *MI, unsigned OpNo,
00196                           MVT::ValueType VT) {
00197       printOp(MI->getOperand(OpNo), true); // Don't print "OFFSET".
00198     }
00199 
00200     void printMemoryOperand(const MachineInstr *MI, unsigned OpNo,
00201                             MVT::ValueType VT) {
00202       switch (VT) {
00203       default: assert(0 && "Unknown arg size!");
00204       case MVT::i8:   O << "BYTE PTR "; break;
00205       case MVT::i16:  O << "WORD PTR "; break;
00206       case MVT::i32:
00207       case MVT::f32:  O << "DWORD PTR "; break;
00208       case MVT::i64:
00209       case MVT::f64:  O << "QWORD PTR "; break;
00210       case MVT::f80:  O << "XWORD PTR "; break;
00211       }
00212       printMemReference(MI, OpNo);
00213     }
00214 
00215     void printMachineInstruction(const MachineInstr *MI);
00216     void printOp(const MachineOperand &MO, bool elideOffsetKeyword = false);
00217     void printMemReference(const MachineInstr *MI, unsigned Op);
00218     bool runOnMachineFunction(MachineFunction &F);    
00219     bool doInitialization(Module &M);
00220   };
00221 } // end of anonymous namespace
00222 
00223 
00224 // Include the auto-generated portion of the assembly writer.
00225 #include "X86GenIntelAsmWriter.inc"
00226 
00227 
00228 /// runOnMachineFunction - This uses the printMachineInstruction()
00229 /// method to print assembly for each instruction.
00230 ///
00231 bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
00232   setupMachineFunction(MF);
00233   O << "\n\n";
00234 
00235   // Print out constants referenced by the function
00236   printConstantPool(MF.getConstantPool());
00237 
00238   // Print out labels for the function.
00239   O << "\t.text\n";
00240   emitAlignment(4);
00241   O << "\t.globl\t" << CurrentFnName << "\n";
00242   O << "\t.type\t" << CurrentFnName << ", @function\n";
00243   O << CurrentFnName << ":\n";
00244 
00245   // Print out code for the function.
00246   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
00247        I != E; ++I) {
00248     // Print a label for the basic block if there are any predecessors.
00249     if (I->pred_begin() != I->pred_end())
00250       O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t"
00251         << CommentString << " " << I->getBasicBlock()->getName() << "\n";
00252     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
00253          II != E; ++II) {
00254       // Print the assembly for the instruction.
00255       O << "\t";
00256       printMachineInstruction(II);
00257     }
00258   }
00259 
00260   // We didn't modify anything.
00261   return false;
00262 }
00263 
00264 void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
00265                                  bool elideOffsetKeyword /* = false */) {
00266   const MRegisterInfo &RI = *TM.getRegisterInfo();
00267   switch (MO.getType()) {
00268   case MachineOperand::MO_VirtualRegister:
00269     if (Value *V = MO.getVRegValueOrNull()) {
00270       O << "<" << V->getName() << ">";
00271       return;
00272     }
00273     // FALLTHROUGH
00274   case MachineOperand::MO_MachineRegister:
00275     if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
00276       // Bug Workaround: See note in Printer::doInitialization about %.
00277       O << "%" << RI.get(MO.getReg()).Name;
00278     else
00279       O << "%reg" << MO.getReg();
00280     return;
00281 
00282   case MachineOperand::MO_SignExtendedImmed:
00283   case MachineOperand::MO_UnextendedImmed:
00284     O << (int)MO.getImmedValue();
00285     return;
00286   case MachineOperand::MO_MachineBasicBlock: {
00287     MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
00288     O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
00289       << "_" << MBBOp->getNumber () << "\t# "
00290       << MBBOp->getBasicBlock ()->getName ();
00291     return;
00292   }
00293   case MachineOperand::MO_PCRelativeDisp:
00294     std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs";
00295     abort ();
00296     return;
00297   case MachineOperand::MO_GlobalAddress: {
00298     if (!elideOffsetKeyword)
00299       O << "OFFSET ";
00300     O << Mang->getValueName(MO.getGlobal());
00301     int Offset = MO.getOffset();
00302     if (Offset > 0)
00303       O << " + " << Offset;
00304     else if (Offset < 0)
00305       O << " - " << -Offset;
00306     return;
00307   }
00308   case MachineOperand::MO_ExternalSymbol:
00309     O << MO.getSymbolName();
00310     return;
00311   default:
00312     O << "<unknown operand type>"; return;    
00313   }
00314 }
00315 
00316 void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
00317   assert(isMem(MI, Op) && "Invalid memory reference!");
00318 
00319   const MachineOperand &BaseReg  = MI->getOperand(Op);
00320   int ScaleVal                   = MI->getOperand(Op+1).getImmedValue();
00321   const MachineOperand &IndexReg = MI->getOperand(Op+2);
00322   const MachineOperand &DispSpec = MI->getOperand(Op+3);
00323 
00324   if (BaseReg.isFrameIndex()) {
00325     O << "[frame slot #" << BaseReg.getFrameIndex();
00326     if (DispSpec.getImmedValue())
00327       O << " + " << DispSpec.getImmedValue();
00328     O << "]";
00329     return;
00330   } else if (BaseReg.isConstantPoolIndex()) {
00331     O << "[.CPI" << CurrentFnName << "_"
00332       << BaseReg.getConstantPoolIndex();
00333 
00334     if (IndexReg.getReg()) {
00335       O << " + ";
00336       if (ScaleVal != 1)
00337         O << ScaleVal << "*";
00338       printOp(IndexReg);
00339     }
00340     
00341     if (DispSpec.getImmedValue())
00342       O << " + " << DispSpec.getImmedValue();
00343     O << "]";
00344     return;
00345   }
00346 
00347   O << "[";
00348   bool NeedPlus = false;
00349   if (BaseReg.getReg()) {
00350     printOp(BaseReg, true);
00351     NeedPlus = true;
00352   }
00353 
00354   if (IndexReg.getReg()) {
00355     if (NeedPlus) O << " + ";
00356     if (ScaleVal != 1)
00357       O << ScaleVal << "*";
00358     printOp(IndexReg);
00359     NeedPlus = true;
00360   }
00361 
00362   if (DispSpec.isGlobalAddress()) {
00363     if (NeedPlus)
00364       O << " + ";
00365     printOp(DispSpec, true);
00366   } else {
00367     int DispVal = DispSpec.getImmedValue();
00368     if (DispVal) {
00369       if (NeedPlus)
00370         if (DispVal > 0)
00371           O << " + ";
00372         else {
00373           O << " - ";
00374           DispVal = -DispVal;
00375         }
00376       O << DispVal;
00377     }
00378   }
00379   O << "]";
00380 }
00381 
00382 
00383 /// printMachineInstruction -- Print out a single X86 LLVM instruction
00384 /// MI in Intel syntax to the current output stream.
00385 ///
00386 void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
00387   ++EmittedInsts;
00388 
00389   // Call the autogenerated instruction printer routines.
00390   printInstruction(MI);
00391 }
00392 
00393 bool X86IntelAsmPrinter::doInitialization(Module &M) {
00394   AsmPrinter::doInitialization(M);
00395   // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
00396   //
00397   // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an
00398   // instruction as a reference to the register named sp, and if you try to
00399   // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased
00400   // before being looked up in the symbol table. This creates spurious
00401   // `undefined symbol' errors when linking. Workaround: Do not use `noprefix'
00402   // mode, and decorate all register names with percent signs.
00403   O << "\t.intel_syntax\n";
00404   return false;
00405 }
00406 
00407 
00408 
00409 namespace {
00410   struct X86ATTAsmPrinter : public X86SharedAsmPrinter {
00411     X86ATTAsmPrinter(std::ostream &O, TargetMachine &TM)
00412       : X86SharedAsmPrinter(O, TM) { }
00413 
00414     virtual const char *getPassName() const {
00415       return "X86 AT&T-Style Assembly Printer";
00416     }
00417 
00418     /// printInstruction - This method is automatically generated by tablegen
00419     /// from the instruction set description.  This method returns true if the
00420     /// machine instruction was sufficiently described to print it, otherwise it
00421     /// returns false.
00422     bool printInstruction(const MachineInstr *MI);
00423 
00424     // This method is used by the tablegen'erated instruction printer.
00425     void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
00426       printOp(MI->getOperand(OpNo));
00427     }
00428 
00429     void printCallOperand(const MachineInstr *MI, unsigned OpNo,
00430                           MVT::ValueType VT) {
00431       printOp(MI->getOperand(OpNo), true); // Don't print '$' prefix.
00432     }
00433 
00434     void printMemoryOperand(const MachineInstr *MI, unsigned OpNo,
00435                             MVT::ValueType VT) {
00436       printMemReference(MI, OpNo);
00437     }
00438 
00439     void printMachineInstruction(const MachineInstr *MI);
00440     void printOp(const MachineOperand &MO, bool isCallOperand = false);
00441     void printMemReference(const MachineInstr *MI, unsigned Op);
00442     bool runOnMachineFunction(MachineFunction &F);    
00443   };
00444 } // end of anonymous namespace
00445 
00446 
00447 // Include the auto-generated portion of the assembly writer.
00448 #include "X86GenATTAsmWriter.inc"
00449 
00450 
00451 /// runOnMachineFunction - This uses the printMachineInstruction()
00452 /// method to print assembly for each instruction.
00453 ///
00454 bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
00455   setupMachineFunction(MF);
00456   O << "\n\n";
00457 
00458   // Print out constants referenced by the function
00459   printConstantPool(MF.getConstantPool());
00460 
00461   // Print out labels for the function.
00462   O << "\t.text\n";
00463   emitAlignment(4);
00464   O << "\t.globl\t" << CurrentFnName << "\n";
00465   O << "\t.type\t" << CurrentFnName << ", @function\n";
00466   O << CurrentFnName << ":\n";
00467 
00468   // Print out code for the function.
00469   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
00470        I != E; ++I) {
00471     // Print a label for the basic block.
00472     if (I->pred_begin() != I->pred_end())
00473       O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t"
00474         << CommentString << " " << I->getBasicBlock()->getName() << "\n";
00475     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
00476          II != E; ++II) {
00477       // Print the assembly for the instruction.
00478       O << "\t";
00479       printMachineInstruction(II);
00480     }
00481   }
00482 
00483   // We didn't modify anything.
00484   return false;
00485 }
00486 
00487 void X86ATTAsmPrinter::printOp(const MachineOperand &MO, bool isCallOp) {
00488   const MRegisterInfo &RI = *TM.getRegisterInfo();
00489   switch (MO.getType()) {
00490   case MachineOperand::MO_VirtualRegister:
00491   case MachineOperand::MO_MachineRegister:
00492     assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
00493            "Virtual registers should not make it this far!");
00494     O << '%';
00495     for (const char *Name = RI.get(MO.getReg()).Name; *Name; ++Name)
00496       O << (char)tolower(*Name);
00497     return;
00498 
00499   case MachineOperand::MO_SignExtendedImmed:
00500   case MachineOperand::MO_UnextendedImmed:
00501     O << '$' << (int)MO.getImmedValue();
00502     return;
00503   case MachineOperand::MO_MachineBasicBlock: {
00504     MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
00505     O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
00506       << "_" << MBBOp->getNumber () << "\t# "
00507       << MBBOp->getBasicBlock ()->getName ();
00508     return;
00509   }
00510   case MachineOperand::MO_PCRelativeDisp:
00511     std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs";
00512     abort ();
00513     return;
00514   case MachineOperand::MO_GlobalAddress: {
00515     if (!isCallOp) O << '$';
00516     O << Mang->getValueName(MO.getGlobal());
00517     int Offset = MO.getOffset();
00518     if (Offset > 0)
00519       O << "+" << Offset;
00520     else if (Offset < 0)
00521       O << Offset;
00522     return;
00523   }
00524   case MachineOperand::MO_ExternalSymbol:
00525     if (!isCallOp) O << '$';
00526     O << MO.getSymbolName();
00527     return;
00528   default:
00529     O << "<unknown operand type>"; return;    
00530   }
00531 }
00532 
00533 void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
00534   assert(isMem(MI, Op) && "Invalid memory reference!");
00535 
00536   const MachineOperand &BaseReg  = MI->getOperand(Op);
00537   int ScaleVal                   = MI->getOperand(Op+1).getImmedValue();
00538   const MachineOperand &IndexReg = MI->getOperand(Op+2);
00539   const MachineOperand &DispSpec = MI->getOperand(Op+3);
00540 
00541   if (BaseReg.isFrameIndex()) {
00542     O << "[frame slot #" << BaseReg.getFrameIndex();
00543     if (DispSpec.getImmedValue())
00544       O << " + " << DispSpec.getImmedValue();
00545     O << "]";
00546     return;
00547   } else if (BaseReg.isConstantPoolIndex()) {
00548     O << ".CPI" << CurrentFnName << "_"
00549       << BaseReg.getConstantPoolIndex();
00550     if (DispSpec.getImmedValue())
00551       O << "+" << DispSpec.getImmedValue();
00552     if (IndexReg.getReg()) {
00553       O << "(,";
00554       printOp(IndexReg);
00555       if (ScaleVal != 1)
00556         O << "," << ScaleVal;
00557       O << ")";
00558     }
00559     return;
00560   }
00561 
00562   if (DispSpec.isGlobalAddress()) {
00563     printOp(DispSpec, true);
00564   } else {
00565     int DispVal = DispSpec.getImmedValue();
00566     if (DispVal)
00567       O << DispVal;
00568   }
00569 
00570   if (IndexReg.getReg() || BaseReg.getReg()) {
00571     O << "(";
00572     if (BaseReg.getReg())
00573       printOp(BaseReg);
00574 
00575     if (IndexReg.getReg()) {
00576       O << ",";
00577       printOp(IndexReg);
00578       if (ScaleVal != 1)
00579         O << "," << ScaleVal;
00580     }
00581 
00582     O << ")";
00583   }
00584 }
00585 
00586 
00587 /// printMachineInstruction -- Print out a single X86 LLVM instruction
00588 /// MI in Intel syntax to the current output stream.
00589 ///
00590 void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
00591   ++EmittedInsts;
00592   // Call the autogenerated instruction printer routines.
00593   printInstruction(MI);
00594 }
00595 
00596 
00597 /// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code
00598 /// for a MachineFunction to the given output stream, using the given target
00599 /// machine description.
00600 ///
00601 FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
00602   switch (AsmWriterFlavor) {
00603   default: assert(0 && "Unknown asm flavor!");
00604   case intel:
00605     return new X86IntelAsmPrinter(o, tm);
00606   case att:
00607     return new X86ATTAsmPrinter(o, tm);
00608   }
00609 }