1//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly ------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to PowerPC assembly language. This printer is
12// the output mechanism used by `llc'.
13//
14// Documentation at http://developer.apple.com/documentation/DeveloperTools/
15// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
16//
17//===----------------------------------------------------------------------===//
18
19#define DEBUG_TYPE "asmprinter"
20#include "PPC.h"
21#include "PPCTargetMachine.h"
22#include "PPCSubtarget.h"
23#include "InstPrinter/PPCInstPrinter.h"
24#include "MCTargetDesc/PPCPredicates.h"
25#include "llvm/Constants.h"
26#include "llvm/DebugInfo.h"
27#include "llvm/DerivedTypes.h"
28#include "llvm/Module.h"
29#include "llvm/Assembly/Writer.h"
30#include "llvm/CodeGen/AsmPrinter.h"
31#include "llvm/CodeGen/MachineFunctionPass.h"
32#include "llvm/CodeGen/MachineInstr.h"
33#include "llvm/CodeGen/MachineInstrBuilder.h"
34#include "llvm/CodeGen/MachineModuleInfoImpls.h"
35#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
36#include "llvm/MC/MCAsmInfo.h"
37#include "llvm/MC/MCContext.h"
38#include "llvm/MC/MCExpr.h"
39#include "llvm/MC/MCInst.h"
40#include "llvm/MC/MCSectionMachO.h"
41#include "llvm/MC/MCStreamer.h"
42#include "llvm/MC/MCSymbol.h"
43#include "llvm/MC/MCSectionELF.h"
44#include "llvm/Target/Mangler.h"
45#include "llvm/Target/TargetRegisterInfo.h"
46#include "llvm/Target/TargetInstrInfo.h"
47#include "llvm/Target/TargetOptions.h"
48#include "llvm/Support/CommandLine.h"
49#include "llvm/Support/Debug.h"
50#include "llvm/Support/MathExtras.h"
51#include "llvm/Support/ErrorHandling.h"
52#include "llvm/Support/TargetRegistry.h"
53#include "llvm/Support/raw_ostream.h"
54#include "llvm/Support/ELF.h"
55#include "llvm/ADT/StringExtras.h"
56#include "llvm/ADT/SmallString.h"
57using namespace llvm;
58
59namespace {
60  class PPCAsmPrinter : public AsmPrinter {
61  protected:
62    DenseMap<MCSymbol*, MCSymbol*> TOC;
63    const PPCSubtarget &Subtarget;
64    uint64_t TOCLabelID;
65  public:
66    explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
67      : AsmPrinter(TM, Streamer),
68        Subtarget(TM.getSubtarget<PPCSubtarget>()), TOCLabelID(0) {}
69
70    virtual const char *getPassName() const {
71      return "PowerPC Assembly Printer";
72    }
73
74
75    virtual void EmitInstruction(const MachineInstr *MI);
76
77    void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
78
79    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
80                         unsigned AsmVariant, const char *ExtraCode,
81                         raw_ostream &O);
82    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
83                               unsigned AsmVariant, const char *ExtraCode,
84                               raw_ostream &O);
85
86    MachineLocation getDebugValueLocation(const MachineInstr *MI) const {
87      MachineLocation Location;
88      assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
89      // Frame address.  Currently handles register +- offset only.
90      if (MI->getOperand(0).isReg() && MI->getOperand(2).isImm())
91        Location.set(MI->getOperand(0).getReg(), MI->getOperand(2).getImm());
92      else {
93        DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
94      }
95      return Location;
96    }
97  };
98
99  /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
100  class PPCLinuxAsmPrinter : public PPCAsmPrinter {
101  public:
102    explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
103      : PPCAsmPrinter(TM, Streamer) {}
104
105    virtual const char *getPassName() const {
106      return "Linux PPC Assembly Printer";
107    }
108
109    bool doFinalization(Module &M);
110
111    virtual void EmitFunctionEntryLabel();
112
113    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.
136static 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
147void 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///
245bool 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
283bool 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///
300void 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    // To avoid name clash check if the name already exists.
372    while (TOCEntry == 0) {
373      if (OutContext.LookupSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
374                                  "C" + Twine(TOCLabelID++)) == 0) {
375        TOCEntry = GetTempSymbol("C", TOCLabelID);
376      }
377    }
378
379    const MCExpr *Exp =
380      MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC_ENTRY,
381                              OutContext);
382    TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
383    OutStreamer.EmitInstruction(TmpInst);
384    return;
385  }
386
387  case PPC::MFCRpseud:
388  case PPC::MFCR8pseud:
389    // Transform: %R3 = MFCRpseud %CR7
390    // Into:      %R3 = MFCR      ;; cr7
391    OutStreamer.AddComment(PPCInstPrinter::
392                           getRegisterName(MI->getOperand(1).getReg()));
393    TmpInst.setOpcode(Subtarget.isPPC64() ? PPC::MFCR8 : PPC::MFCR);
394    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
395    OutStreamer.EmitInstruction(TmpInst);
396    return;
397  case PPC::SYNC:
398    // In Book E sync is called msync, handle this special case here...
399    if (Subtarget.isBookE()) {
400      OutStreamer.EmitRawText(StringRef("\tmsync"));
401      return;
402    }
403  }
404
405  LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
406  OutStreamer.EmitInstruction(TmpInst);
407}
408
409void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
410  if (!Subtarget.isPPC64())  // linux/ppc32 - Normal entry label.
411    return AsmPrinter::EmitFunctionEntryLabel();
412
413  // Emit an official procedure descriptor.
414  const MCSection *Current = OutStreamer.getCurrentSection();
415  const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".opd",
416      ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
417      SectionKind::getReadOnly());
418  OutStreamer.SwitchSection(Section);
419  OutStreamer.EmitLabel(CurrentFnSym);
420  OutStreamer.EmitValueToAlignment(8);
421  MCSymbol *Symbol1 =
422    OutContext.GetOrCreateSymbol(".L." + Twine(CurrentFnSym->getName()));
423  MCSymbol *Symbol2 = OutContext.GetOrCreateSymbol(StringRef(".TOC.@tocbase"));
424  OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol1, OutContext),
425                        8/*size*/, 0/*addrspace*/);
426  OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol2, OutContext),
427                        8/*size*/, 0/*addrspace*/);
428  // Emit a null environment pointer.
429  OutStreamer.EmitIntValue(0, 8 /* size */, 0 /* addrspace */);
430  OutStreamer.SwitchSection(Current);
431
432  MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol(
433                          ".L." + Twine(CurrentFnSym->getName()));
434  OutStreamer.EmitLabel(RealFnSym);
435  CurrentFnSymForSize = RealFnSym;
436}
437
438
439bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
440  const TargetData *TD = TM.getTargetData();
441
442  bool isPPC64 = TD->getPointerSizeInBits() == 64;
443
444  if (isPPC64 && !TOC.empty()) {
445    const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc",
446        ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
447        SectionKind::getReadOnly());
448    OutStreamer.SwitchSection(Section);
449
450    // FIXME: This is nondeterminstic!
451    for (DenseMap<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(),
452         E = TOC.end(); I != E; ++I) {
453      OutStreamer.EmitLabel(I->second);
454      OutStreamer.EmitRawText("\t.tc " + Twine(I->first->getName()) +
455                              "[TC]," + I->first->getName());
456    }
457  }
458
459  return AsmPrinter::doFinalization(M);
460}
461
462/// EmitFunctionBodyEnd - Print the traceback table before the .size
463/// directive.
464///
465void PPCLinuxAsmPrinter::EmitFunctionBodyEnd() {
466  // Only the 64-bit target requires a traceback table.  For now,
467  // we only emit the word of zeroes that GDB requires to find
468  // the end of the function, and zeroes for the eight-byte
469  // mandatory fields.
470  // FIXME: We should fill in the eight-byte mandatory fields as described in
471  // the PPC64 ELF ABI (this is a low-priority item because GDB does not
472  // currently make use of these fields).
473  if (Subtarget.isPPC64()) {
474    OutStreamer.EmitIntValue(0, 4/*size*/);
475    OutStreamer.EmitIntValue(0, 8/*size*/);
476  }
477}
478
479void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) {
480  static const char *const CPUDirectives[] = {
481    "",
482    "ppc",
483    "ppc440",
484    "ppc601",
485    "ppc602",
486    "ppc603",
487    "ppc7400",
488    "ppc750",
489    "ppc970",
490    "ppcA2",
491    "ppce500mc",
492    "ppce5500",
493    "power6",
494    "power7",
495    "ppc64"
496  };
497
498  unsigned Directive = Subtarget.getDarwinDirective();
499  if (Subtarget.hasMFOCRF() && Directive < PPC::DIR_970)
500    Directive = PPC::DIR_970;
501  if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400)
502    Directive = PPC::DIR_7400;
503  if (Subtarget.isPPC64() && Directive < PPC::DIR_64)
504    Directive = PPC::DIR_64;
505  assert(Directive <= PPC::DIR_64 && "Directive out of range.");
506
507  // FIXME: This is a total hack, finish mc'izing the PPC backend.
508  if (OutStreamer.hasRawTextSupport())
509    OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive]));
510
511  // Prime text sections so they are adjacent.  This reduces the likelihood a
512  // large data or debug section causes a branch to exceed 16M limit.
513  const TargetLoweringObjectFileMachO &TLOFMacho =
514    static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
515  OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
516  if (TM.getRelocationModel() == Reloc::PIC_) {
517    OutStreamer.SwitchSection(
518           OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
519                                      MCSectionMachO::S_SYMBOL_STUBS |
520                                      MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
521                                      32, SectionKind::getText()));
522  } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) {
523    OutStreamer.SwitchSection(
524           OutContext.getMachOSection("__TEXT","__symbol_stub1",
525                                      MCSectionMachO::S_SYMBOL_STUBS |
526                                      MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
527                                      16, SectionKind::getText()));
528  }
529  OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
530}
531
532static MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) {
533  // Remove $stub suffix, add $lazy_ptr.
534  SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()-5);
535  TmpStr += "$lazy_ptr";
536  return Ctx.GetOrCreateSymbol(TmpStr.str());
537}
538
539static MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) {
540  // Add $tmp suffix to $stub, yielding $stub$tmp.
541  SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end());
542  TmpStr += "$tmp";
543  return Ctx.GetOrCreateSymbol(TmpStr.str());
544}
545
546void PPCDarwinAsmPrinter::
547EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) {
548  bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64;
549
550  const TargetLoweringObjectFileMachO &TLOFMacho =
551    static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
552
553  // .lazy_symbol_pointer
554  const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection();
555
556  // Output stubs for dynamically-linked functions
557  if (TM.getRelocationModel() == Reloc::PIC_) {
558    const MCSection *StubSection =
559    OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
560                               MCSectionMachO::S_SYMBOL_STUBS |
561                               MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
562                               32, SectionKind::getText());
563    for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
564      OutStreamer.SwitchSection(StubSection);
565      EmitAlignment(4);
566
567      MCSymbol *Stub = Stubs[i].first;
568      MCSymbol *RawSym = Stubs[i].second.getPointer();
569      MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
570      MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext);
571
572      OutStreamer.EmitLabel(Stub);
573      OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
574      // FIXME: MCize this.
575      OutStreamer.EmitRawText(StringRef("\tmflr r0"));
576      OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName()));
577      OutStreamer.EmitLabel(AnonSymbol);
578      OutStreamer.EmitRawText(StringRef("\tmflr r11"));
579      OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+
580                              "-" + AnonSymbol->getName() + ")");
581      OutStreamer.EmitRawText(StringRef("\tmtlr r0"));
582
583      if (isPPC64)
584        OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) +
585                                "-" + AnonSymbol->getName() + ")(r11)");
586      else
587        OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) +
588                                "-" + AnonSymbol->getName() + ")(r11)");
589      OutStreamer.EmitRawText(StringRef("\tmtctr r12"));
590      OutStreamer.EmitRawText(StringRef("\tbctr"));
591
592      OutStreamer.SwitchSection(LSPSection);
593      OutStreamer.EmitLabel(LazyPtr);
594      OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
595
596      if (isPPC64)
597        OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper"));
598      else
599        OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper"));
600    }
601    OutStreamer.AddBlankLine();
602    return;
603  }
604
605  const MCSection *StubSection =
606    OutContext.getMachOSection("__TEXT","__symbol_stub1",
607                               MCSectionMachO::S_SYMBOL_STUBS |
608                               MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
609                               16, SectionKind::getText());
610  for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
611    MCSymbol *Stub = Stubs[i].first;
612    MCSymbol *RawSym = Stubs[i].second.getPointer();
613    MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
614
615    OutStreamer.SwitchSection(StubSection);
616    EmitAlignment(4);
617    OutStreamer.EmitLabel(Stub);
618    OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
619    OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")");
620    if (isPPC64)
621      OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) +
622                              ")(r11)");
623    else
624      OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) +
625                              ")(r11)");
626    OutStreamer.EmitRawText(StringRef("\tmtctr r12"));
627    OutStreamer.EmitRawText(StringRef("\tbctr"));
628    OutStreamer.SwitchSection(LSPSection);
629    OutStreamer.EmitLabel(LazyPtr);
630    OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
631
632    if (isPPC64)
633      OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper"));
634    else
635      OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper"));
636  }
637
638  OutStreamer.AddBlankLine();
639}
640
641
642bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
643  bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64;
644
645  // Darwin/PPC always uses mach-o.
646  const TargetLoweringObjectFileMachO &TLOFMacho =
647    static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
648  MachineModuleInfoMachO &MMIMacho =
649    MMI->getObjFileInfo<MachineModuleInfoMachO>();
650
651  MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList();
652  if (!Stubs.empty())
653    EmitFunctionStubs(Stubs);
654
655  if (MAI->doesSupportExceptionHandling() && MMI) {
656    // Add the (possibly multiple) personalities to the set of global values.
657    // Only referenced functions get into the Personalities list.
658    const std::vector<const Function*> &Personalities = MMI->getPersonalities();
659    for (std::vector<const Function*>::const_iterator I = Personalities.begin(),
660         E = Personalities.end(); I != E; ++I) {
661      if (*I) {
662        MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr");
663        MachineModuleInfoImpl::StubValueTy &StubSym =
664          MMIMacho.getGVStubEntry(NLPSym);
665        StubSym = MachineModuleInfoImpl::StubValueTy(Mang->getSymbol(*I), true);
666      }
667    }
668  }
669
670  // Output stubs for dynamically-linked functions.
671  Stubs = MMIMacho.GetGVStubList();
672
673  // Output macho stubs for external and common global variables.
674  if (!Stubs.empty()) {
675    // Switch with ".non_lazy_symbol_pointer" directive.
676    OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
677    EmitAlignment(isPPC64 ? 3 : 2);
678
679    for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
680      // L_foo$stub:
681      OutStreamer.EmitLabel(Stubs[i].first);
682      //   .indirect_symbol _foo
683      MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
684      OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);
685
686      if (MCSym.getInt())
687        // External to current translation unit.
688        OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/);
689      else
690        // Internal to current translation unit.
691        //
692        // When we place the LSDA into the TEXT section, the type info pointers
693        // need to be indirect and pc-rel. We accomplish this by using NLPs.
694        // However, sometimes the types are local to the file. So we need to
695        // fill in the value for the NLP in those cases.
696        OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
697                                                      OutContext),
698                              isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/);
699    }
700
701    Stubs.clear();
702    OutStreamer.AddBlankLine();
703  }
704
705  Stubs = MMIMacho.GetHiddenGVStubList();
706  if (!Stubs.empty()) {
707    OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
708    EmitAlignment(isPPC64 ? 3 : 2);
709
710    for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
711      // L_foo$stub:
712      OutStreamer.EmitLabel(Stubs[i].first);
713      //   .long _foo
714      OutStreamer.EmitValue(MCSymbolRefExpr::
715                            Create(Stubs[i].second.getPointer(),
716                                   OutContext),
717                            isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/);
718    }
719
720    Stubs.clear();
721    OutStreamer.AddBlankLine();
722  }
723
724  // Funny Darwin hack: This flag tells the linker that no global symbols
725  // contain code that falls through to other global symbols (e.g. the obvious
726  // implementation of multiple entry points).  If this doesn't occur, the
727  // linker can safely perform dead code stripping.  Since LLVM never generates
728  // code that does this, it is always safe to set.
729  OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
730
731  return AsmPrinter::doFinalization(M);
732}
733
734/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
735/// for a MachineFunction to the given output stream, in a format that the
736/// Darwin assembler can deal with.
737///
738static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm,
739                                           MCStreamer &Streamer) {
740  const PPCSubtarget *Subtarget = &tm.getSubtarget<PPCSubtarget>();
741
742  if (Subtarget->isDarwin())
743    return new PPCDarwinAsmPrinter(tm, Streamer);
744  return new PPCLinuxAsmPrinter(tm, Streamer);
745}
746
747// Force static initialization.
748extern "C" void LLVMInitializePowerPCAsmPrinter() {
749  TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass);
750  TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass);
751}
752