1 //===-- X86AsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains a printer that converts from our internal representation 11 // of machine-dependent LLVM code to X86 machine code. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "X86AsmPrinter.h" 16 #include "InstPrinter/X86ATTInstPrinter.h" 17 #include "MCTargetDesc/X86BaseInfo.h" 18 #include "X86InstrInfo.h" 19 #include "X86MachineFunctionInfo.h" 20 #include "llvm/ADT/SmallString.h" 21 #include "llvm/CodeGen/MachineModuleInfoImpls.h" 22 #include "llvm/CodeGen/MachineValueType.h" 23 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 24 #include "llvm/IR/DebugInfo.h" 25 #include "llvm/IR/DerivedTypes.h" 26 #include "llvm/IR/Mangler.h" 27 #include "llvm/IR/Module.h" 28 #include "llvm/IR/Type.h" 29 #include "llvm/MC/MCAsmInfo.h" 30 #include "llvm/MC/MCContext.h" 31 #include "llvm/MC/MCExpr.h" 32 #include "llvm/MC/MCSectionMachO.h" 33 #include "llvm/MC/MCStreamer.h" 34 #include "llvm/MC/MCSymbol.h" 35 #include "llvm/Support/COFF.h" 36 #include "llvm/Support/Debug.h" 37 #include "llvm/Support/ErrorHandling.h" 38 #include "llvm/Support/TargetRegistry.h" 39 using namespace llvm; 40 41 //===----------------------------------------------------------------------===// 42 // Primitive Helper Functions. 43 //===----------------------------------------------------------------------===// 44 45 /// runOnMachineFunction - Emit the function body. 46 /// 47 bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 48 SetupMachineFunction(MF); 49 50 if (Subtarget->isTargetCOFF()) { 51 bool Intrn = MF.getFunction()->hasInternalLinkage(); 52 OutStreamer.BeginCOFFSymbolDef(CurrentFnSym); 53 OutStreamer.EmitCOFFSymbolStorageClass(Intrn ? COFF::IMAGE_SYM_CLASS_STATIC 54 : COFF::IMAGE_SYM_CLASS_EXTERNAL); 55 OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION 56 << COFF::SCT_COMPLEX_TYPE_SHIFT); 57 OutStreamer.EndCOFFSymbolDef(); 58 } 59 60 // Have common code print out the function header with linkage info etc. 61 EmitFunctionHeader(); 62 63 // Emit the rest of the function body. 64 EmitFunctionBody(); 65 66 // We didn't modify anything. 67 return false; 68 } 69 70 /// printSymbolOperand - Print a raw symbol reference operand. This handles 71 /// jump tables, constant pools, global address and external symbols, all of 72 /// which print to a label with various suffixes for relocation types etc. 73 static void printSymbolOperand(X86AsmPrinter &P, const MachineOperand &MO, 74 raw_ostream &O) { 75 switch (MO.getType()) { 76 default: llvm_unreachable("unknown symbol type!"); 77 case MachineOperand::MO_ConstantPoolIndex: 78 O << *P.GetCPISymbol(MO.getIndex()); 79 P.printOffset(MO.getOffset(), O); 80 break; 81 case MachineOperand::MO_GlobalAddress: { 82 const GlobalValue *GV = MO.getGlobal(); 83 84 MCSymbol *GVSym; 85 if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) 86 GVSym = P.getSymbolWithGlobalValueBase(GV, "$stub"); 87 else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || 88 MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || 89 MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) 90 GVSym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 91 else 92 GVSym = P.getSymbol(GV); 93 94 // Handle dllimport linkage. 95 if (MO.getTargetFlags() == X86II::MO_DLLIMPORT) 96 GVSym = 97 P.OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); 98 99 if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || 100 MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) { 101 MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 102 MachineModuleInfoImpl::StubValueTy &StubSym = 103 P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym); 104 if (!StubSym.getPointer()) 105 StubSym = MachineModuleInfoImpl:: 106 StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); 107 } else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){ 108 MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 109 MachineModuleInfoImpl::StubValueTy &StubSym = 110 P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry( 111 Sym); 112 if (!StubSym.getPointer()) 113 StubSym = MachineModuleInfoImpl:: 114 StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); 115 } else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { 116 MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$stub"); 117 MachineModuleInfoImpl::StubValueTy &StubSym = 118 P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); 119 if (!StubSym.getPointer()) 120 StubSym = MachineModuleInfoImpl:: 121 StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage()); 122 } 123 124 // If the name begins with a dollar-sign, enclose it in parens. We do this 125 // to avoid having it look like an integer immediate to the assembler. 126 if (GVSym->getName()[0] != '$') 127 O << *GVSym; 128 else 129 O << '(' << *GVSym << ')'; 130 P.printOffset(MO.getOffset(), O); 131 break; 132 } 133 } 134 135 switch (MO.getTargetFlags()) { 136 default: 137 llvm_unreachable("Unknown target flag on GV operand"); 138 case X86II::MO_NO_FLAG: // No flag. 139 break; 140 case X86II::MO_DARWIN_NONLAZY: 141 case X86II::MO_DLLIMPORT: 142 case X86II::MO_DARWIN_STUB: 143 // These affect the name of the symbol, not any suffix. 144 break; 145 case X86II::MO_GOT_ABSOLUTE_ADDRESS: 146 O << " + [.-" << *P.MF->getPICBaseSymbol() << ']'; 147 break; 148 case X86II::MO_PIC_BASE_OFFSET: 149 case X86II::MO_DARWIN_NONLAZY_PIC_BASE: 150 case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: 151 O << '-' << *P.MF->getPICBaseSymbol(); 152 break; 153 case X86II::MO_TLSGD: O << "@TLSGD"; break; 154 case X86II::MO_TLSLD: O << "@TLSLD"; break; 155 case X86II::MO_TLSLDM: O << "@TLSLDM"; break; 156 case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break; 157 case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break; 158 case X86II::MO_TPOFF: O << "@TPOFF"; break; 159 case X86II::MO_DTPOFF: O << "@DTPOFF"; break; 160 case X86II::MO_NTPOFF: O << "@NTPOFF"; break; 161 case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break; 162 case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break; 163 case X86II::MO_GOT: O << "@GOT"; break; 164 case X86II::MO_GOTOFF: O << "@GOTOFF"; break; 165 case X86II::MO_PLT: O << "@PLT"; break; 166 case X86II::MO_TLVP: O << "@TLVP"; break; 167 case X86II::MO_TLVP_PIC_BASE: 168 O << "@TLVP" << '-' << *P.MF->getPICBaseSymbol(); 169 break; 170 case X86II::MO_SECREL: O << "@SECREL32"; break; 171 } 172 } 173 174 static void printOperand(X86AsmPrinter &P, const MachineInstr *MI, 175 unsigned OpNo, raw_ostream &O, 176 const char *Modifier = nullptr, unsigned AsmVariant = 0); 177 178 /// printPCRelImm - This is used to print an immediate value that ends up 179 /// being encoded as a pc-relative value. These print slightly differently, for 180 /// example, a $ is not emitted. 181 static void printPCRelImm(X86AsmPrinter &P, const MachineInstr *MI, 182 unsigned OpNo, raw_ostream &O) { 183 const MachineOperand &MO = MI->getOperand(OpNo); 184 switch (MO.getType()) { 185 default: llvm_unreachable("Unknown pcrel immediate operand"); 186 case MachineOperand::MO_Register: 187 // pc-relativeness was handled when computing the value in the reg. 188 printOperand(P, MI, OpNo, O); 189 return; 190 case MachineOperand::MO_Immediate: 191 O << MO.getImm(); 192 return; 193 case MachineOperand::MO_GlobalAddress: 194 printSymbolOperand(P, MO, O); 195 return; 196 } 197 } 198 199 static void printOperand(X86AsmPrinter &P, const MachineInstr *MI, 200 unsigned OpNo, raw_ostream &O, const char *Modifier, 201 unsigned AsmVariant) { 202 const MachineOperand &MO = MI->getOperand(OpNo); 203 switch (MO.getType()) { 204 default: llvm_unreachable("unknown operand type!"); 205 case MachineOperand::MO_Register: { 206 // FIXME: Enumerating AsmVariant, so we can remove magic number. 207 if (AsmVariant == 0) O << '%'; 208 unsigned Reg = MO.getReg(); 209 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { 210 MVT::SimpleValueType VT = (strcmp(Modifier+6,"64") == 0) ? 211 MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : 212 ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); 213 Reg = getX86SubSuperRegister(Reg, VT); 214 } 215 O << X86ATTInstPrinter::getRegisterName(Reg); 216 return; 217 } 218 219 case MachineOperand::MO_Immediate: 220 if (AsmVariant == 0) O << '$'; 221 O << MO.getImm(); 222 return; 223 224 case MachineOperand::MO_GlobalAddress: { 225 if (AsmVariant == 0) O << '$'; 226 printSymbolOperand(P, MO, O); 227 break; 228 } 229 } 230 } 231 232 static void printLeaMemReference(X86AsmPrinter &P, const MachineInstr *MI, 233 unsigned Op, raw_ostream &O, 234 const char *Modifier = nullptr) { 235 const MachineOperand &BaseReg = MI->getOperand(Op+X86::AddrBaseReg); 236 const MachineOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg); 237 const MachineOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp); 238 239 // If we really don't want to print out (rip), don't. 240 bool HasBaseReg = BaseReg.getReg() != 0; 241 if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") && 242 BaseReg.getReg() == X86::RIP) 243 HasBaseReg = false; 244 245 // HasParenPart - True if we will print out the () part of the mem ref. 246 bool HasParenPart = IndexReg.getReg() || HasBaseReg; 247 248 switch (DispSpec.getType()) { 249 default: 250 llvm_unreachable("unknown operand type!"); 251 case MachineOperand::MO_Immediate: { 252 int DispVal = DispSpec.getImm(); 253 if (DispVal || !HasParenPart) 254 O << DispVal; 255 break; 256 } 257 case MachineOperand::MO_GlobalAddress: 258 case MachineOperand::MO_ConstantPoolIndex: 259 printSymbolOperand(P, DispSpec, O); 260 } 261 262 if (Modifier && strcmp(Modifier, "H") == 0) 263 O << "+8"; 264 265 if (HasParenPart) { 266 assert(IndexReg.getReg() != X86::ESP && 267 "X86 doesn't allow scaling by ESP"); 268 269 O << '('; 270 if (HasBaseReg) 271 printOperand(P, MI, Op+X86::AddrBaseReg, O, Modifier); 272 273 if (IndexReg.getReg()) { 274 O << ','; 275 printOperand(P, MI, Op+X86::AddrIndexReg, O, Modifier); 276 unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm(); 277 if (ScaleVal != 1) 278 O << ',' << ScaleVal; 279 } 280 O << ')'; 281 } 282 } 283 284 static void printMemReference(X86AsmPrinter &P, const MachineInstr *MI, 285 unsigned Op, raw_ostream &O, 286 const char *Modifier = nullptr) { 287 assert(isMem(MI, Op) && "Invalid memory reference!"); 288 const MachineOperand &Segment = MI->getOperand(Op+X86::AddrSegmentReg); 289 if (Segment.getReg()) { 290 printOperand(P, MI, Op+X86::AddrSegmentReg, O, Modifier); 291 O << ':'; 292 } 293 printLeaMemReference(P, MI, Op, O, Modifier); 294 } 295 296 static void printIntelMemReference(X86AsmPrinter &P, const MachineInstr *MI, 297 unsigned Op, raw_ostream &O, 298 const char *Modifier = nullptr, 299 unsigned AsmVariant = 1) { 300 const MachineOperand &BaseReg = MI->getOperand(Op+X86::AddrBaseReg); 301 unsigned ScaleVal = MI->getOperand(Op+X86::AddrScaleAmt).getImm(); 302 const MachineOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg); 303 const MachineOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp); 304 const MachineOperand &SegReg = MI->getOperand(Op+X86::AddrSegmentReg); 305 306 // If this has a segment register, print it. 307 if (SegReg.getReg()) { 308 printOperand(P, MI, Op+X86::AddrSegmentReg, O, Modifier, AsmVariant); 309 O << ':'; 310 } 311 312 O << '['; 313 314 bool NeedPlus = false; 315 if (BaseReg.getReg()) { 316 printOperand(P, MI, Op+X86::AddrBaseReg, O, Modifier, AsmVariant); 317 NeedPlus = true; 318 } 319 320 if (IndexReg.getReg()) { 321 if (NeedPlus) O << " + "; 322 if (ScaleVal != 1) 323 O << ScaleVal << '*'; 324 printOperand(P, MI, Op+X86::AddrIndexReg, O, Modifier, AsmVariant); 325 NeedPlus = true; 326 } 327 328 if (!DispSpec.isImm()) { 329 if (NeedPlus) O << " + "; 330 printOperand(P, MI, Op+X86::AddrDisp, O, Modifier, AsmVariant); 331 } else { 332 int64_t DispVal = DispSpec.getImm(); 333 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) { 334 if (NeedPlus) { 335 if (DispVal > 0) 336 O << " + "; 337 else { 338 O << " - "; 339 DispVal = -DispVal; 340 } 341 } 342 O << DispVal; 343 } 344 } 345 O << ']'; 346 } 347 348 static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO, 349 char Mode, raw_ostream &O) { 350 unsigned Reg = MO.getReg(); 351 switch (Mode) { 352 default: return true; // Unknown mode. 353 case 'b': // Print QImode register 354 Reg = getX86SubSuperRegister(Reg, MVT::i8); 355 break; 356 case 'h': // Print QImode high register 357 Reg = getX86SubSuperRegister(Reg, MVT::i8, true); 358 break; 359 case 'w': // Print HImode register 360 Reg = getX86SubSuperRegister(Reg, MVT::i16); 361 break; 362 case 'k': // Print SImode register 363 Reg = getX86SubSuperRegister(Reg, MVT::i32); 364 break; 365 case 'q': 366 // Print 64-bit register names if 64-bit integer registers are available. 367 // Otherwise, print 32-bit register names. 368 MVT::SimpleValueType Ty = P.getSubtarget().is64Bit() ? MVT::i64 : MVT::i32; 369 Reg = getX86SubSuperRegister(Reg, Ty); 370 break; 371 } 372 373 O << '%' << X86ATTInstPrinter::getRegisterName(Reg); 374 return false; 375 } 376 377 /// PrintAsmOperand - Print out an operand for an inline asm expression. 378 /// 379 bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 380 unsigned AsmVariant, 381 const char *ExtraCode, raw_ostream &O) { 382 // Does this asm operand have a single letter operand modifier? 383 if (ExtraCode && ExtraCode[0]) { 384 if (ExtraCode[1] != 0) return true; // Unknown modifier. 385 386 const MachineOperand &MO = MI->getOperand(OpNo); 387 388 switch (ExtraCode[0]) { 389 default: 390 // See if this is a generic print operand 391 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); 392 case 'a': // This is an address. Currently only 'i' and 'r' are expected. 393 switch (MO.getType()) { 394 default: 395 return true; 396 case MachineOperand::MO_Immediate: 397 O << MO.getImm(); 398 return false; 399 case MachineOperand::MO_ConstantPoolIndex: 400 case MachineOperand::MO_JumpTableIndex: 401 case MachineOperand::MO_ExternalSymbol: 402 llvm_unreachable("unexpected operand type!"); 403 case MachineOperand::MO_GlobalAddress: 404 printSymbolOperand(*this, MO, O); 405 if (Subtarget->isPICStyleRIPRel()) 406 O << "(%rip)"; 407 return false; 408 case MachineOperand::MO_Register: 409 O << '('; 410 printOperand(*this, MI, OpNo, O); 411 O << ')'; 412 return false; 413 } 414 415 case 'c': // Don't print "$" before a global var name or constant. 416 switch (MO.getType()) { 417 default: 418 printOperand(*this, MI, OpNo, O); 419 break; 420 case MachineOperand::MO_Immediate: 421 O << MO.getImm(); 422 break; 423 case MachineOperand::MO_ConstantPoolIndex: 424 case MachineOperand::MO_JumpTableIndex: 425 case MachineOperand::MO_ExternalSymbol: 426 llvm_unreachable("unexpected operand type!"); 427 case MachineOperand::MO_GlobalAddress: 428 printSymbolOperand(*this, MO, O); 429 break; 430 } 431 return false; 432 433 case 'A': // Print '*' before a register (it must be a register) 434 if (MO.isReg()) { 435 O << '*'; 436 printOperand(*this, MI, OpNo, O); 437 return false; 438 } 439 return true; 440 441 case 'b': // Print QImode register 442 case 'h': // Print QImode high register 443 case 'w': // Print HImode register 444 case 'k': // Print SImode register 445 case 'q': // Print DImode register 446 if (MO.isReg()) 447 return printAsmMRegister(*this, MO, ExtraCode[0], O); 448 printOperand(*this, MI, OpNo, O); 449 return false; 450 451 case 'P': // This is the operand of a call, treat specially. 452 printPCRelImm(*this, MI, OpNo, O); 453 return false; 454 455 case 'n': // Negate the immediate or print a '-' before the operand. 456 // Note: this is a temporary solution. It should be handled target 457 // independently as part of the 'MC' work. 458 if (MO.isImm()) { 459 O << -MO.getImm(); 460 return false; 461 } 462 O << '-'; 463 } 464 } 465 466 printOperand(*this, MI, OpNo, O, /*Modifier*/ nullptr, AsmVariant); 467 return false; 468 } 469 470 bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 471 unsigned OpNo, unsigned AsmVariant, 472 const char *ExtraCode, 473 raw_ostream &O) { 474 if (AsmVariant) { 475 printIntelMemReference(*this, MI, OpNo, O); 476 return false; 477 } 478 479 if (ExtraCode && ExtraCode[0]) { 480 if (ExtraCode[1] != 0) return true; // Unknown modifier. 481 482 switch (ExtraCode[0]) { 483 default: return true; // Unknown modifier. 484 case 'b': // Print QImode register 485 case 'h': // Print QImode high register 486 case 'w': // Print HImode register 487 case 'k': // Print SImode register 488 case 'q': // Print SImode register 489 // These only apply to registers, ignore on mem. 490 break; 491 case 'H': 492 printMemReference(*this, MI, OpNo, O, "H"); 493 return false; 494 case 'P': // Don't print @PLT, but do print as memory. 495 printMemReference(*this, MI, OpNo, O, "no-rip"); 496 return false; 497 } 498 } 499 printMemReference(*this, MI, OpNo, O); 500 return false; 501 } 502 503 void X86AsmPrinter::EmitStartOfAsmFile(Module &M) { 504 if (Subtarget->isTargetMacho()) 505 OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); 506 507 if (Subtarget->isTargetCOFF()) { 508 // Emit an absolute @feat.00 symbol. This appears to be some kind of 509 // compiler features bitfield read by link.exe. 510 if (!Subtarget->is64Bit()) { 511 MCSymbol *S = MMI->getContext().GetOrCreateSymbol(StringRef("@feat.00")); 512 OutStreamer.BeginCOFFSymbolDef(S); 513 OutStreamer.EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC); 514 OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL); 515 OutStreamer.EndCOFFSymbolDef(); 516 // According to the PE-COFF spec, the LSB of this value marks the object 517 // for "registered SEH". This means that all SEH handler entry points 518 // must be registered in .sxdata. Use of any unregistered handlers will 519 // cause the process to terminate immediately. LLVM does not know how to 520 // register any SEH handlers, so its object files should be safe. 521 S->setAbsolute(); 522 OutStreamer.EmitSymbolAttribute(S, MCSA_Global); 523 OutStreamer.EmitAssignment( 524 S, MCConstantExpr::Create(int64_t(1), MMI->getContext())); 525 } 526 } 527 } 528 529 static void 530 emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, 531 MachineModuleInfoImpl::StubValueTy &MCSym) { 532 // L_foo$stub: 533 OutStreamer.EmitLabel(StubLabel); 534 // .indirect_symbol _foo 535 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); 536 537 if (MCSym.getInt()) 538 // External to current translation unit. 539 OutStreamer.EmitIntValue(0, 4/*size*/); 540 else 541 // Internal to current translation unit. 542 // 543 // When we place the LSDA into the TEXT section, the type info 544 // pointers need to be indirect and pc-rel. We accomplish this by 545 // using NLPs; however, sometimes the types are local to the file. 546 // We need to fill in the value for the NLP in those cases. 547 OutStreamer.EmitValue( 548 MCSymbolRefExpr::Create(MCSym.getPointer(), OutStreamer.getContext()), 549 4 /*size*/); 550 } 551 552 void X86AsmPrinter::GenerateExportDirective(const MCSymbol *Sym, bool IsData) { 553 SmallString<128> Directive; 554 raw_svector_ostream OS(Directive); 555 StringRef Name = Sym->getName(); 556 557 if (Subtarget->isTargetKnownWindowsMSVC()) 558 OS << " /EXPORT:"; 559 else 560 OS << " -export:"; 561 562 if ((Subtarget->isTargetWindowsGNU() || Subtarget->isTargetWindowsCygwin()) && 563 (Name[0] == getDataLayout().getGlobalPrefix())) 564 Name = Name.drop_front(); 565 566 OS << Name; 567 568 if (IsData) { 569 if (Subtarget->isTargetKnownWindowsMSVC()) 570 OS << ",DATA"; 571 else 572 OS << ",data"; 573 } 574 575 OS.flush(); 576 OutStreamer.EmitBytes(Directive); 577 } 578 579 void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { 580 if (Subtarget->isTargetMacho()) { 581 // All darwin targets use mach-o. 582 MachineModuleInfoMachO &MMIMacho = 583 MMI->getObjFileInfo<MachineModuleInfoMachO>(); 584 585 // Output stubs for dynamically-linked functions. 586 MachineModuleInfoMachO::SymbolListTy Stubs; 587 588 Stubs = MMIMacho.GetFnStubList(); 589 if (!Stubs.empty()) { 590 const MCSection *TheSection = 591 OutContext.getMachOSection("__IMPORT", "__jump_table", 592 MachO::S_SYMBOL_STUBS | 593 MachO::S_ATTR_SELF_MODIFYING_CODE | 594 MachO::S_ATTR_PURE_INSTRUCTIONS, 595 5, SectionKind::getMetadata()); 596 OutStreamer.SwitchSection(TheSection); 597 598 for (const auto &Stub : Stubs) { 599 // L_foo$stub: 600 OutStreamer.EmitLabel(Stub.first); 601 // .indirect_symbol _foo 602 OutStreamer.EmitSymbolAttribute(Stub.second.getPointer(), 603 MCSA_IndirectSymbol); 604 // hlt; hlt; hlt; hlt; hlt hlt = 0xf4. 605 const char HltInsts[] = "\xf4\xf4\xf4\xf4\xf4"; 606 OutStreamer.EmitBytes(StringRef(HltInsts, 5)); 607 } 608 609 Stubs.clear(); 610 OutStreamer.AddBlankLine(); 611 } 612 613 // Output stubs for external and common global variables. 614 Stubs = MMIMacho.GetGVStubList(); 615 if (!Stubs.empty()) { 616 const MCSection *TheSection = 617 OutContext.getMachOSection("__IMPORT", "__pointers", 618 MachO::S_NON_LAZY_SYMBOL_POINTERS, 619 SectionKind::getMetadata()); 620 OutStreamer.SwitchSection(TheSection); 621 622 for (auto &Stub : Stubs) 623 emitNonLazySymbolPointer(OutStreamer, Stub.first, Stub.second); 624 625 Stubs.clear(); 626 OutStreamer.AddBlankLine(); 627 } 628 629 Stubs = MMIMacho.GetHiddenGVStubList(); 630 if (!Stubs.empty()) { 631 const MCSection *TheSection = 632 OutContext.getMachOSection("__IMPORT", "__pointers", 633 MachO::S_NON_LAZY_SYMBOL_POINTERS, 634 SectionKind::getMetadata()); 635 OutStreamer.SwitchSection(TheSection); 636 637 for (auto &Stub : Stubs) 638 emitNonLazySymbolPointer(OutStreamer, Stub.first, Stub.second); 639 640 Stubs.clear(); 641 OutStreamer.AddBlankLine(); 642 } 643 644 SM.serializeToStackMapSection(); 645 646 // Funny Darwin hack: This flag tells the linker that no global symbols 647 // contain code that falls through to other global symbols (e.g. the obvious 648 // implementation of multiple entry points). If this doesn't occur, the 649 // linker can safely perform dead code stripping. Since LLVM never 650 // generates code that does this, it is always safe to set. 651 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 652 } 653 654 if (Subtarget->isTargetKnownWindowsMSVC() && MMI->usesVAFloatArgument()) { 655 StringRef SymbolName = Subtarget->is64Bit() ? "_fltused" : "__fltused"; 656 MCSymbol *S = MMI->getContext().GetOrCreateSymbol(SymbolName); 657 OutStreamer.EmitSymbolAttribute(S, MCSA_Global); 658 } 659 660 if (Subtarget->isTargetCOFF()) { 661 // Necessary for dllexport support 662 std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals; 663 664 for (const auto &Function : M) 665 if (Function.hasDLLExportStorageClass()) 666 DLLExportedFns.push_back(getSymbol(&Function)); 667 668 for (const auto &Global : M.globals()) 669 if (Global.hasDLLExportStorageClass()) 670 DLLExportedGlobals.push_back(getSymbol(&Global)); 671 672 for (const auto &Alias : M.aliases()) { 673 if (!Alias.hasDLLExportStorageClass()) 674 continue; 675 676 if (Alias.getType()->getElementType()->isFunctionTy()) 677 DLLExportedFns.push_back(getSymbol(&Alias)); 678 else 679 DLLExportedGlobals.push_back(getSymbol(&Alias)); 680 } 681 682 // Output linker support code for dllexported globals on windows. 683 if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) { 684 const TargetLoweringObjectFileCOFF &TLOFCOFF = 685 static_cast<const TargetLoweringObjectFileCOFF&>(getObjFileLowering()); 686 687 OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection()); 688 689 for (auto & Symbol : DLLExportedGlobals) 690 GenerateExportDirective(Symbol, /*IsData=*/true); 691 for (auto & Symbol : DLLExportedFns) 692 GenerateExportDirective(Symbol, /*IsData=*/false); 693 } 694 } 695 696 if (Subtarget->isTargetELF()) { 697 const TargetLoweringObjectFileELF &TLOFELF = 698 static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); 699 700 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); 701 702 // Output stubs for external and common global variables. 703 MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); 704 if (!Stubs.empty()) { 705 OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); 706 const DataLayout *TD = TM.getDataLayout(); 707 708 for (const auto &Stub : Stubs) { 709 OutStreamer.EmitLabel(Stub.first); 710 OutStreamer.EmitSymbolValue(Stub.second.getPointer(), 711 TD->getPointerSize()); 712 } 713 Stubs.clear(); 714 } 715 } 716 } 717 718 //===----------------------------------------------------------------------===// 719 // Target Registry Stuff 720 //===----------------------------------------------------------------------===// 721 722 // Force static initialization. 723 extern "C" void LLVMInitializeX86AsmPrinter() { 724 RegisterAsmPrinter<X86AsmPrinter> X(TheX86_32Target); 725 RegisterAsmPrinter<X86AsmPrinter> Y(TheX86_64Target); 726 } 727