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