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