1212793Sdim//===-- X86AsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly --------===// 2212793Sdim// 3212793Sdim// The LLVM Compiler Infrastructure 4212793Sdim// 5212793Sdim// This file is distributed under the University of Illinois Open Source 6212793Sdim// License. See LICENSE.TXT for details. 7212793Sdim// 8212793Sdim//===----------------------------------------------------------------------===// 9212793Sdim// 10212793Sdim// This file contains a printer that converts from our internal representation 11212793Sdim// of machine-dependent LLVM code to X86 machine code. 12212793Sdim// 13212793Sdim//===----------------------------------------------------------------------===// 14212793Sdim 15212793Sdim#include "X86AsmPrinter.h" 16252723Sdim#include "InstPrinter/X86ATTInstPrinter.h" 17212793Sdim#include "X86.h" 18212793Sdim#include "X86COFFMachineModuleInfo.h" 19212793Sdim#include "X86MachineFunctionInfo.h" 20212793Sdim#include "X86TargetMachine.h" 21252723Sdim#include "llvm/ADT/SmallString.h" 22252723Sdim#include "llvm/Assembly/Writer.h" 23252723Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h" 24252723Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h" 25252723Sdim#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 26245431Sdim#include "llvm/DebugInfo.h" 27252723Sdim#include "llvm/IR/CallingConv.h" 28252723Sdim#include "llvm/IR/DerivedTypes.h" 29252723Sdim#include "llvm/IR/Module.h" 30252723Sdim#include "llvm/IR/Type.h" 31212793Sdim#include "llvm/MC/MCAsmInfo.h" 32212793Sdim#include "llvm/MC/MCContext.h" 33212793Sdim#include "llvm/MC/MCExpr.h" 34212793Sdim#include "llvm/MC/MCSectionMachO.h" 35212793Sdim#include "llvm/MC/MCStreamer.h" 36212793Sdim#include "llvm/MC/MCSymbol.h" 37212793Sdim#include "llvm/Support/COFF.h" 38212793Sdim#include "llvm/Support/Debug.h" 39212793Sdim#include "llvm/Support/ErrorHandling.h" 40226890Sdim#include "llvm/Support/TargetRegistry.h" 41252723Sdim#include "llvm/Target/Mangler.h" 42252723Sdim#include "llvm/Target/TargetOptions.h" 43212793Sdimusing namespace llvm; 44212793Sdim 45212793Sdim//===----------------------------------------------------------------------===// 46212793Sdim// Primitive Helper Functions. 47212793Sdim//===----------------------------------------------------------------------===// 48212793Sdim 49212793Sdim/// runOnMachineFunction - Emit the function body. 50212793Sdim/// 51212793Sdimbool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 52212793Sdim SetupMachineFunction(MF); 53212793Sdim 54218893Sdim if (Subtarget->isTargetCOFF() && !Subtarget->isTargetEnvMacho()) { 55212793Sdim bool Intrn = MF.getFunction()->hasInternalLinkage(); 56212793Sdim OutStreamer.BeginCOFFSymbolDef(CurrentFnSym); 57218893Sdim OutStreamer.EmitCOFFSymbolStorageClass(Intrn ? COFF::IMAGE_SYM_CLASS_STATIC 58212793Sdim : COFF::IMAGE_SYM_CLASS_EXTERNAL); 59212793Sdim OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION 60212793Sdim << COFF::SCT_COMPLEX_TYPE_SHIFT); 61212793Sdim OutStreamer.EndCOFFSymbolDef(); 62212793Sdim } 63212793Sdim 64212793Sdim // Have common code print out the function header with linkage info etc. 65212793Sdim EmitFunctionHeader(); 66212793Sdim 67212793Sdim // Emit the rest of the function body. 68212793Sdim EmitFunctionBody(); 69212793Sdim 70212793Sdim // We didn't modify anything. 71212793Sdim return false; 72212793Sdim} 73212793Sdim 74212793Sdim/// printSymbolOperand - Print a raw symbol reference operand. This handles 75212793Sdim/// jump tables, constant pools, global address and external symbols, all of 76212793Sdim/// which print to a label with various suffixes for relocation types etc. 77212793Sdimvoid X86AsmPrinter::printSymbolOperand(const MachineOperand &MO, 78212793Sdim raw_ostream &O) { 79212793Sdim switch (MO.getType()) { 80212793Sdim default: llvm_unreachable("unknown symbol type!"); 81212793Sdim case MachineOperand::MO_JumpTableIndex: 82212793Sdim O << *GetJTISymbol(MO.getIndex()); 83212793Sdim break; 84212793Sdim case MachineOperand::MO_ConstantPoolIndex: 85212793Sdim O << *GetCPISymbol(MO.getIndex()); 86212793Sdim printOffset(MO.getOffset(), O); 87212793Sdim break; 88212793Sdim case MachineOperand::MO_GlobalAddress: { 89212793Sdim const GlobalValue *GV = MO.getGlobal(); 90218893Sdim 91212793Sdim MCSymbol *GVSym; 92212793Sdim if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) 93212793Sdim GVSym = GetSymbolWithGlobalValueBase(GV, "$stub"); 94212793Sdim else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || 95212793Sdim MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || 96212793Sdim MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) 97212793Sdim GVSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 98212793Sdim else 99263509Sdim GVSym = getSymbol(GV); 100212793Sdim 101212793Sdim // Handle dllimport linkage. 102212793Sdim if (MO.getTargetFlags() == X86II::MO_DLLIMPORT) 103212793Sdim GVSym = OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); 104218893Sdim 105212793Sdim if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || 106212793Sdim MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) { 107212793Sdim MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 108218893Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 109212793Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym); 110212793Sdim if (StubSym.getPointer() == 0) 111212793Sdim StubSym = MachineModuleInfoImpl:: 112263509Sdim StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); 113212793Sdim } else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){ 114212793Sdim MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 115212793Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 116212793Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry(Sym); 117212793Sdim if (StubSym.getPointer() == 0) 118212793Sdim StubSym = MachineModuleInfoImpl:: 119263509Sdim StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); 120212793Sdim } else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { 121212793Sdim MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub"); 122212793Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 123212793Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); 124212793Sdim if (StubSym.getPointer() == 0) 125212793Sdim StubSym = MachineModuleInfoImpl:: 126263509Sdim StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); 127212793Sdim } 128218893Sdim 129212793Sdim // If the name begins with a dollar-sign, enclose it in parens. We do this 130212793Sdim // to avoid having it look like an integer immediate to the assembler. 131212793Sdim if (GVSym->getName()[0] != '$') 132212793Sdim O << *GVSym; 133212793Sdim else 134212793Sdim O << '(' << *GVSym << ')'; 135212793Sdim printOffset(MO.getOffset(), O); 136212793Sdim break; 137212793Sdim } 138212793Sdim case MachineOperand::MO_ExternalSymbol: { 139212793Sdim const MCSymbol *SymToPrint; 140212793Sdim if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { 141212793Sdim SmallString<128> TempNameStr; 142212793Sdim TempNameStr += StringRef(MO.getSymbolName()); 143212793Sdim TempNameStr += StringRef("$stub"); 144218893Sdim 145212793Sdim MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str()); 146212793Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 147212793Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); 148212793Sdim if (StubSym.getPointer() == 0) { 149212793Sdim TempNameStr.erase(TempNameStr.end()-5, TempNameStr.end()); 150212793Sdim StubSym = MachineModuleInfoImpl:: 151212793Sdim StubValueTy(OutContext.GetOrCreateSymbol(TempNameStr.str()), 152212793Sdim true); 153212793Sdim } 154212793Sdim SymToPrint = StubSym.getPointer(); 155212793Sdim } else { 156212793Sdim SymToPrint = GetExternalSymbolSymbol(MO.getSymbolName()); 157212793Sdim } 158218893Sdim 159212793Sdim // If the name begins with a dollar-sign, enclose it in parens. We do this 160212793Sdim // to avoid having it look like an integer immediate to the assembler. 161218893Sdim if (SymToPrint->getName()[0] != '$') 162212793Sdim O << *SymToPrint; 163212793Sdim else 164212793Sdim O << '(' << *SymToPrint << '('; 165212793Sdim break; 166212793Sdim } 167212793Sdim } 168218893Sdim 169212793Sdim switch (MO.getTargetFlags()) { 170212793Sdim default: 171212793Sdim llvm_unreachable("Unknown target flag on GV operand"); 172212793Sdim case X86II::MO_NO_FLAG: // No flag. 173212793Sdim break; 174212793Sdim case X86II::MO_DARWIN_NONLAZY: 175212793Sdim case X86II::MO_DLLIMPORT: 176212793Sdim case X86II::MO_DARWIN_STUB: 177212793Sdim // These affect the name of the symbol, not any suffix. 178212793Sdim break; 179212793Sdim case X86II::MO_GOT_ABSOLUTE_ADDRESS: 180218893Sdim O << " + [.-" << *MF->getPICBaseSymbol() << ']'; 181218893Sdim break; 182212793Sdim case X86II::MO_PIC_BASE_OFFSET: 183212793Sdim case X86II::MO_DARWIN_NONLAZY_PIC_BASE: 184212793Sdim case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: 185218893Sdim O << '-' << *MF->getPICBaseSymbol(); 186212793Sdim break; 187212793Sdim case X86II::MO_TLSGD: O << "@TLSGD"; break; 188245431Sdim case X86II::MO_TLSLD: O << "@TLSLD"; break; 189245431Sdim case X86II::MO_TLSLDM: O << "@TLSLDM"; break; 190212793Sdim case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break; 191212793Sdim case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break; 192212793Sdim case X86II::MO_TPOFF: O << "@TPOFF"; break; 193245431Sdim case X86II::MO_DTPOFF: O << "@DTPOFF"; break; 194212793Sdim case X86II::MO_NTPOFF: O << "@NTPOFF"; break; 195245431Sdim case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break; 196212793Sdim case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break; 197212793Sdim case X86II::MO_GOT: O << "@GOT"; break; 198212793Sdim case X86II::MO_GOTOFF: O << "@GOTOFF"; break; 199212793Sdim case X86II::MO_PLT: O << "@PLT"; break; 200212793Sdim case X86II::MO_TLVP: O << "@TLVP"; break; 201212793Sdim case X86II::MO_TLVP_PIC_BASE: 202218893Sdim O << "@TLVP" << '-' << *MF->getPICBaseSymbol(); 203212793Sdim break; 204252723Sdim case X86II::MO_SECREL: O << "@SECREL32"; break; 205212793Sdim } 206212793Sdim} 207212793Sdim 208245431Sdim/// printPCRelImm - This is used to print an immediate value that ends up 209212793Sdim/// being encoded as a pc-relative value. These print slightly differently, for 210212793Sdim/// example, a $ is not emitted. 211245431Sdimvoid X86AsmPrinter::printPCRelImm(const MachineInstr *MI, unsigned OpNo, 212212793Sdim raw_ostream &O) { 213212793Sdim const MachineOperand &MO = MI->getOperand(OpNo); 214212793Sdim switch (MO.getType()) { 215212793Sdim default: llvm_unreachable("Unknown pcrel immediate operand"); 216212793Sdim case MachineOperand::MO_Register: 217212793Sdim // pc-relativeness was handled when computing the value in the reg. 218212793Sdim printOperand(MI, OpNo, O); 219212793Sdim return; 220212793Sdim case MachineOperand::MO_Immediate: 221212793Sdim O << MO.getImm(); 222212793Sdim return; 223212793Sdim case MachineOperand::MO_MachineBasicBlock: 224212793Sdim O << *MO.getMBB()->getSymbol(); 225212793Sdim return; 226212793Sdim case MachineOperand::MO_GlobalAddress: 227212793Sdim case MachineOperand::MO_ExternalSymbol: 228212793Sdim printSymbolOperand(MO, O); 229212793Sdim return; 230212793Sdim } 231212793Sdim} 232212793Sdim 233212793Sdim 234212793Sdimvoid X86AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, 235245431Sdim raw_ostream &O, const char *Modifier, 236245431Sdim unsigned AsmVariant) { 237212793Sdim const MachineOperand &MO = MI->getOperand(OpNo); 238212793Sdim switch (MO.getType()) { 239212793Sdim default: llvm_unreachable("unknown operand type!"); 240212793Sdim case MachineOperand::MO_Register: { 241245431Sdim // FIXME: Enumerating AsmVariant, so we can remove magic number. 242245431Sdim if (AsmVariant == 0) O << '%'; 243212793Sdim unsigned Reg = MO.getReg(); 244212793Sdim if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { 245245431Sdim MVT::SimpleValueType VT = (strcmp(Modifier+6,"64") == 0) ? 246212793Sdim MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : 247212793Sdim ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); 248212793Sdim Reg = getX86SubSuperRegister(Reg, VT); 249212793Sdim } 250212793Sdim O << X86ATTInstPrinter::getRegisterName(Reg); 251212793Sdim return; 252212793Sdim } 253212793Sdim 254212793Sdim case MachineOperand::MO_Immediate: 255252723Sdim if (AsmVariant == 0) O << '$'; 256252723Sdim O << MO.getImm(); 257212793Sdim return; 258212793Sdim 259212793Sdim case MachineOperand::MO_JumpTableIndex: 260212793Sdim case MachineOperand::MO_ConstantPoolIndex: 261218893Sdim case MachineOperand::MO_GlobalAddress: 262212793Sdim case MachineOperand::MO_ExternalSymbol: { 263252723Sdim if (AsmVariant == 0) O << '$'; 264212793Sdim printSymbolOperand(MO, O); 265212793Sdim break; 266212793Sdim } 267212793Sdim } 268212793Sdim} 269212793Sdim 270212793Sdimvoid X86AsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op, 271212793Sdim raw_ostream &O, const char *Modifier) { 272212793Sdim const MachineOperand &BaseReg = MI->getOperand(Op); 273212793Sdim const MachineOperand &IndexReg = MI->getOperand(Op+2); 274212793Sdim const MachineOperand &DispSpec = MI->getOperand(Op+3); 275212793Sdim 276212793Sdim // If we really don't want to print out (rip), don't. 277212793Sdim bool HasBaseReg = BaseReg.getReg() != 0; 278212793Sdim if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") && 279212793Sdim BaseReg.getReg() == X86::RIP) 280212793Sdim HasBaseReg = false; 281218893Sdim 282212793Sdim // HasParenPart - True if we will print out the () part of the mem ref. 283212793Sdim bool HasParenPart = IndexReg.getReg() || HasBaseReg; 284218893Sdim 285212793Sdim if (DispSpec.isImm()) { 286212793Sdim int DispVal = DispSpec.getImm(); 287212793Sdim if (DispVal || !HasParenPart) 288212793Sdim O << DispVal; 289212793Sdim } else { 290212793Sdim assert(DispSpec.isGlobal() || DispSpec.isCPI() || 291212793Sdim DispSpec.isJTI() || DispSpec.isSymbol()); 292212793Sdim printSymbolOperand(MI->getOperand(Op+3), O); 293212793Sdim } 294212793Sdim 295218893Sdim if (Modifier && strcmp(Modifier, "H") == 0) 296218893Sdim O << "+8"; 297218893Sdim 298212793Sdim if (HasParenPart) { 299212793Sdim assert(IndexReg.getReg() != X86::ESP && 300212793Sdim "X86 doesn't allow scaling by ESP"); 301212793Sdim 302212793Sdim O << '('; 303212793Sdim if (HasBaseReg) 304212793Sdim printOperand(MI, Op, O, Modifier); 305212793Sdim 306212793Sdim if (IndexReg.getReg()) { 307212793Sdim O << ','; 308212793Sdim printOperand(MI, Op+2, O, Modifier); 309212793Sdim unsigned ScaleVal = MI->getOperand(Op+1).getImm(); 310212793Sdim if (ScaleVal != 1) 311212793Sdim O << ',' << ScaleVal; 312212793Sdim } 313212793Sdim O << ')'; 314212793Sdim } 315212793Sdim} 316212793Sdim 317212793Sdimvoid X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, 318212793Sdim raw_ostream &O, const char *Modifier) { 319212793Sdim assert(isMem(MI, Op) && "Invalid memory reference!"); 320212793Sdim const MachineOperand &Segment = MI->getOperand(Op+4); 321212793Sdim if (Segment.getReg()) { 322212793Sdim printOperand(MI, Op+4, O, Modifier); 323212793Sdim O << ':'; 324212793Sdim } 325212793Sdim printLeaMemReference(MI, Op, O, Modifier); 326212793Sdim} 327212793Sdim 328245431Sdimvoid X86AsmPrinter::printIntelMemReference(const MachineInstr *MI, unsigned Op, 329245431Sdim raw_ostream &O, const char *Modifier, 330245431Sdim unsigned AsmVariant){ 331245431Sdim const MachineOperand &BaseReg = MI->getOperand(Op); 332245431Sdim unsigned ScaleVal = MI->getOperand(Op+1).getImm(); 333245431Sdim const MachineOperand &IndexReg = MI->getOperand(Op+2); 334245431Sdim const MachineOperand &DispSpec = MI->getOperand(Op+3); 335245431Sdim const MachineOperand &SegReg = MI->getOperand(Op+4); 336263509Sdim 337245431Sdim // If this has a segment register, print it. 338245431Sdim if (SegReg.getReg()) { 339245431Sdim printOperand(MI, Op+4, O, Modifier, AsmVariant); 340245431Sdim O << ':'; 341245431Sdim } 342263509Sdim 343245431Sdim O << '['; 344263509Sdim 345245431Sdim bool NeedPlus = false; 346245431Sdim if (BaseReg.getReg()) { 347245431Sdim printOperand(MI, Op, O, Modifier, AsmVariant); 348245431Sdim NeedPlus = true; 349245431Sdim } 350263509Sdim 351245431Sdim if (IndexReg.getReg()) { 352245431Sdim if (NeedPlus) O << " + "; 353245431Sdim if (ScaleVal != 1) 354245431Sdim O << ScaleVal << '*'; 355245431Sdim printOperand(MI, Op+2, O, Modifier, AsmVariant); 356245431Sdim NeedPlus = true; 357245431Sdim } 358245431Sdim 359252723Sdim if (!DispSpec.isImm()) { 360252723Sdim if (NeedPlus) O << " + "; 361252723Sdim printOperand(MI, Op+3, O, Modifier, AsmVariant); 362252723Sdim } else { 363252723Sdim int64_t DispVal = DispSpec.getImm(); 364252723Sdim if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) { 365252723Sdim if (NeedPlus) { 366252723Sdim if (DispVal > 0) 367252723Sdim O << " + "; 368252723Sdim else { 369252723Sdim O << " - "; 370252723Sdim DispVal = -DispVal; 371252723Sdim } 372245431Sdim } 373252723Sdim O << DispVal; 374245431Sdim } 375252723Sdim } 376245431Sdim O << ']'; 377212793Sdim} 378212793Sdim 379212793Sdimbool X86AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode, 380212793Sdim raw_ostream &O) { 381212793Sdim unsigned Reg = MO.getReg(); 382212793Sdim switch (Mode) { 383212793Sdim default: return true; // Unknown mode. 384212793Sdim case 'b': // Print QImode register 385212793Sdim Reg = getX86SubSuperRegister(Reg, MVT::i8); 386212793Sdim break; 387212793Sdim case 'h': // Print QImode high register 388212793Sdim Reg = getX86SubSuperRegister(Reg, MVT::i8, true); 389212793Sdim break; 390212793Sdim case 'w': // Print HImode register 391212793Sdim Reg = getX86SubSuperRegister(Reg, MVT::i16); 392212793Sdim break; 393212793Sdim case 'k': // Print SImode register 394212793Sdim Reg = getX86SubSuperRegister(Reg, MVT::i32); 395212793Sdim break; 396266759Sdim case 'q': 397266759Sdim // Print 64-bit register names if 64-bit integer registers are available. 398266759Sdim // Otherwise, print 32-bit register names. 399266759Sdim MVT::SimpleValueType Ty = Subtarget->is64Bit() ? MVT::i64 : MVT::i32; 400266759Sdim Reg = getX86SubSuperRegister(Reg, Ty); 401212793Sdim break; 402212793Sdim } 403212793Sdim 404212793Sdim O << '%' << X86ATTInstPrinter::getRegisterName(Reg); 405212793Sdim return false; 406212793Sdim} 407212793Sdim 408212793Sdim/// PrintAsmOperand - Print out an operand for an inline asm expression. 409212793Sdim/// 410212793Sdimbool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 411212793Sdim unsigned AsmVariant, 412212793Sdim const char *ExtraCode, raw_ostream &O) { 413212793Sdim // Does this asm operand have a single letter operand modifier? 414212793Sdim if (ExtraCode && ExtraCode[0]) { 415212793Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 416212793Sdim 417212793Sdim const MachineOperand &MO = MI->getOperand(OpNo); 418218893Sdim 419212793Sdim switch (ExtraCode[0]) { 420245431Sdim default: 421245431Sdim // See if this is a generic print operand 422245431Sdim return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); 423212793Sdim case 'a': // This is an address. Currently only 'i' and 'r' are expected. 424212793Sdim if (MO.isImm()) { 425212793Sdim O << MO.getImm(); 426212793Sdim return false; 427218893Sdim } 428212793Sdim if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) { 429212793Sdim printSymbolOperand(MO, O); 430212793Sdim if (Subtarget->isPICStyleRIPRel()) 431212793Sdim O << "(%rip)"; 432212793Sdim return false; 433212793Sdim } 434212793Sdim if (MO.isReg()) { 435212793Sdim O << '('; 436212793Sdim printOperand(MI, OpNo, O); 437212793Sdim O << ')'; 438212793Sdim return false; 439212793Sdim } 440212793Sdim return true; 441212793Sdim 442212793Sdim case 'c': // Don't print "$" before a global var name or constant. 443212793Sdim if (MO.isImm()) 444212793Sdim O << MO.getImm(); 445212793Sdim else if (MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isSymbol()) 446212793Sdim printSymbolOperand(MO, O); 447212793Sdim else 448212793Sdim printOperand(MI, OpNo, O); 449212793Sdim return false; 450212793Sdim 451212793Sdim case 'A': // Print '*' before a register (it must be a register) 452212793Sdim if (MO.isReg()) { 453212793Sdim O << '*'; 454212793Sdim printOperand(MI, OpNo, O); 455212793Sdim return false; 456212793Sdim } 457212793Sdim return true; 458212793Sdim 459212793Sdim case 'b': // Print QImode register 460212793Sdim case 'h': // Print QImode high register 461212793Sdim case 'w': // Print HImode register 462212793Sdim case 'k': // Print SImode register 463212793Sdim case 'q': // Print DImode register 464212793Sdim if (MO.isReg()) 465212793Sdim return printAsmMRegister(MO, ExtraCode[0], O); 466212793Sdim printOperand(MI, OpNo, O); 467212793Sdim return false; 468212793Sdim 469212793Sdim case 'P': // This is the operand of a call, treat specially. 470245431Sdim printPCRelImm(MI, OpNo, O); 471212793Sdim return false; 472212793Sdim 473212793Sdim case 'n': // Negate the immediate or print a '-' before the operand. 474212793Sdim // Note: this is a temporary solution. It should be handled target 475212793Sdim // independently as part of the 'MC' work. 476212793Sdim if (MO.isImm()) { 477212793Sdim O << -MO.getImm(); 478212793Sdim return false; 479212793Sdim } 480212793Sdim O << '-'; 481212793Sdim } 482212793Sdim } 483212793Sdim 484245431Sdim printOperand(MI, OpNo, O, /*Modifier*/ 0, AsmVariant); 485212793Sdim return false; 486212793Sdim} 487212793Sdim 488212793Sdimbool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 489212793Sdim unsigned OpNo, unsigned AsmVariant, 490212793Sdim const char *ExtraCode, 491212793Sdim raw_ostream &O) { 492245431Sdim if (AsmVariant) { 493245431Sdim printIntelMemReference(MI, OpNo, O); 494245431Sdim return false; 495245431Sdim } 496245431Sdim 497212793Sdim if (ExtraCode && ExtraCode[0]) { 498212793Sdim if (ExtraCode[1] != 0) return true; // Unknown modifier. 499212793Sdim 500212793Sdim switch (ExtraCode[0]) { 501212793Sdim default: return true; // Unknown modifier. 502212793Sdim case 'b': // Print QImode register 503212793Sdim case 'h': // Print QImode high register 504212793Sdim case 'w': // Print HImode register 505212793Sdim case 'k': // Print SImode register 506212793Sdim case 'q': // Print SImode register 507212793Sdim // These only apply to registers, ignore on mem. 508212793Sdim break; 509218893Sdim case 'H': 510218893Sdim printMemReference(MI, OpNo, O, "H"); 511218893Sdim return false; 512212793Sdim case 'P': // Don't print @PLT, but do print as memory. 513212793Sdim printMemReference(MI, OpNo, O, "no-rip"); 514212793Sdim return false; 515212793Sdim } 516212793Sdim } 517212793Sdim printMemReference(MI, OpNo, O); 518212793Sdim return false; 519212793Sdim} 520212793Sdim 521212793Sdimvoid X86AsmPrinter::EmitStartOfAsmFile(Module &M) { 522218893Sdim if (Subtarget->isTargetEnvMacho()) 523212793Sdim OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); 524263509Sdim 525263509Sdim if (Subtarget->isTargetCOFF()) { 526263509Sdim // Emit an absolute @feat.00 symbol. This appears to be some kind of 527263509Sdim // compiler features bitfield read by link.exe. 528263509Sdim if (!Subtarget->is64Bit()) { 529263509Sdim MCSymbol *S = MMI->getContext().GetOrCreateSymbol(StringRef("@feat.00")); 530263509Sdim OutStreamer.BeginCOFFSymbolDef(S); 531263509Sdim OutStreamer.EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC); 532263509Sdim OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL); 533263509Sdim OutStreamer.EndCOFFSymbolDef(); 534263509Sdim // According to the PE-COFF spec, the LSB of this value marks the object 535263509Sdim // for "registered SEH". This means that all SEH handler entry points 536263509Sdim // must be registered in .sxdata. Use of any unregistered handlers will 537263509Sdim // cause the process to terminate immediately. LLVM does not know how to 538263509Sdim // register any SEH handlers, so its object files should be safe. 539263509Sdim S->setAbsolute(); 540263509Sdim OutStreamer.EmitSymbolAttribute(S, MCSA_Global); 541263509Sdim OutStreamer.EmitAssignment( 542263509Sdim S, MCConstantExpr::Create(int64_t(1), MMI->getContext())); 543263509Sdim } 544263509Sdim } 545212793Sdim} 546212793Sdim 547212793Sdim 548212793Sdimvoid X86AsmPrinter::EmitEndOfAsmFile(Module &M) { 549218893Sdim if (Subtarget->isTargetEnvMacho()) { 550212793Sdim // All darwin targets use mach-o. 551212793Sdim MachineModuleInfoMachO &MMIMacho = 552212793Sdim MMI->getObjFileInfo<MachineModuleInfoMachO>(); 553218893Sdim 554212793Sdim // Output stubs for dynamically-linked functions. 555212793Sdim MachineModuleInfoMachO::SymbolListTy Stubs; 556212793Sdim 557212793Sdim Stubs = MMIMacho.GetFnStubList(); 558212793Sdim if (!Stubs.empty()) { 559218893Sdim const MCSection *TheSection = 560212793Sdim OutContext.getMachOSection("__IMPORT", "__jump_table", 561212793Sdim MCSectionMachO::S_SYMBOL_STUBS | 562212793Sdim MCSectionMachO::S_ATTR_SELF_MODIFYING_CODE | 563212793Sdim MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 564212793Sdim 5, SectionKind::getMetadata()); 565212793Sdim OutStreamer.SwitchSection(TheSection); 566212793Sdim 567212793Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 568212793Sdim // L_foo$stub: 569212793Sdim OutStreamer.EmitLabel(Stubs[i].first); 570212793Sdim // .indirect_symbol _foo 571212793Sdim OutStreamer.EmitSymbolAttribute(Stubs[i].second.getPointer(), 572212793Sdim MCSA_IndirectSymbol); 573226890Sdim // hlt; hlt; hlt; hlt; hlt hlt = 0xf4. 574226890Sdim const char HltInsts[] = "\xf4\xf4\xf4\xf4\xf4"; 575252723Sdim OutStreamer.EmitBytes(StringRef(HltInsts, 5)); 576212793Sdim } 577218893Sdim 578212793Sdim Stubs.clear(); 579212793Sdim OutStreamer.AddBlankLine(); 580212793Sdim } 581212793Sdim 582212793Sdim // Output stubs for external and common global variables. 583212793Sdim Stubs = MMIMacho.GetGVStubList(); 584212793Sdim if (!Stubs.empty()) { 585218893Sdim const MCSection *TheSection = 586212793Sdim OutContext.getMachOSection("__IMPORT", "__pointers", 587212793Sdim MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, 588212793Sdim SectionKind::getMetadata()); 589212793Sdim OutStreamer.SwitchSection(TheSection); 590212793Sdim 591212793Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 592212793Sdim // L_foo$non_lazy_ptr: 593212793Sdim OutStreamer.EmitLabel(Stubs[i].first); 594212793Sdim // .indirect_symbol _foo 595212793Sdim MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 596212793Sdim OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), 597212793Sdim MCSA_IndirectSymbol); 598212793Sdim // .long 0 599212793Sdim if (MCSym.getInt()) 600212793Sdim // External to current translation unit. 601252723Sdim OutStreamer.EmitIntValue(0, 4/*size*/); 602212793Sdim else 603212793Sdim // Internal to current translation unit. 604212793Sdim // 605212793Sdim // When we place the LSDA into the TEXT section, the type info 606212793Sdim // pointers need to be indirect and pc-rel. We accomplish this by 607212793Sdim // using NLPs. However, sometimes the types are local to the file. So 608212793Sdim // we need to fill in the value for the NLP in those cases. 609212793Sdim OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), 610252723Sdim OutContext), 4/*size*/); 611212793Sdim } 612212793Sdim Stubs.clear(); 613212793Sdim OutStreamer.AddBlankLine(); 614212793Sdim } 615212793Sdim 616212793Sdim Stubs = MMIMacho.GetHiddenGVStubList(); 617212793Sdim if (!Stubs.empty()) { 618212793Sdim OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 619212793Sdim EmitAlignment(2); 620212793Sdim 621212793Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 622212793Sdim // L_foo$non_lazy_ptr: 623212793Sdim OutStreamer.EmitLabel(Stubs[i].first); 624212793Sdim // .long _foo 625212793Sdim OutStreamer.EmitValue(MCSymbolRefExpr:: 626212793Sdim Create(Stubs[i].second.getPointer(), 627252723Sdim OutContext), 4/*size*/); 628212793Sdim } 629212793Sdim Stubs.clear(); 630212793Sdim OutStreamer.AddBlankLine(); 631212793Sdim } 632212793Sdim 633263509Sdim SM.serializeToStackMapSection(); 634263509Sdim 635212793Sdim // Funny Darwin hack: This flag tells the linker that no global symbols 636212793Sdim // contain code that falls through to other global symbols (e.g. the obvious 637212793Sdim // implementation of multiple entry points). If this doesn't occur, the 638212793Sdim // linker can safely perform dead code stripping. Since LLVM never 639212793Sdim // generates code that does this, it is always safe to set. 640212793Sdim OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 641212793Sdim } 642212793Sdim 643218893Sdim if (Subtarget->isTargetWindows() && !Subtarget->isTargetCygMing() && 644235633Sdim MMI->usesVAFloatArgument()) { 645218893Sdim StringRef SymbolName = Subtarget->is64Bit() ? "_fltused" : "__fltused"; 646218893Sdim MCSymbol *S = MMI->getContext().GetOrCreateSymbol(SymbolName); 647218893Sdim OutStreamer.EmitSymbolAttribute(S, MCSA_Global); 648218893Sdim } 649218893Sdim 650218893Sdim if (Subtarget->isTargetCOFF() && !Subtarget->isTargetEnvMacho()) { 651212793Sdim X86COFFMachineModuleInfo &COFFMMI = 652212793Sdim MMI->getObjFileInfo<X86COFFMachineModuleInfo>(); 653212793Sdim 654212793Sdim // Emit type information for external functions 655212793Sdim typedef X86COFFMachineModuleInfo::externals_iterator externals_iterator; 656212793Sdim for (externals_iterator I = COFFMMI.externals_begin(), 657212793Sdim E = COFFMMI.externals_end(); 658212793Sdim I != E; ++I) { 659212793Sdim OutStreamer.BeginCOFFSymbolDef(CurrentFnSym); 660212793Sdim OutStreamer.EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_EXTERNAL); 661212793Sdim OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION 662212793Sdim << COFF::SCT_COMPLEX_TYPE_SHIFT); 663212793Sdim OutStreamer.EndCOFFSymbolDef(); 664212793Sdim } 665212793Sdim 666212793Sdim // Necessary for dllexport support 667212793Sdim std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals; 668212793Sdim 669212793Sdim const TargetLoweringObjectFileCOFF &TLOFCOFF = 670212793Sdim static_cast<const TargetLoweringObjectFileCOFF&>(getObjFileLowering()); 671212793Sdim 672212793Sdim for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) 673212793Sdim if (I->hasDLLExportLinkage()) 674263509Sdim DLLExportedFns.push_back(getSymbol(I)); 675212793Sdim 676212793Sdim for (Module::const_global_iterator I = M.global_begin(), 677212793Sdim E = M.global_end(); I != E; ++I) 678212793Sdim if (I->hasDLLExportLinkage()) 679263509Sdim DLLExportedGlobals.push_back(getSymbol(I)); 680212793Sdim 681212793Sdim // Output linker support code for dllexported globals on windows. 682212793Sdim if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) { 683212793Sdim OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection()); 684212793Sdim SmallString<128> name; 685212793Sdim for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i) { 686212793Sdim if (Subtarget->isTargetWindows()) 687212793Sdim name = " /EXPORT:"; 688212793Sdim else 689212793Sdim name = " -export:"; 690212793Sdim name += DLLExportedGlobals[i]->getName(); 691212793Sdim if (Subtarget->isTargetWindows()) 692212793Sdim name += ",DATA"; 693212793Sdim else 694212793Sdim name += ",data"; 695252723Sdim OutStreamer.EmitBytes(name); 696212793Sdim } 697212793Sdim 698212793Sdim for (unsigned i = 0, e = DLLExportedFns.size(); i != e; ++i) { 699212793Sdim if (Subtarget->isTargetWindows()) 700212793Sdim name = " /EXPORT:"; 701212793Sdim else 702212793Sdim name = " -export:"; 703212793Sdim name += DLLExportedFns[i]->getName(); 704252723Sdim OutStreamer.EmitBytes(name); 705212793Sdim } 706212793Sdim } 707212793Sdim } 708212793Sdim 709212793Sdim if (Subtarget->isTargetELF()) { 710212793Sdim const TargetLoweringObjectFileELF &TLOFELF = 711212793Sdim static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); 712212793Sdim 713212793Sdim MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); 714212793Sdim 715212793Sdim // Output stubs for external and common global variables. 716212793Sdim MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); 717212793Sdim if (!Stubs.empty()) { 718212793Sdim OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); 719245431Sdim const DataLayout *TD = TM.getDataLayout(); 720212793Sdim 721212793Sdim for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 722212793Sdim OutStreamer.EmitLabel(Stubs[i].first); 723212793Sdim OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), 724252723Sdim TD->getPointerSize()); 725212793Sdim } 726212793Sdim Stubs.clear(); 727212793Sdim } 728212793Sdim } 729212793Sdim} 730212793Sdim 731212793Sdim//===----------------------------------------------------------------------===// 732212793Sdim// Target Registry Stuff 733212793Sdim//===----------------------------------------------------------------------===// 734212793Sdim 735212793Sdim// Force static initialization. 736218893Sdimextern "C" void LLVMInitializeX86AsmPrinter() { 737212793Sdim RegisterAsmPrinter<X86AsmPrinter> X(TheX86_32Target); 738212793Sdim RegisterAsmPrinter<X86AsmPrinter> Y(TheX86_64Target); 739212793Sdim} 740