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