PPCAsmPrinter.cpp revision ed9e442cf098663ce213cb16778b44be466b441f
1//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC 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 PowerPC assembly language. This printer is 12// the output mechanism used by `llc'. 13// 14// Documentation at http://developer.apple.com/documentation/DeveloperTools/ 15// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html 16// 17//===----------------------------------------------------------------------===// 18 19#define DEBUG_TYPE "asmprinter" 20#include "PPC.h" 21#include "PPCTargetMachine.h" 22#include "PPCSubtarget.h" 23#include "InstPrinter/PPCInstPrinter.h" 24#include "MCTargetDesc/PPCPredicates.h" 25#include "llvm/Constants.h" 26#include "llvm/DebugInfo.h" 27#include "llvm/DerivedTypes.h" 28#include "llvm/Module.h" 29#include "llvm/Assembly/Writer.h" 30#include "llvm/CodeGen/AsmPrinter.h" 31#include "llvm/CodeGen/MachineFunctionPass.h" 32#include "llvm/CodeGen/MachineInstr.h" 33#include "llvm/CodeGen/MachineInstrBuilder.h" 34#include "llvm/CodeGen/MachineModuleInfoImpls.h" 35#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 36#include "llvm/MC/MCAsmInfo.h" 37#include "llvm/MC/MCContext.h" 38#include "llvm/MC/MCExpr.h" 39#include "llvm/MC/MCInst.h" 40#include "llvm/MC/MCInstBuilder.h" 41#include "llvm/MC/MCSectionMachO.h" 42#include "llvm/MC/MCStreamer.h" 43#include "llvm/MC/MCSymbol.h" 44#include "llvm/MC/MCSectionELF.h" 45#include "llvm/Target/Mangler.h" 46#include "llvm/Target/TargetRegisterInfo.h" 47#include "llvm/Target/TargetInstrInfo.h" 48#include "llvm/Target/TargetOptions.h" 49#include "llvm/Support/CommandLine.h" 50#include "llvm/Support/Debug.h" 51#include "llvm/Support/MathExtras.h" 52#include "llvm/Support/ErrorHandling.h" 53#include "llvm/Support/TargetRegistry.h" 54#include "llvm/Support/raw_ostream.h" 55#include "llvm/Support/ELF.h" 56#include "llvm/ADT/StringExtras.h" 57#include "llvm/ADT/SmallString.h" 58#include "llvm/ADT/MapVector.h" 59using namespace llvm; 60 61namespace { 62 class PPCAsmPrinter : public AsmPrinter { 63 protected: 64 MapVector<MCSymbol*, MCSymbol*> TOC; 65 const PPCSubtarget &Subtarget; 66 uint64_t TOCLabelID; 67 public: 68 explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 69 : AsmPrinter(TM, Streamer), 70 Subtarget(TM.getSubtarget<PPCSubtarget>()), TOCLabelID(0) {} 71 72 virtual const char *getPassName() const { 73 return "PowerPC Assembly Printer"; 74 } 75 76 77 virtual void EmitInstruction(const MachineInstr *MI); 78 79 void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); 80 81 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 82 unsigned AsmVariant, const char *ExtraCode, 83 raw_ostream &O); 84 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 85 unsigned AsmVariant, const char *ExtraCode, 86 raw_ostream &O); 87 88 MachineLocation getDebugValueLocation(const MachineInstr *MI) const { 89 MachineLocation Location; 90 assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); 91 // Frame address. Currently handles register +- offset only. 92 if (MI->getOperand(0).isReg() && MI->getOperand(2).isImm()) 93 Location.set(MI->getOperand(0).getReg(), MI->getOperand(2).getImm()); 94 else { 95 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); 96 } 97 return Location; 98 } 99 }; 100 101 /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux 102 class PPCLinuxAsmPrinter : public PPCAsmPrinter { 103 public: 104 explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 105 : PPCAsmPrinter(TM, Streamer) {} 106 107 virtual const char *getPassName() const { 108 return "Linux PPC Assembly Printer"; 109 } 110 111 bool doFinalization(Module &M); 112 113 virtual void EmitFunctionEntryLabel(); 114 115 void EmitFunctionBodyEnd(); 116 }; 117 118 /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac 119 /// OS X 120 class PPCDarwinAsmPrinter : public PPCAsmPrinter { 121 public: 122 explicit PPCDarwinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 123 : PPCAsmPrinter(TM, Streamer) {} 124 125 virtual const char *getPassName() const { 126 return "Darwin PPC Assembly Printer"; 127 } 128 129 bool doFinalization(Module &M); 130 void EmitStartOfAsmFile(Module &M); 131 132 void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs); 133 }; 134} // end of anonymous namespace 135 136/// stripRegisterPrefix - This method strips the character prefix from a 137/// register name so that only the number is left. Used by for linux asm. 138static const char *stripRegisterPrefix(const char *RegName) { 139 switch (RegName[0]) { 140 case 'r': 141 case 'f': 142 case 'v': return RegName + 1; 143 case 'c': if (RegName[1] == 'r') return RegName + 2; 144 } 145 146 return RegName; 147} 148 149void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, 150 raw_ostream &O) { 151 const MachineOperand &MO = MI->getOperand(OpNo); 152 153 switch (MO.getType()) { 154 case MachineOperand::MO_Register: { 155 const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg()); 156 // Linux assembler (Others?) does not take register mnemonics. 157 // FIXME - What about special registers used in mfspr/mtspr? 158 if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); 159 O << RegName; 160 return; 161 } 162 case MachineOperand::MO_Immediate: 163 O << MO.getImm(); 164 return; 165 166 case MachineOperand::MO_MachineBasicBlock: 167 O << *MO.getMBB()->getSymbol(); 168 return; 169 case MachineOperand::MO_JumpTableIndex: 170 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 171 << '_' << MO.getIndex(); 172 // FIXME: PIC relocation model 173 return; 174 case MachineOperand::MO_ConstantPoolIndex: 175 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() 176 << '_' << MO.getIndex(); 177 return; 178 case MachineOperand::MO_BlockAddress: 179 O << *GetBlockAddressSymbol(MO.getBlockAddress()); 180 return; 181 case MachineOperand::MO_ExternalSymbol: { 182 // Computing the address of an external symbol, not calling it. 183 if (TM.getRelocationModel() == Reloc::Static) { 184 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 185 return; 186 } 187 188 MCSymbol *NLPSym = 189 OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+ 190 MO.getSymbolName()+"$non_lazy_ptr"); 191 MachineModuleInfoImpl::StubValueTy &StubSym = 192 MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(NLPSym); 193 if (StubSym.getPointer() == 0) 194 StubSym = MachineModuleInfoImpl:: 195 StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true); 196 197 O << *NLPSym; 198 return; 199 } 200 case MachineOperand::MO_GlobalAddress: { 201 // Computing the address of a global symbol, not calling it. 202 const GlobalValue *GV = MO.getGlobal(); 203 MCSymbol *SymToPrint; 204 205 // External or weakly linked global variables need non-lazily-resolved stubs 206 if (TM.getRelocationModel() != Reloc::Static && 207 (GV->isDeclaration() || GV->isWeakForLinker())) { 208 if (!GV->hasHiddenVisibility()) { 209 SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 210 MachineModuleInfoImpl::StubValueTy &StubSym = 211 MMI->getObjFileInfo<MachineModuleInfoMachO>() 212 .getGVStubEntry(SymToPrint); 213 if (StubSym.getPointer() == 0) 214 StubSym = MachineModuleInfoImpl:: 215 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); 216 } else if (GV->isDeclaration() || GV->hasCommonLinkage() || 217 GV->hasAvailableExternallyLinkage()) { 218 SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 219 220 MachineModuleInfoImpl::StubValueTy &StubSym = 221 MMI->getObjFileInfo<MachineModuleInfoMachO>(). 222 getHiddenGVStubEntry(SymToPrint); 223 if (StubSym.getPointer() == 0) 224 StubSym = MachineModuleInfoImpl:: 225 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); 226 } else { 227 SymToPrint = Mang->getSymbol(GV); 228 } 229 } else { 230 SymToPrint = Mang->getSymbol(GV); 231 } 232 233 O << *SymToPrint; 234 235 printOffset(MO.getOffset(), O); 236 return; 237 } 238 239 default: 240 O << "<unknown operand type: " << MO.getType() << ">"; 241 return; 242 } 243} 244 245/// PrintAsmOperand - Print out an operand for an inline asm expression. 246/// 247bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 248 unsigned AsmVariant, 249 const char *ExtraCode, raw_ostream &O) { 250 // Does this asm operand have a single letter operand modifier? 251 if (ExtraCode && ExtraCode[0]) { 252 if (ExtraCode[1] != 0) return true; // Unknown modifier. 253 254 switch (ExtraCode[0]) { 255 default: 256 // See if this is a generic print operand 257 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); 258 case 'c': // Don't print "$" before a global var name or constant. 259 break; // PPC never has a prefix. 260 case 'L': // Write second word of DImode reference. 261 // Verify that this operand has two consecutive registers. 262 if (!MI->getOperand(OpNo).isReg() || 263 OpNo+1 == MI->getNumOperands() || 264 !MI->getOperand(OpNo+1).isReg()) 265 return true; 266 ++OpNo; // Return the high-part. 267 break; 268 case 'I': 269 // Write 'i' if an integer constant, otherwise nothing. Used to print 270 // addi vs add, etc. 271 if (MI->getOperand(OpNo).isImm()) 272 O << "i"; 273 return false; 274 } 275 } 276 277 printOperand(MI, OpNo, O); 278 return false; 279} 280 281// At the moment, all inline asm memory operands are a single register. 282// In any case, the output of this routine should always be just one 283// assembler operand. 284 285bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 286 unsigned AsmVariant, 287 const char *ExtraCode, 288 raw_ostream &O) { 289 if (ExtraCode && ExtraCode[0]) { 290 if (ExtraCode[1] != 0) return true; // Unknown modifier. 291 292 switch (ExtraCode[0]) { 293 default: return true; // Unknown modifier. 294 case 'y': // A memory reference for an X-form instruction 295 { 296 const char *RegName = "r0"; 297 if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); 298 O << RegName << ", "; 299 printOperand(MI, OpNo, O); 300 return false; 301 } 302 } 303 } 304 305 assert(MI->getOperand(OpNo).isReg()); 306 O << "0("; 307 printOperand(MI, OpNo, O); 308 O << ")"; 309 return false; 310} 311 312 313/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to 314/// the current output stream. 315/// 316void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { 317 MCInst TmpInst; 318 319 // Lower multi-instruction pseudo operations. 320 switch (MI->getOpcode()) { 321 default: break; 322 case TargetOpcode::DBG_VALUE: { 323 if (!isVerbose() || !OutStreamer.hasRawTextSupport()) return; 324 325 SmallString<32> Str; 326 raw_svector_ostream O(Str); 327 unsigned NOps = MI->getNumOperands(); 328 assert(NOps==4); 329 O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; 330 // cast away const; DIetc do not take const operands for some reason. 331 DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata())); 332 O << V.getName(); 333 O << " <- "; 334 // Frame address. Currently handles register +- offset only. 335 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); 336 O << '['; printOperand(MI, 0, O); O << '+'; printOperand(MI, 1, O); 337 O << ']'; 338 O << "+"; 339 printOperand(MI, NOps-2, O); 340 OutStreamer.EmitRawText(O.str()); 341 return; 342 } 343 344 case PPC::MovePCtoLR: 345 case PPC::MovePCtoLR8: { 346 // Transform %LR = MovePCtoLR 347 // Into this, where the label is the PIC base: 348 // bl L1$pb 349 // L1$pb: 350 MCSymbol *PICBase = MF->getPICBaseSymbol(); 351 352 // Emit the 'bl'. 353 OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL_Darwin) // Darwin vs SVR4 doesn't matter here. 354 // FIXME: We would like an efficient form for this, so we don't have to do 355 // a lot of extra uniquing. 356 .addExpr(MCSymbolRefExpr::Create(PICBase, OutContext))); 357 358 // Emit the label. 359 OutStreamer.EmitLabel(PICBase); 360 return; 361 } 362 case PPC::LDtocJTI: 363 case PPC::LDtocCPT: 364 case PPC::LDtoc: { 365 // Transform %X3 = LDtoc <ga:@min1>, %X2 366 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); 367 368 // Change the opcode to LD, and the global address operand to be a 369 // reference to the TOC entry we will synthesize later. 370 TmpInst.setOpcode(PPC::LD); 371 const MachineOperand &MO = MI->getOperand(1); 372 373 // Map symbol -> label of TOC entry 374 assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); 375 MCSymbol *MOSymbol = 0; 376 if (MO.isGlobal()) 377 MOSymbol = Mang->getSymbol(MO.getGlobal()); 378 else if (MO.isCPI()) 379 MOSymbol = GetCPISymbol(MO.getIndex()); 380 else if (MO.isJTI()) 381 MOSymbol = GetJTISymbol(MO.getIndex()); 382 MCSymbol *&TOCEntry = TOC[MOSymbol]; 383 // To avoid name clash check if the name already exists. 384 while (TOCEntry == 0) { 385 if (OutContext.LookupSymbol(Twine(MAI->getPrivateGlobalPrefix()) + 386 "C" + Twine(TOCLabelID++)) == 0) { 387 TOCEntry = GetTempSymbol("C", TOCLabelID); 388 } 389 } 390 391 const MCExpr *Exp = 392 MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC_ENTRY, 393 OutContext); 394 TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); 395 OutStreamer.EmitInstruction(TmpInst); 396 return; 397 } 398 399 case PPC::MFCRpseud: 400 case PPC::MFCR8pseud: 401 // Transform: %R3 = MFCRpseud %CR7 402 // Into: %R3 = MFCR ;; cr7 403 OutStreamer.AddComment(PPCInstPrinter:: 404 getRegisterName(MI->getOperand(1).getReg())); 405 OutStreamer.EmitInstruction(MCInstBuilder(Subtarget.isPPC64() ? PPC::MFCR8 : PPC::MFCR) 406 .addReg(MI->getOperand(0).getReg())); 407 return; 408 case PPC::SYNC: 409 // In Book E sync is called msync, handle this special case here... 410 if (Subtarget.isBookE()) { 411 OutStreamer.EmitRawText(StringRef("\tmsync")); 412 return; 413 } 414 } 415 416 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); 417 OutStreamer.EmitInstruction(TmpInst); 418} 419 420void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { 421 if (!Subtarget.isPPC64()) // linux/ppc32 - Normal entry label. 422 return AsmPrinter::EmitFunctionEntryLabel(); 423 424 // Emit an official procedure descriptor. 425 const MCSection *Current = OutStreamer.getCurrentSection(); 426 const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".opd", 427 ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, 428 SectionKind::getReadOnly()); 429 OutStreamer.SwitchSection(Section); 430 OutStreamer.EmitLabel(CurrentFnSym); 431 OutStreamer.EmitValueToAlignment(8); 432 MCSymbol *Symbol1 = 433 OutContext.GetOrCreateSymbol(".L." + Twine(CurrentFnSym->getName())); 434 // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function 435 // entry point. 436 OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol1, OutContext), 437 8/*size*/, 0/*addrspace*/); 438 MCSymbol *Symbol2 = OutContext.GetOrCreateSymbol(StringRef(".TOC.")); 439 // Generates a R_PPC64_TOC relocation for TOC base insertion. 440 OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol2, 441 MCSymbolRefExpr::VK_PPC_TOC, OutContext), 442 8/*size*/, 0/*addrspace*/); 443 // Emit a null environment pointer. 444 OutStreamer.EmitIntValue(0, 8 /* size */, 0 /* addrspace */); 445 OutStreamer.SwitchSection(Current); 446 447 MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol( 448 ".L." + Twine(CurrentFnSym->getName())); 449 OutStreamer.EmitLabel(RealFnSym); 450 CurrentFnSymForSize = RealFnSym; 451} 452 453 454bool PPCLinuxAsmPrinter::doFinalization(Module &M) { 455 const DataLayout *TD = TM.getDataLayout(); 456 457 bool isPPC64 = TD->getPointerSizeInBits() == 64; 458 459 if (isPPC64 && !TOC.empty()) { 460 const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc", 461 ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC, 462 SectionKind::getReadOnly()); 463 OutStreamer.SwitchSection(Section); 464 465 for (MapVector<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(), 466 E = TOC.end(); I != E; ++I) { 467 OutStreamer.EmitLabel(I->second); 468 MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName()); 469 OutStreamer.EmitTCEntry(*S); 470 } 471 } 472 473 return AsmPrinter::doFinalization(M); 474} 475 476/// EmitFunctionBodyEnd - Print the traceback table before the .size 477/// directive. 478/// 479void PPCLinuxAsmPrinter::EmitFunctionBodyEnd() { 480 // Only the 64-bit target requires a traceback table. For now, 481 // we only emit the word of zeroes that GDB requires to find 482 // the end of the function, and zeroes for the eight-byte 483 // mandatory fields. 484 // FIXME: We should fill in the eight-byte mandatory fields as described in 485 // the PPC64 ELF ABI (this is a low-priority item because GDB does not 486 // currently make use of these fields). 487 if (Subtarget.isPPC64()) { 488 OutStreamer.EmitIntValue(0, 4/*size*/); 489 OutStreamer.EmitIntValue(0, 8/*size*/); 490 } 491} 492 493void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { 494 static const char *const CPUDirectives[] = { 495 "", 496 "ppc", 497 "ppc440", 498 "ppc601", 499 "ppc602", 500 "ppc603", 501 "ppc7400", 502 "ppc750", 503 "ppc970", 504 "ppcA2", 505 "ppce500mc", 506 "ppce5500", 507 "power6", 508 "power7", 509 "ppc64" 510 }; 511 512 unsigned Directive = Subtarget.getDarwinDirective(); 513 if (Subtarget.hasMFOCRF() && Directive < PPC::DIR_970) 514 Directive = PPC::DIR_970; 515 if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400) 516 Directive = PPC::DIR_7400; 517 if (Subtarget.isPPC64() && Directive < PPC::DIR_64) 518 Directive = PPC::DIR_64; 519 assert(Directive <= PPC::DIR_64 && "Directive out of range."); 520 521 // FIXME: This is a total hack, finish mc'izing the PPC backend. 522 if (OutStreamer.hasRawTextSupport()) 523 OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive])); 524 525 // Prime text sections so they are adjacent. This reduces the likelihood a 526 // large data or debug section causes a branch to exceed 16M limit. 527 const TargetLoweringObjectFileMachO &TLOFMacho = 528 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 529 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); 530 if (TM.getRelocationModel() == Reloc::PIC_) { 531 OutStreamer.SwitchSection( 532 OutContext.getMachOSection("__TEXT", "__picsymbolstub1", 533 MCSectionMachO::S_SYMBOL_STUBS | 534 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 535 32, SectionKind::getText())); 536 } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { 537 OutStreamer.SwitchSection( 538 OutContext.getMachOSection("__TEXT","__symbol_stub1", 539 MCSectionMachO::S_SYMBOL_STUBS | 540 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 541 16, SectionKind::getText())); 542 } 543 OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); 544} 545 546static MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) { 547 // Remove $stub suffix, add $lazy_ptr. 548 StringRef NoStub = Sym->getName().substr(0, Sym->getName().size()-5); 549 return Ctx.GetOrCreateSymbol(NoStub + "$lazy_ptr"); 550} 551 552static MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) { 553 // Add $tmp suffix to $stub, yielding $stub$tmp. 554 return Ctx.GetOrCreateSymbol(Sym->getName() + "$tmp"); 555} 556 557void PPCDarwinAsmPrinter:: 558EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { 559 bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64; 560 561 const TargetLoweringObjectFileMachO &TLOFMacho = 562 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 563 564 // .lazy_symbol_pointer 565 const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection(); 566 567 // Output stubs for dynamically-linked functions 568 if (TM.getRelocationModel() == Reloc::PIC_) { 569 const MCSection *StubSection = 570 OutContext.getMachOSection("__TEXT", "__picsymbolstub1", 571 MCSectionMachO::S_SYMBOL_STUBS | 572 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 573 32, SectionKind::getText()); 574 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 575 OutStreamer.SwitchSection(StubSection); 576 EmitAlignment(4); 577 578 MCSymbol *Stub = Stubs[i].first; 579 MCSymbol *RawSym = Stubs[i].second.getPointer(); 580 MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); 581 MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); 582 583 OutStreamer.EmitLabel(Stub); 584 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 585 586 // mflr r0 587 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R0)); 588 // FIXME: MCize this. 589 OutStreamer.EmitRawText("\tbcl 20, 31, " + Twine(AnonSymbol->getName())); 590 OutStreamer.EmitLabel(AnonSymbol); 591 // mflr r11 592 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R11)); 593 // addis r11, r11, ha16(LazyPtr - AnonSymbol) 594 const MCExpr *Sub = 595 MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(LazyPtr, OutContext), 596 MCSymbolRefExpr::Create(AnonSymbol, OutContext), 597 OutContext); 598 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS) 599 .addReg(PPC::R11) 600 .addReg(PPC::R11) 601 .addExpr(Sub)); 602 // mtlr r0 603 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTLR).addReg(PPC::R0)); 604 605 // ldu r12, lo16(LazyPtr - AnonSymbol)(r11) 606 // lwzu r12, lo16(LazyPtr - AnonSymbol)(r11) 607 OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) 608 .addReg(PPC::R12) 609 .addExpr(Sub).addExpr(Sub) 610 .addReg(PPC::R11)); 611 // mtctr r12 612 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); 613 // bctr 614 OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR)); 615 616 OutStreamer.SwitchSection(LSPSection); 617 OutStreamer.EmitLabel(LazyPtr); 618 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 619 620 MCSymbol *DyldStubBindingHelper = 621 OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper")); 622 if (isPPC64) { 623 // .quad dyld_stub_binding_helper 624 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8); 625 } else { 626 // .long dyld_stub_binding_helper 627 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4); 628 } 629 } 630 OutStreamer.AddBlankLine(); 631 return; 632 } 633 634 const MCSection *StubSection = 635 OutContext.getMachOSection("__TEXT","__symbol_stub1", 636 MCSectionMachO::S_SYMBOL_STUBS | 637 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 638 16, SectionKind::getText()); 639 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 640 MCSymbol *Stub = Stubs[i].first; 641 MCSymbol *RawSym = Stubs[i].second.getPointer(); 642 MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); 643 644 OutStreamer.SwitchSection(StubSection); 645 EmitAlignment(4); 646 OutStreamer.EmitLabel(Stub); 647 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 648 // lis r11, ha16(LazyPtr) 649 const MCExpr *LazyPtrHa16 = 650 MCSymbolRefExpr::Create(LazyPtr, MCSymbolRefExpr::VK_PPC_DARWIN_HA16, 651 OutContext); 652 OutStreamer.EmitInstruction(MCInstBuilder(PPC::LIS) 653 .addReg(PPC::R11) 654 .addExpr(LazyPtrHa16)); 655 656 const MCExpr *LazyPtrLo16 = 657 MCSymbolRefExpr::Create(LazyPtr, MCSymbolRefExpr::VK_PPC_DARWIN_LO16, 658 OutContext); 659 // ldu r12, lo16(LazyPtr)(r11) 660 // lwzu r12, lo16(LazyPtr)(r11) 661 OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU) 662 .addReg(PPC::R12) 663 .addExpr(LazyPtrLo16).addExpr(LazyPtrLo16) 664 .addReg(PPC::R11)); 665 666 // mtctr r12 667 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12)); 668 // bctr 669 OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR)); 670 671 OutStreamer.SwitchSection(LSPSection); 672 OutStreamer.EmitLabel(LazyPtr); 673 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 674 675 MCSymbol *DyldStubBindingHelper = 676 OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper")); 677 if (isPPC64) { 678 // .quad dyld_stub_binding_helper 679 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8); 680 } else { 681 // .long dyld_stub_binding_helper 682 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4); 683 } 684 } 685 686 OutStreamer.AddBlankLine(); 687} 688 689 690bool PPCDarwinAsmPrinter::doFinalization(Module &M) { 691 bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64; 692 693 // Darwin/PPC always uses mach-o. 694 const TargetLoweringObjectFileMachO &TLOFMacho = 695 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 696 MachineModuleInfoMachO &MMIMacho = 697 MMI->getObjFileInfo<MachineModuleInfoMachO>(); 698 699 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList(); 700 if (!Stubs.empty()) 701 EmitFunctionStubs(Stubs); 702 703 if (MAI->doesSupportExceptionHandling() && MMI) { 704 // Add the (possibly multiple) personalities to the set of global values. 705 // Only referenced functions get into the Personalities list. 706 const std::vector<const Function*> &Personalities = MMI->getPersonalities(); 707 for (std::vector<const Function*>::const_iterator I = Personalities.begin(), 708 E = Personalities.end(); I != E; ++I) { 709 if (*I) { 710 MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr"); 711 MachineModuleInfoImpl::StubValueTy &StubSym = 712 MMIMacho.getGVStubEntry(NLPSym); 713 StubSym = MachineModuleInfoImpl::StubValueTy(Mang->getSymbol(*I), true); 714 } 715 } 716 } 717 718 // Output stubs for dynamically-linked functions. 719 Stubs = MMIMacho.GetGVStubList(); 720 721 // Output macho stubs for external and common global variables. 722 if (!Stubs.empty()) { 723 // Switch with ".non_lazy_symbol_pointer" directive. 724 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); 725 EmitAlignment(isPPC64 ? 3 : 2); 726 727 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 728 // L_foo$stub: 729 OutStreamer.EmitLabel(Stubs[i].first); 730 // .indirect_symbol _foo 731 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 732 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); 733 734 if (MCSym.getInt()) 735 // External to current translation unit. 736 OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); 737 else 738 // Internal to current translation unit. 739 // 740 // When we place the LSDA into the TEXT section, the type info pointers 741 // need to be indirect and pc-rel. We accomplish this by using NLPs. 742 // However, sometimes the types are local to the file. So we need to 743 // fill in the value for the NLP in those cases. 744 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), 745 OutContext), 746 isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); 747 } 748 749 Stubs.clear(); 750 OutStreamer.AddBlankLine(); 751 } 752 753 Stubs = MMIMacho.GetHiddenGVStubList(); 754 if (!Stubs.empty()) { 755 OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 756 EmitAlignment(isPPC64 ? 3 : 2); 757 758 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 759 // L_foo$stub: 760 OutStreamer.EmitLabel(Stubs[i].first); 761 // .long _foo 762 OutStreamer.EmitValue(MCSymbolRefExpr:: 763 Create(Stubs[i].second.getPointer(), 764 OutContext), 765 isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); 766 } 767 768 Stubs.clear(); 769 OutStreamer.AddBlankLine(); 770 } 771 772 // Funny Darwin hack: This flag tells the linker that no global symbols 773 // contain code that falls through to other global symbols (e.g. the obvious 774 // implementation of multiple entry points). If this doesn't occur, the 775 // linker can safely perform dead code stripping. Since LLVM never generates 776 // code that does this, it is always safe to set. 777 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 778 779 return AsmPrinter::doFinalization(M); 780} 781 782/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code 783/// for a MachineFunction to the given output stream, in a format that the 784/// Darwin assembler can deal with. 785/// 786static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, 787 MCStreamer &Streamer) { 788 const PPCSubtarget *Subtarget = &tm.getSubtarget<PPCSubtarget>(); 789 790 if (Subtarget->isDarwin()) 791 return new PPCDarwinAsmPrinter(tm, Streamer); 792 return new PPCLinuxAsmPrinter(tm, Streamer); 793} 794 795// Force static initialization. 796extern "C" void LLVMInitializePowerPCAsmPrinter() { 797 TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass); 798 TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass); 799} 800