LLVM API Documentation

X86IntelAsmPrinter.cpp

Go to the documentation of this file.
00001 //===-- X86IntelAsmPrinter.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 format assembly language.
00012 // This printer is the output mechanism used by `llc'.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "X86IntelAsmPrinter.h"
00017 #include "X86.h"
00018 #include "llvm/Constants.h"
00019 #include "llvm/Module.h"
00020 #include "llvm/Assembly/Writer.h"
00021 #include "llvm/Support/Mangler.h"
00022 #include "llvm/Target/TargetOptions.h"
00023 using namespace llvm;
00024 
00025 X86IntelAsmPrinter::X86IntelAsmPrinter(std::ostream &O, X86TargetMachine &TM)
00026     : X86SharedAsmPrinter(O, TM) {
00027 }
00028 
00029 /// runOnMachineFunction - This uses the printMachineInstruction()
00030 /// method to print assembly for each instruction.
00031 ///
00032 bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
00033   SetupMachineFunction(MF);
00034   O << "\n\n";
00035 
00036   // Print out constants referenced by the function
00037   EmitConstantPool(MF.getConstantPool());
00038 
00039   // Print out labels for the function.
00040   SwitchToTextSection("_text", MF.getFunction());
00041   EmitAlignment(4);
00042   if (MF.getFunction()->getLinkage() == GlobalValue::ExternalLinkage)
00043     O << "\tpublic " << CurrentFnName << "\n";
00044   O << CurrentFnName << "\tproc near\n";
00045   
00046   // Print out code for the function.
00047   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
00048        I != E; ++I) {
00049     // Print a label for the basic block if there are any predecessors.
00050     if (I->pred_begin() != I->pred_end()) {
00051       printBasicBlockLabel(I, true);
00052       O << '\n';
00053     }
00054     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
00055          II != E; ++II) {
00056       // Print the assembly for the instruction.
00057       O << "\t";
00058       printMachineInstruction(II);
00059     }
00060   }
00061 
00062   O << CurrentFnName << "\tendp\n";
00063 
00064   // We didn't modify anything.
00065   return false;
00066 }
00067 
00068 void X86IntelAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
00069   unsigned char value = MI->getOperand(Op).getImmedValue();
00070   assert(value <= 7 && "Invalid ssecc argument!");
00071   switch (value) {
00072   case 0: O << "eq"; break;
00073   case 1: O << "lt"; break;
00074   case 2: O << "le"; break;
00075   case 3: O << "unord"; break;
00076   case 4: O << "neq"; break;
00077   case 5: O << "nlt"; break;
00078   case 6: O << "nle"; break;
00079   case 7: O << "ord"; break;
00080   }
00081 }
00082 
00083 void X86IntelAsmPrinter::printOp(const MachineOperand &MO, 
00084                                  const char *Modifier) {
00085   const MRegisterInfo &RI = *TM.getRegisterInfo();
00086   switch (MO.getType()) {
00087   case MachineOperand::MO_Register:
00088     if (MRegisterInfo::isPhysicalRegister(MO.getReg())) {
00089       unsigned Reg = MO.getReg();
00090       if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
00091         MVT::ValueType VT = (strcmp(Modifier,"subreg16") == 0)
00092           ? MVT::i16 : MVT::i8;
00093         Reg = getX86SubSuperRegister(Reg, VT);
00094       }
00095       O << RI.get(Reg).Name;
00096     } else
00097       O << "reg" << MO.getReg();
00098     return;
00099 
00100   case MachineOperand::MO_Immediate:
00101     O << MO.getImmedValue();
00102     return;
00103   case MachineOperand::MO_MachineBasicBlock:
00104     printBasicBlockLabel(MO.getMachineBasicBlock());
00105     return;
00106   case MachineOperand::MO_ConstantPoolIndex: {
00107     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
00108     if (!isMemOp) O << "OFFSET ";
00109     O << "[" << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
00110       << MO.getConstantPoolIndex();
00111     int Offset = MO.getOffset();
00112     if (Offset > 0)
00113       O << " + " << Offset;
00114     else if (Offset < 0)
00115       O << Offset;
00116     O << "]";
00117     return;
00118   }
00119   case MachineOperand::MO_GlobalAddress: {
00120     bool isCallOp = Modifier && !strcmp(Modifier, "call");
00121     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
00122     if (!isMemOp && !isCallOp) O << "OFFSET ";
00123     O << Mang->getValueName(MO.getGlobal());
00124     int Offset = MO.getOffset();
00125     if (Offset > 0)
00126       O << " + " << Offset;
00127     else if (Offset < 0)
00128       O << Offset;
00129     return;
00130   }
00131   case MachineOperand::MO_ExternalSymbol: {
00132     bool isCallOp = Modifier && !strcmp(Modifier, "call");
00133     if (!isCallOp) O << "OFFSET ";
00134     O << GlobalPrefix << MO.getSymbolName();
00135     return;
00136   }
00137   default:
00138     O << "<unknown operand type>"; return;
00139   }
00140 }
00141 
00142 void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
00143   assert(isMem(MI, Op) && "Invalid memory reference!");
00144 
00145   const MachineOperand &BaseReg  = MI->getOperand(Op);
00146   int ScaleVal                   = MI->getOperand(Op+1).getImmedValue();
00147   const MachineOperand &IndexReg = MI->getOperand(Op+2);
00148   const MachineOperand &DispSpec = MI->getOperand(Op+3);
00149 
00150   if (BaseReg.isFrameIndex()) {
00151     O << "[frame slot #" << BaseReg.getFrameIndex();
00152     if (DispSpec.getImmedValue())
00153       O << " + " << DispSpec.getImmedValue();
00154     O << "]";
00155     return;
00156   }
00157 
00158   O << "[";
00159   bool NeedPlus = false;
00160   if (BaseReg.getReg()) {
00161     printOp(BaseReg, "mem");
00162     NeedPlus = true;
00163   }
00164 
00165   if (IndexReg.getReg()) {
00166     if (NeedPlus) O << " + ";
00167     if (ScaleVal != 1)
00168       O << ScaleVal << "*";
00169     printOp(IndexReg);
00170     NeedPlus = true;
00171   }
00172 
00173   if (DispSpec.isGlobalAddress() || DispSpec.isConstantPoolIndex()) {
00174     if (NeedPlus)
00175       O << " + ";
00176     printOp(DispSpec, "mem");
00177   } else {
00178     int DispVal = DispSpec.getImmedValue();
00179     if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) {
00180       if (NeedPlus)
00181         if (DispVal > 0)
00182           O << " + ";
00183         else {
00184           O << " - ";
00185           DispVal = -DispVal;
00186         }
00187       O << DispVal;
00188     }
00189   }
00190   O << "]";
00191 }
00192 
00193 void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
00194   O << "\"L" << getFunctionNumber() << "$pb\"\n";
00195   O << "\"L" << getFunctionNumber() << "$pb\":";
00196 }
00197 
00198 bool X86IntelAsmPrinter::printAsmMRegister(const MachineOperand &MO,
00199                                            const char Mode) {
00200   const MRegisterInfo &RI = *TM.getRegisterInfo();
00201   unsigned Reg = MO.getReg();
00202   switch (Mode) {
00203   default: return true;  // Unknown mode.
00204   case 'b': // Print QImode register
00205     Reg = getX86SubSuperRegister(Reg, MVT::i8);
00206     break;
00207   case 'h': // Print QImode high register
00208     Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
00209     break;
00210   case 'w': // Print HImode register
00211     Reg = getX86SubSuperRegister(Reg, MVT::i16);
00212     break;
00213   case 'k': // Print SImode register
00214     Reg = getX86SubSuperRegister(Reg, MVT::i32);
00215     break;
00216   }
00217 
00218   O << '%' << RI.get(Reg).Name;
00219   return false;
00220 }
00221 
00222 /// PrintAsmOperand - Print out an operand for an inline asm expression.
00223 ///
00224 bool X86IntelAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00225                                          unsigned AsmVariant, 
00226                                          const char *ExtraCode) {
00227   // Does this asm operand have a single letter operand modifier?
00228   if (ExtraCode && ExtraCode[0]) {
00229     if (ExtraCode[1] != 0) return true; // Unknown modifier.
00230     
00231     switch (ExtraCode[0]) {
00232     default: return true;  // Unknown modifier.
00233     case 'b': // Print QImode register
00234     case 'h': // Print QImode high register
00235     case 'w': // Print HImode register
00236     case 'k': // Print SImode register
00237       return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]);
00238     }
00239   }
00240   
00241   printOperand(MI, OpNo);
00242   return false;
00243 }
00244 
00245 bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
00246                                                unsigned OpNo,
00247                                                unsigned AsmVariant, 
00248                                                const char *ExtraCode) {
00249   if (ExtraCode && ExtraCode[0])
00250     return true; // Unknown modifier.
00251   printMemReference(MI, OpNo);
00252   return false;
00253 }
00254 
00255 /// printMachineInstruction -- Print out a single X86 LLVM instruction
00256 /// MI in Intel syntax to the current output stream.
00257 ///
00258 void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
00259   ++EmittedInsts;
00260 
00261   // See if a truncate instruction can be turned into a nop.
00262   switch (MI->getOpcode()) {
00263   default: break;
00264   case X86::TRUNC_GR32_GR16:
00265   case X86::TRUNC_GR32_GR8:
00266   case X86::TRUNC_GR16_GR8: {
00267     const MachineOperand &MO0 = MI->getOperand(0);
00268     const MachineOperand &MO1 = MI->getOperand(1);
00269     unsigned Reg0 = MO0.getReg();
00270     unsigned Reg1 = MO1.getReg();
00271     if (MI->getOpcode() == X86::TRUNC_GR32_GR16)
00272       Reg1 = getX86SubSuperRegister(Reg1, MVT::i16);
00273     else
00274       Reg1 = getX86SubSuperRegister(Reg1, MVT::i8);
00275     O << CommentString << " TRUNCATE ";
00276     if (Reg0 != Reg1)
00277       O << "\n\t";
00278     break;
00279   }
00280   }
00281 
00282   // Call the autogenerated instruction printer routines.
00283   printInstruction(MI);
00284 }
00285 
00286 bool X86IntelAsmPrinter::doInitialization(Module &M) {
00287   GlobalPrefix = "_";
00288   CommentString = ";";
00289 
00290   X86SharedAsmPrinter::doInitialization(M);
00291 
00292   PrivateGlobalPrefix = "$";
00293   AlignDirective = "\talign\t";
00294   ZeroDirective = "\tdb\t";
00295   ZeroDirectiveSuffix = " dup(0)";
00296   AsciiDirective = "\tdb\t";
00297   AscizDirective = 0;
00298   Data8bitsDirective = "\tdb\t";
00299   Data16bitsDirective = "\tdw\t";
00300   Data32bitsDirective = "\tdd\t";
00301   Data64bitsDirective = "\tdq\t";
00302   HasDotTypeDotSizeDirective = false;
00303   Mang->markCharUnacceptable('.');
00304   
00305   DefaultTextSection = "_text";
00306   DefaultDataSection = "_data";
00307   SwitchToSectionDirective = "";
00308   TextSectionStartSuffix = "\tsegment 'CODE'";
00309   DataSectionStartSuffix = "\tsegment 'DATA'";
00310   SectionEndDirectiveSuffix = "\tends\n";
00311 
00312   O << "\t.686\n\t.model flat\n\n";
00313 
00314   // Emit declarations for external functions.
00315   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
00316     if (I->isExternal())
00317       O << "\textern " << Mang->getValueName(I) << ":near\n";
00318 
00319   // Emit declarations for external globals.  Note that VC++ always declares
00320   // external globals to have type byte, and if that's good enough for VC++...
00321   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
00322        I != E; ++I) {
00323     if (I->isExternal())
00324       O << "\textern " << Mang->getValueName(I) << ":byte\n";
00325   }
00326 
00327   return false;
00328 }
00329 
00330 bool X86IntelAsmPrinter::doFinalization(Module &M) {
00331   const TargetData *TD = TM.getTargetData();
00332 
00333   // Print out module-level global variables here.
00334   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
00335        I != E; ++I) {
00336     if (I->isExternal()) continue;   // External global require no code
00337     
00338     // Check to see if this is a special global used by LLVM, if so, emit it.
00339     if (EmitSpecialLLVMGlobal(I))
00340       continue;
00341     
00342     std::string name = Mang->getValueName(I);
00343     Constant *C = I->getInitializer();
00344     unsigned Size = TD->getTypeSize(C->getType());
00345     unsigned Align = getPreferredAlignmentLog(I);
00346     bool bCustomSegment = false;
00347 
00348     switch (I->getLinkage()) {
00349     case GlobalValue::LinkOnceLinkage:
00350     case GlobalValue::WeakLinkage:
00351       SwitchToDataSection("", 0);
00352       O << name << "?\tsegment common 'COMMON'\n";
00353       bCustomSegment = true;
00354       // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
00355       // are also available.
00356       break;
00357     case GlobalValue::AppendingLinkage:
00358       SwitchToDataSection("", 0);
00359       O << name << "?\tsegment public 'DATA'\n";
00360       bCustomSegment = true;
00361       // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
00362       // are also available.
00363       break;
00364     case GlobalValue::ExternalLinkage:
00365       O << "\tpublic " << name << "\n";
00366       // FALL THROUGH
00367     case GlobalValue::InternalLinkage:
00368       SwitchToDataSection(DefaultDataSection, I);
00369       break;
00370     default:
00371       assert(0 && "Unknown linkage type!");
00372     }
00373 
00374     if (!bCustomSegment)
00375       EmitAlignment(Align, I);
00376 
00377     O << name << ":\t\t\t\t" << CommentString << " " << I->getName() << '\n';
00378 
00379     EmitGlobalConstant(C);
00380 
00381     if (bCustomSegment)
00382       O << name << "?\tends\n";
00383   }
00384   
00385   // Bypass X86SharedAsmPrinter::doFinalization().
00386   AsmPrinter::doFinalization(M);
00387   SwitchToDataSection("", 0);
00388   O << "\tend\n";
00389   return false; // success
00390 }
00391 
00392 void X86IntelAsmPrinter::EmitString(const ConstantArray *CVA) const {
00393   unsigned NumElts = CVA->getNumOperands();
00394   if (NumElts) {
00395     // ML does not have escape sequences except '' for '.  It also has a maximum
00396     // string length of 255.
00397     unsigned len = 0;
00398     bool inString = false;
00399     for (unsigned i = 0; i < NumElts; i++) {
00400       int n = cast<ConstantInt>(CVA->getOperand(i))->getRawValue() & 255;
00401       if (len == 0)
00402         O << "\tdb ";
00403 
00404       if (n >= 32 && n <= 127) {
00405         if (!inString) {
00406           if (len > 0) {
00407             O << ",'";
00408             len += 2;
00409           } else {
00410             O << "'";
00411             len++;
00412           }
00413           inString = true;
00414         }
00415         if (n == '\'') {
00416           O << "'";
00417           len++;
00418         }
00419         O << char(n);
00420       } else {
00421         if (inString) {
00422           O << "'";
00423           len++;
00424           inString = false;
00425         }
00426         if (len > 0) {
00427           O << ",";
00428           len++;
00429         }
00430         O << n;
00431         len += 1 + (n > 9) + (n > 99);
00432       }
00433 
00434       if (len > 60) {
00435         if (inString) {
00436           O << "'";
00437           inString = false;
00438         }
00439         O << "\n";
00440         len = 0;
00441       }
00442     }
00443 
00444     if (len > 0) {
00445       if (inString)
00446         O << "'";
00447       O << "\n";
00448     }
00449   }
00450 }
00451 
00452 // Include the auto-generated portion of the assembly writer.
00453 #include "X86GenAsmWriter1.inc"