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