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