LLVM API Documentation
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/Module.h" 00019 #include "llvm/Assembly/Writer.h" 00020 #include "llvm/Support/Mangler.h" 00021 #include "llvm/Target/TargetOptions.h" 00022 using namespace llvm; 00023 00024 /// runOnMachineFunction - This uses the printMachineInstruction() 00025 /// method to print assembly for each instruction. 00026 /// 00027 bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 00028 if (forDarwin) { 00029 // Let PassManager know we need debug information and relay 00030 // the MachineDebugInfo address on to DwarfWriter. 00031 DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>()); 00032 } 00033 00034 SetupMachineFunction(MF); 00035 O << "\n\n"; 00036 00037 // Print out constants referenced by the function 00038 EmitConstantPool(MF.getConstantPool()); 00039 00040 // Print out labels for the function. 00041 SwitchSection("\t.text\n", MF.getFunction()); 00042 EmitAlignment(4); 00043 O << "\t.globl\t" << CurrentFnName << "\n"; 00044 if (HasDotTypeDotSizeDirective) 00045 O << "\t.type\t" << CurrentFnName << ", @function\n"; 00046 O << CurrentFnName << ":\n"; 00047 00048 if (forDarwin) { 00049 // Emit pre-function debug information. 00050 DW.BeginFunction(&MF); 00051 } 00052 00053 // Print out code for the function. 00054 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 00055 I != E; ++I) { 00056 // Print a label for the basic block if there are any predecessors. 00057 if (I->pred_begin() != I->pred_end()) 00058 O << PrivateGlobalPrefix << "BB" << CurrentFnName << "_" << I->getNumber() 00059 << ":\t" 00060 << CommentString << " " << I->getBasicBlock()->getName() << "\n"; 00061 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 00062 II != E; ++II) { 00063 // Print the assembly for the instruction. 00064 O << "\t"; 00065 printMachineInstruction(II); 00066 } 00067 } 00068 00069 if (forDarwin) { 00070 // Emit post-function debug information. 00071 DW.EndFunction(); 00072 } 00073 00074 // We didn't modify anything. 00075 return false; 00076 } 00077 00078 void X86IntelAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { 00079 unsigned char value = MI->getOperand(Op).getImmedValue(); 00080 assert(value <= 7 && "Invalid ssecc argument!"); 00081 switch (value) { 00082 case 0: O << "eq"; break; 00083 case 1: O << "lt"; break; 00084 case 2: O << "le"; break; 00085 case 3: O << "unord"; break; 00086 case 4: O << "neq"; break; 00087 case 5: O << "nlt"; break; 00088 case 6: O << "nle"; break; 00089 case 7: O << "ord"; break; 00090 } 00091 } 00092 00093 void X86IntelAsmPrinter::printOp(const MachineOperand &MO, 00094 const char *Modifier) { 00095 const MRegisterInfo &RI = *TM.getRegisterInfo(); 00096 switch (MO.getType()) { 00097 case MachineOperand::MO_VirtualRegister: 00098 if (Value *V = MO.getVRegValueOrNull()) { 00099 O << "<" << V->getName() << ">"; 00100 return; 00101 } 00102 // FALLTHROUGH 00103 case MachineOperand::MO_MachineRegister: 00104 if (MRegisterInfo::isPhysicalRegister(MO.getReg())) 00105 // Bug Workaround: See note in Printer::doInitialization about %. 00106 O << "%" << RI.get(MO.getReg()).Name; 00107 else 00108 O << "%reg" << MO.getReg(); 00109 return; 00110 00111 case MachineOperand::MO_SignExtendedImmed: 00112 case MachineOperand::MO_UnextendedImmed: 00113 O << (int)MO.getImmedValue(); 00114 return; 00115 case MachineOperand::MO_MachineBasicBlock: { 00116 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); 00117 O << PrivateGlobalPrefix << "BB" 00118 << Mang->getValueName(MBBOp->getParent()->getFunction()) 00119 << "_" << MBBOp->getNumber () << "\t# " 00120 << MBBOp->getBasicBlock ()->getName (); 00121 return; 00122 } 00123 case MachineOperand::MO_PCRelativeDisp: 00124 assert(0 && "Shouldn't use addPCDisp() when building X86 MachineInstrs"); 00125 abort (); 00126 return; 00127 case MachineOperand::MO_ConstantPoolIndex: { 00128 bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 00129 if (!isMemOp) O << "OFFSET "; 00130 O << "[" << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_" 00131 << MO.getConstantPoolIndex(); 00132 if (forDarwin && TM.getRelocationModel() == Reloc::PIC) 00133 O << "-\"L" << getFunctionNumber() << "$pb\""; 00134 int Offset = MO.getOffset(); 00135 if (Offset > 0) 00136 O << " + " << Offset; 00137 else if (Offset < 0) 00138 O << Offset; 00139 O << "]"; 00140 return; 00141 } 00142 case MachineOperand::MO_GlobalAddress: { 00143 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 00144 bool isMemOp = Modifier && !strcmp(Modifier, "mem"); 00145 if (!isMemOp && !isCallOp) O << "OFFSET "; 00146 if (forDarwin && TM.getRelocationModel() != Reloc::Static) { 00147 GlobalValue *GV = MO.getGlobal(); 00148 std::string Name = Mang->getValueName(GV); 00149 if (!isMemOp && !isCallOp) O << '$'; 00150 // Link-once, External, or Weakly-linked global variables need 00151 // non-lazily-resolved stubs 00152 if (GV->isExternal() || GV->hasWeakLinkage() || 00153 GV->hasLinkOnceLinkage()) { 00154 // Dynamically-resolved functions need a stub for the function. 00155 if (isCallOp && isa<Function>(GV) && cast<Function>(GV)->isExternal()) { 00156 FnStubs.insert(Name); 00157 O << "L" << Name << "$stub"; 00158 } else { 00159 GVStubs.insert(Name); 00160 O << "L" << Name << "$non_lazy_ptr"; 00161 } 00162 } else { 00163 O << Mang->getValueName(GV); 00164 } 00165 if (!isCallOp && TM.getRelocationModel() == Reloc::PIC) 00166 O << "-\"L" << getFunctionNumber() << "$pb\""; 00167 } else 00168 O << Mang->getValueName(MO.getGlobal()); 00169 int Offset = MO.getOffset(); 00170 if (Offset > 0) 00171 O << " + " << Offset; 00172 else if (Offset < 0) 00173 O << Offset; 00174 return; 00175 } 00176 case MachineOperand::MO_ExternalSymbol: { 00177 bool isCallOp = Modifier && !strcmp(Modifier, "call"); 00178 if (isCallOp && forDarwin && TM.getRelocationModel() != Reloc::Static) { 00179 std::string Name(GlobalPrefix); 00180 Name += MO.getSymbolName(); 00181 FnStubs.insert(Name); 00182 O << "L" << Name << "$stub"; 00183 return; 00184 } 00185 if (!isCallOp) O << "OFFSET "; 00186 O << GlobalPrefix << MO.getSymbolName(); 00187 return; 00188 } 00189 default: 00190 O << "<unknown operand type>"; return; 00191 } 00192 } 00193 00194 void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){ 00195 assert(isMem(MI, Op) && "Invalid memory reference!"); 00196 00197 const MachineOperand &BaseReg = MI->getOperand(Op); 00198 int ScaleVal = MI->getOperand(Op+1).getImmedValue(); 00199 const MachineOperand &IndexReg = MI->getOperand(Op+2); 00200 const MachineOperand &DispSpec = MI->getOperand(Op+3); 00201 00202 if (BaseReg.isFrameIndex()) { 00203 O << "[frame slot #" << BaseReg.getFrameIndex(); 00204 if (DispSpec.getImmedValue()) 00205 O << " + " << DispSpec.getImmedValue(); 00206 O << "]"; 00207 return; 00208 } 00209 00210 O << "["; 00211 bool NeedPlus = false; 00212 if (BaseReg.getReg()) { 00213 printOp(BaseReg, "mem"); 00214 NeedPlus = true; 00215 } 00216 00217 if (IndexReg.getReg()) { 00218 if (NeedPlus) O << " + "; 00219 if (ScaleVal != 1) 00220 O << ScaleVal << "*"; 00221 printOp(IndexReg); 00222 NeedPlus = true; 00223 } 00224 00225 if (DispSpec.isGlobalAddress() || DispSpec.isConstantPoolIndex()) { 00226 if (NeedPlus) 00227 O << " + "; 00228 printOp(DispSpec, "mem"); 00229 } else { 00230 int DispVal = DispSpec.getImmedValue(); 00231 if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) { 00232 if (NeedPlus) 00233 if (DispVal > 0) 00234 O << " + "; 00235 else { 00236 O << " - "; 00237 DispVal = -DispVal; 00238 } 00239 O << DispVal; 00240 } 00241 } 00242 O << "]"; 00243 } 00244 00245 void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { 00246 O << "\"L" << getFunctionNumber() << "$pb\"\n"; 00247 O << "\"L" << getFunctionNumber() << "$pb\":"; 00248 } 00249 00250 /// printMachineInstruction -- Print out a single X86 LLVM instruction 00251 /// MI in Intel syntax to the current output stream. 00252 /// 00253 void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 00254 ++EmittedInsts; 00255 00256 // Call the autogenerated instruction printer routines. 00257 printInstruction(MI); 00258 } 00259 00260 bool X86IntelAsmPrinter::doInitialization(Module &M) { 00261 X86SharedAsmPrinter::doInitialization(M); 00262 // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly. 00263 // 00264 // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an 00265 // instruction as a reference to the register named sp, and if you try to 00266 // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased 00267 // before being looked up in the symbol table. This creates spurious 00268 // `undefined symbol' errors when linking. Workaround: Do not use `noprefix' 00269 // mode, and decorate all register names with percent signs. 00270 O << "\t.intel_syntax\n"; 00271 return false; 00272 } 00273 00274 // Include the auto-generated portion of the assembly writer. 00275 #include "X86GenAsmWriter1.inc"