Revert the majority of the next patch in the address space series:
[oota-llvm.git] / lib / Target / PowerPC / PPCAsmPrinter.cpp
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     // 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
409 void 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   // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function
424   // entry point.
425   OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol1, OutContext),
426                         8/*size*/, 0/*addrspace*/);
427   MCSymbol *Symbol2 = OutContext.GetOrCreateSymbol(StringRef(".TOC."));
428   // Generates a R_PPC64_TOC relocation for TOC base insertion.
429   OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol2,
430                         MCSymbolRefExpr::VK_PPC_TOC, OutContext),
431                         8/*size*/, 0/*addrspace*/);
432   // Emit a null environment pointer.
433   OutStreamer.EmitIntValue(0, 8 /* size */, 0 /* addrspace */);
434   OutStreamer.SwitchSection(Current);
435
436   MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol(
437                           ".L." + Twine(CurrentFnSym->getName()));
438   OutStreamer.EmitLabel(RealFnSym);
439   CurrentFnSymForSize = RealFnSym;
440 }
441
442
443 bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
444   const DataLayout *TD = TM.getDataLayout();
445
446   bool isPPC64 = TD->getPointerSizeInBits() == 64;
447
448   if (isPPC64 && !TOC.empty()) {
449     const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc",
450         ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
451         SectionKind::getReadOnly());
452     OutStreamer.SwitchSection(Section);
453
454     // FIXME: This is nondeterminstic!
455     for (DenseMap<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(),
456          E = TOC.end(); I != E; ++I) {
457       OutStreamer.EmitLabel(I->second);
458       MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName());
459       OutStreamer.EmitTCEntry(*S);
460     }
461   }
462
463   return AsmPrinter::doFinalization(M);
464 }
465
466 /// EmitFunctionBodyEnd - Print the traceback table before the .size
467 /// directive.
468 ///
469 void PPCLinuxAsmPrinter::EmitFunctionBodyEnd() {
470   // Only the 64-bit target requires a traceback table.  For now,
471   // we only emit the word of zeroes that GDB requires to find
472   // the end of the function, and zeroes for the eight-byte
473   // mandatory fields.
474   // FIXME: We should fill in the eight-byte mandatory fields as described in
475   // the PPC64 ELF ABI (this is a low-priority item because GDB does not
476   // currently make use of these fields).
477   if (Subtarget.isPPC64()) {
478     OutStreamer.EmitIntValue(0, 4/*size*/);
479     OutStreamer.EmitIntValue(0, 8/*size*/);
480   }
481 }
482
483 void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) {
484   static const char *const CPUDirectives[] = {
485     "",
486     "ppc",
487     "ppc440",
488     "ppc601",
489     "ppc602",
490     "ppc603",
491     "ppc7400",
492     "ppc750",
493     "ppc970",
494     "ppcA2",
495     "ppce500mc",
496     "ppce5500",
497     "power6",
498     "power7",
499     "ppc64"
500   };
501
502   unsigned Directive = Subtarget.getDarwinDirective();
503   if (Subtarget.hasMFOCRF() && Directive < PPC::DIR_970)
504     Directive = PPC::DIR_970;
505   if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400)
506     Directive = PPC::DIR_7400;
507   if (Subtarget.isPPC64() && Directive < PPC::DIR_64)
508     Directive = PPC::DIR_64;
509   assert(Directive <= PPC::DIR_64 && "Directive out of range.");
510   
511   // FIXME: This is a total hack, finish mc'izing the PPC backend.
512   if (OutStreamer.hasRawTextSupport())
513     OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive]));
514
515   // Prime text sections so they are adjacent.  This reduces the likelihood a
516   // large data or debug section causes a branch to exceed 16M limit.
517   const TargetLoweringObjectFileMachO &TLOFMacho = 
518     static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
519   OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
520   if (TM.getRelocationModel() == Reloc::PIC_) {
521     OutStreamer.SwitchSection(
522            OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
523                                       MCSectionMachO::S_SYMBOL_STUBS |
524                                       MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
525                                       32, SectionKind::getText()));
526   } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) {
527     OutStreamer.SwitchSection(
528            OutContext.getMachOSection("__TEXT","__symbol_stub1",
529                                       MCSectionMachO::S_SYMBOL_STUBS |
530                                       MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
531                                       16, SectionKind::getText()));
532   }
533   OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
534 }
535
536 static MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) {
537   // Remove $stub suffix, add $lazy_ptr.
538   SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()-5);
539   TmpStr += "$lazy_ptr";
540   return Ctx.GetOrCreateSymbol(TmpStr.str());
541 }
542
543 static MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) {
544   // Add $tmp suffix to $stub, yielding $stub$tmp.
545   SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end());
546   TmpStr += "$tmp";
547   return Ctx.GetOrCreateSymbol(TmpStr.str());
548 }
549
550 void PPCDarwinAsmPrinter::
551 EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) {
552   bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64;
553   
554   const TargetLoweringObjectFileMachO &TLOFMacho = 
555     static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
556
557   // .lazy_symbol_pointer
558   const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection();
559   
560   // Output stubs for dynamically-linked functions
561   if (TM.getRelocationModel() == Reloc::PIC_) {
562     const MCSection *StubSection = 
563     OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
564                                MCSectionMachO::S_SYMBOL_STUBS |
565                                MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
566                                32, SectionKind::getText());
567     for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
568       OutStreamer.SwitchSection(StubSection);
569       EmitAlignment(4);
570       
571       MCSymbol *Stub = Stubs[i].first;
572       MCSymbol *RawSym = Stubs[i].second.getPointer();
573       MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
574       MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext);
575                                            
576       OutStreamer.EmitLabel(Stub);
577       OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
578       // FIXME: MCize this.
579       OutStreamer.EmitRawText(StringRef("\tmflr r0"));
580       OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName()));
581       OutStreamer.EmitLabel(AnonSymbol);
582       OutStreamer.EmitRawText(StringRef("\tmflr r11"));
583       OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+
584                               "-" + AnonSymbol->getName() + ")");
585       OutStreamer.EmitRawText(StringRef("\tmtlr r0"));
586       
587       if (isPPC64)
588         OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) +
589                                 "-" + AnonSymbol->getName() + ")(r11)");
590       else
591         OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) +
592                                 "-" + AnonSymbol->getName() + ")(r11)");
593       OutStreamer.EmitRawText(StringRef("\tmtctr r12"));
594       OutStreamer.EmitRawText(StringRef("\tbctr"));
595       
596       OutStreamer.SwitchSection(LSPSection);
597       OutStreamer.EmitLabel(LazyPtr);
598       OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
599       
600       if (isPPC64)
601         OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper"));
602       else
603         OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper"));
604     }
605     OutStreamer.AddBlankLine();
606     return;
607   }
608   
609   const MCSection *StubSection =
610     OutContext.getMachOSection("__TEXT","__symbol_stub1",
611                                MCSectionMachO::S_SYMBOL_STUBS |
612                                MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
613                                16, SectionKind::getText());
614   for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
615     MCSymbol *Stub = Stubs[i].first;
616     MCSymbol *RawSym = Stubs[i].second.getPointer();
617     MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
618
619     OutStreamer.SwitchSection(StubSection);
620     EmitAlignment(4);
621     OutStreamer.EmitLabel(Stub);
622     OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
623     OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")");
624     if (isPPC64)
625       OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) +
626                               ")(r11)");
627     else
628       OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) +
629                               ")(r11)");
630     OutStreamer.EmitRawText(StringRef("\tmtctr r12"));
631     OutStreamer.EmitRawText(StringRef("\tbctr"));
632     OutStreamer.SwitchSection(LSPSection);
633     OutStreamer.EmitLabel(LazyPtr);
634     OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
635     
636     if (isPPC64)
637       OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper"));
638     else
639       OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper"));
640   }
641   
642   OutStreamer.AddBlankLine();
643 }
644
645
646 bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
647   bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64;
648
649   // Darwin/PPC always uses mach-o.
650   const TargetLoweringObjectFileMachO &TLOFMacho = 
651     static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
652   MachineModuleInfoMachO &MMIMacho =
653     MMI->getObjFileInfo<MachineModuleInfoMachO>();
654   
655   MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList();
656   if (!Stubs.empty())
657     EmitFunctionStubs(Stubs);
658
659   if (MAI->doesSupportExceptionHandling() && MMI) {
660     // Add the (possibly multiple) personalities to the set of global values.
661     // Only referenced functions get into the Personalities list.
662     const std::vector<const Function*> &Personalities = MMI->getPersonalities();
663     for (std::vector<const Function*>::const_iterator I = Personalities.begin(),
664          E = Personalities.end(); I != E; ++I) {
665       if (*I) {
666         MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr");
667         MachineModuleInfoImpl::StubValueTy &StubSym =
668           MMIMacho.getGVStubEntry(NLPSym);
669         StubSym = MachineModuleInfoImpl::StubValueTy(Mang->getSymbol(*I), true);
670       }
671     }
672   }
673
674   // Output stubs for dynamically-linked functions.
675   Stubs = MMIMacho.GetGVStubList();
676   
677   // Output macho stubs for external and common global variables.
678   if (!Stubs.empty()) {
679     // Switch with ".non_lazy_symbol_pointer" directive.
680     OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
681     EmitAlignment(isPPC64 ? 3 : 2);
682     
683     for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
684       // L_foo$stub:
685       OutStreamer.EmitLabel(Stubs[i].first);
686       //   .indirect_symbol _foo
687       MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
688       OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);
689
690       if (MCSym.getInt())
691         // External to current translation unit.
692         OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/);
693       else
694         // Internal to current translation unit.
695         //
696         // When we place the LSDA into the TEXT section, the type info pointers
697         // need to be indirect and pc-rel. We accomplish this by using NLPs.
698         // However, sometimes the types are local to the file. So we need to
699         // fill in the value for the NLP in those cases.
700         OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
701                                                       OutContext),
702                               isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/);
703     }
704
705     Stubs.clear();
706     OutStreamer.AddBlankLine();
707   }
708
709   Stubs = MMIMacho.GetHiddenGVStubList();
710   if (!Stubs.empty()) {
711     OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
712     EmitAlignment(isPPC64 ? 3 : 2);
713     
714     for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
715       // L_foo$stub:
716       OutStreamer.EmitLabel(Stubs[i].first);
717       //   .long _foo
718       OutStreamer.EmitValue(MCSymbolRefExpr::
719                             Create(Stubs[i].second.getPointer(),
720                                    OutContext),
721                             isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/);
722     }
723
724     Stubs.clear();
725     OutStreamer.AddBlankLine();
726   }
727
728   // Funny Darwin hack: This flag tells the linker that no global symbols
729   // contain code that falls through to other global symbols (e.g. the obvious
730   // implementation of multiple entry points).  If this doesn't occur, the
731   // linker can safely perform dead code stripping.  Since LLVM never generates
732   // code that does this, it is always safe to set.
733   OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
734
735   return AsmPrinter::doFinalization(M);
736 }
737
738 /// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
739 /// for a MachineFunction to the given output stream, in a format that the
740 /// Darwin assembler can deal with.
741 ///
742 static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm,
743                                            MCStreamer &Streamer) {
744   const PPCSubtarget *Subtarget = &tm.getSubtarget<PPCSubtarget>();
745
746   if (Subtarget->isDarwin())
747     return new PPCDarwinAsmPrinter(tm, Streamer);
748   return new PPCLinuxAsmPrinter(tm, Streamer);
749 }
750
751 // Force static initialization.
752 extern "C" void LLVMInitializePowerPCAsmPrinter() { 
753   TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass);
754   TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass);
755 }