1234353Sdim//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly ------===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This file contains a printer that converts from our internal representation
11218885Sdim// of machine-dependent LLVM code to PowerPC assembly language. This printer is
12218885Sdim// the output mechanism used by `llc'.
13218885Sdim//
14218885Sdim// Documentation at http://developer.apple.com/documentation/DeveloperTools/
15218885Sdim// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
16218885Sdim//
17218885Sdim//===----------------------------------------------------------------------===//
18218885Sdim
19218885Sdim#define DEBUG_TYPE "asmprinter"
20218885Sdim#include "PPC.h"
21234353Sdim#include "InstPrinter/PPCInstPrinter.h"
22226633Sdim#include "MCTargetDesc/PPCPredicates.h"
23263508Sdim#include "MCTargetDesc/PPCMCExpr.h"
24249423Sdim#include "PPCSubtarget.h"
25249423Sdim#include "PPCTargetMachine.h"
26263508Sdim#include "PPCTargetStreamer.h"
27249423Sdim#include "llvm/ADT/MapVector.h"
28249423Sdim#include "llvm/ADT/SmallString.h"
29249423Sdim#include "llvm/ADT/StringExtras.h"
30218885Sdim#include "llvm/Assembly/Writer.h"
31218885Sdim#include "llvm/CodeGen/AsmPrinter.h"
32218885Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
33218885Sdim#include "llvm/CodeGen/MachineInstr.h"
34218885Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
35218885Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h"
36218885Sdim#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
37249423Sdim#include "llvm/DebugInfo.h"
38249423Sdim#include "llvm/IR/Constants.h"
39249423Sdim#include "llvm/IR/DerivedTypes.h"
40249423Sdim#include "llvm/IR/Module.h"
41218885Sdim#include "llvm/MC/MCAsmInfo.h"
42218885Sdim#include "llvm/MC/MCContext.h"
43218885Sdim#include "llvm/MC/MCExpr.h"
44218885Sdim#include "llvm/MC/MCInst.h"
45249423Sdim#include "llvm/MC/MCInstBuilder.h"
46249423Sdim#include "llvm/MC/MCSectionELF.h"
47218885Sdim#include "llvm/MC/MCSectionMachO.h"
48218885Sdim#include "llvm/MC/MCStreamer.h"
49218885Sdim#include "llvm/MC/MCSymbol.h"
50218885Sdim#include "llvm/Support/CommandLine.h"
51218885Sdim#include "llvm/Support/Debug.h"
52249423Sdim#include "llvm/Support/ELF.h"
53249423Sdim#include "llvm/Support/ErrorHandling.h"
54218885Sdim#include "llvm/Support/MathExtras.h"
55226633Sdim#include "llvm/Support/TargetRegistry.h"
56218885Sdim#include "llvm/Support/raw_ostream.h"
57249423Sdim#include "llvm/Target/Mangler.h"
58249423Sdim#include "llvm/Target/TargetInstrInfo.h"
59249423Sdim#include "llvm/Target/TargetOptions.h"
60249423Sdim#include "llvm/Target/TargetRegisterInfo.h"
61218885Sdimusing namespace llvm;
62218885Sdim
63218885Sdimnamespace {
64218885Sdim  class PPCAsmPrinter : public AsmPrinter {
65218885Sdim  protected:
66243830Sdim    MapVector<MCSymbol*, MCSymbol*> TOC;
67218885Sdim    const PPCSubtarget &Subtarget;
68218885Sdim    uint64_t TOCLabelID;
69218885Sdim  public:
70218885Sdim    explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
71218885Sdim      : AsmPrinter(TM, Streamer),
72218885Sdim        Subtarget(TM.getSubtarget<PPCSubtarget>()), TOCLabelID(0) {}
73218885Sdim
74218885Sdim    virtual const char *getPassName() const {
75218885Sdim      return "PowerPC Assembly Printer";
76218885Sdim    }
77218885Sdim
78249423Sdim    MCSymbol *lookUpOrCreateTOCEntry(MCSymbol *Sym);
79218885Sdim
80218885Sdim    virtual void EmitInstruction(const MachineInstr *MI);
81218885Sdim
82218885Sdim    void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
83218885Sdim
84218885Sdim    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
85218885Sdim                         unsigned AsmVariant, const char *ExtraCode,
86218885Sdim                         raw_ostream &O);
87218885Sdim    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
88218885Sdim                               unsigned AsmVariant, const char *ExtraCode,
89218885Sdim                               raw_ostream &O);
90218885Sdim  };
91218885Sdim
92218885Sdim  /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
93218885Sdim  class PPCLinuxAsmPrinter : public PPCAsmPrinter {
94218885Sdim  public:
95218885Sdim    explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
96218885Sdim      : PPCAsmPrinter(TM, Streamer) {}
97218885Sdim
98218885Sdim    virtual const char *getPassName() const {
99218885Sdim      return "Linux PPC Assembly Printer";
100218885Sdim    }
101218885Sdim
102218885Sdim    bool doFinalization(Module &M);
103218885Sdim
104218885Sdim    virtual void EmitFunctionEntryLabel();
105243830Sdim
106243830Sdim    void EmitFunctionBodyEnd();
107218885Sdim  };
108218885Sdim
109218885Sdim  /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac
110218885Sdim  /// OS X
111218885Sdim  class PPCDarwinAsmPrinter : public PPCAsmPrinter {
112218885Sdim  public:
113218885Sdim    explicit PPCDarwinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
114218885Sdim      : PPCAsmPrinter(TM, Streamer) {}
115218885Sdim
116218885Sdim    virtual const char *getPassName() const {
117218885Sdim      return "Darwin PPC Assembly Printer";
118218885Sdim    }
119218885Sdim
120218885Sdim    bool doFinalization(Module &M);
121218885Sdim    void EmitStartOfAsmFile(Module &M);
122218885Sdim
123218885Sdim    void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs);
124218885Sdim  };
125218885Sdim} // end of anonymous namespace
126218885Sdim
127218885Sdim/// stripRegisterPrefix - This method strips the character prefix from a
128218885Sdim/// register name so that only the number is left.  Used by for linux asm.
129218885Sdimstatic const char *stripRegisterPrefix(const char *RegName) {
130218885Sdim  switch (RegName[0]) {
131218885Sdim    case 'r':
132218885Sdim    case 'f':
133218885Sdim    case 'v': return RegName + 1;
134218885Sdim    case 'c': if (RegName[1] == 'r') return RegName + 2;
135218885Sdim  }
136218885Sdim
137218885Sdim  return RegName;
138218885Sdim}
139218885Sdim
140218885Sdimvoid PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
141218885Sdim                                 raw_ostream &O) {
142218885Sdim  const MachineOperand &MO = MI->getOperand(OpNo);
143218885Sdim
144218885Sdim  switch (MO.getType()) {
145218885Sdim  case MachineOperand::MO_Register: {
146218885Sdim    const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg());
147218885Sdim    // Linux assembler (Others?) does not take register mnemonics.
148218885Sdim    // FIXME - What about special registers used in mfspr/mtspr?
149218885Sdim    if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName);
150218885Sdim    O << RegName;
151218885Sdim    return;
152218885Sdim  }
153218885Sdim  case MachineOperand::MO_Immediate:
154218885Sdim    O << MO.getImm();
155218885Sdim    return;
156218885Sdim
157218885Sdim  case MachineOperand::MO_MachineBasicBlock:
158218885Sdim    O << *MO.getMBB()->getSymbol();
159218885Sdim    return;
160218885Sdim  case MachineOperand::MO_JumpTableIndex:
161218885Sdim    O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
162218885Sdim      << '_' << MO.getIndex();
163218885Sdim    // FIXME: PIC relocation model
164218885Sdim    return;
165218885Sdim  case MachineOperand::MO_ConstantPoolIndex:
166218885Sdim    O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
167218885Sdim      << '_' << MO.getIndex();
168218885Sdim    return;
169218885Sdim  case MachineOperand::MO_BlockAddress:
170218885Sdim    O << *GetBlockAddressSymbol(MO.getBlockAddress());
171218885Sdim    return;
172218885Sdim  case MachineOperand::MO_ExternalSymbol: {
173218885Sdim    // Computing the address of an external symbol, not calling it.
174218885Sdim    if (TM.getRelocationModel() == Reloc::Static) {
175218885Sdim      O << *GetExternalSymbolSymbol(MO.getSymbolName());
176218885Sdim      return;
177218885Sdim    }
178218885Sdim
179218885Sdim    MCSymbol *NLPSym =
180218885Sdim      OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+
181218885Sdim                                   MO.getSymbolName()+"$non_lazy_ptr");
182218885Sdim    MachineModuleInfoImpl::StubValueTy &StubSym =
183218885Sdim      MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(NLPSym);
184218885Sdim    if (StubSym.getPointer() == 0)
185218885Sdim      StubSym = MachineModuleInfoImpl::
186218885Sdim        StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true);
187218885Sdim
188218885Sdim    O << *NLPSym;
189218885Sdim    return;
190218885Sdim  }
191218885Sdim  case MachineOperand::MO_GlobalAddress: {
192218885Sdim    // Computing the address of a global symbol, not calling it.
193218885Sdim    const GlobalValue *GV = MO.getGlobal();
194218885Sdim    MCSymbol *SymToPrint;
195218885Sdim
196218885Sdim    // External or weakly linked global variables need non-lazily-resolved stubs
197218885Sdim    if (TM.getRelocationModel() != Reloc::Static &&
198218885Sdim        (GV->isDeclaration() || GV->isWeakForLinker())) {
199218885Sdim      if (!GV->hasHiddenVisibility()) {
200218885Sdim        SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
201218885Sdim        MachineModuleInfoImpl::StubValueTy &StubSym =
202218885Sdim          MMI->getObjFileInfo<MachineModuleInfoMachO>()
203218885Sdim            .getGVStubEntry(SymToPrint);
204218885Sdim        if (StubSym.getPointer() == 0)
205218885Sdim          StubSym = MachineModuleInfoImpl::
206263508Sdim            StubValueTy(getSymbol(GV), !GV->hasInternalLinkage());
207218885Sdim      } else if (GV->isDeclaration() || GV->hasCommonLinkage() ||
208218885Sdim                 GV->hasAvailableExternallyLinkage()) {
209218885Sdim        SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
210218885Sdim
211218885Sdim        MachineModuleInfoImpl::StubValueTy &StubSym =
212218885Sdim          MMI->getObjFileInfo<MachineModuleInfoMachO>().
213218885Sdim                    getHiddenGVStubEntry(SymToPrint);
214218885Sdim        if (StubSym.getPointer() == 0)
215218885Sdim          StubSym = MachineModuleInfoImpl::
216263508Sdim            StubValueTy(getSymbol(GV), !GV->hasInternalLinkage());
217218885Sdim      } else {
218263508Sdim        SymToPrint = getSymbol(GV);
219218885Sdim      }
220218885Sdim    } else {
221263508Sdim      SymToPrint = getSymbol(GV);
222218885Sdim    }
223218885Sdim
224218885Sdim    O << *SymToPrint;
225218885Sdim
226218885Sdim    printOffset(MO.getOffset(), O);
227218885Sdim    return;
228218885Sdim  }
229218885Sdim
230218885Sdim  default:
231218885Sdim    O << "<unknown operand type: " << MO.getType() << ">";
232218885Sdim    return;
233218885Sdim  }
234218885Sdim}
235218885Sdim
236218885Sdim/// PrintAsmOperand - Print out an operand for an inline asm expression.
237218885Sdim///
238218885Sdimbool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
239218885Sdim                                    unsigned AsmVariant,
240218885Sdim                                    const char *ExtraCode, raw_ostream &O) {
241218885Sdim  // Does this asm operand have a single letter operand modifier?
242218885Sdim  if (ExtraCode && ExtraCode[0]) {
243218885Sdim    if (ExtraCode[1] != 0) return true; // Unknown modifier.
244218885Sdim
245218885Sdim    switch (ExtraCode[0]) {
246239462Sdim    default:
247239462Sdim      // See if this is a generic print operand
248239462Sdim      return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
249218885Sdim    case 'c': // Don't print "$" before a global var name or constant.
250218885Sdim      break; // PPC never has a prefix.
251218885Sdim    case 'L': // Write second word of DImode reference.
252218885Sdim      // Verify that this operand has two consecutive registers.
253218885Sdim      if (!MI->getOperand(OpNo).isReg() ||
254218885Sdim          OpNo+1 == MI->getNumOperands() ||
255218885Sdim          !MI->getOperand(OpNo+1).isReg())
256218885Sdim        return true;
257218885Sdim      ++OpNo;   // Return the high-part.
258218885Sdim      break;
259218885Sdim    case 'I':
260218885Sdim      // Write 'i' if an integer constant, otherwise nothing.  Used to print
261218885Sdim      // addi vs add, etc.
262218885Sdim      if (MI->getOperand(OpNo).isImm())
263218885Sdim        O << "i";
264218885Sdim      return false;
265218885Sdim    }
266218885Sdim  }
267218885Sdim
268218885Sdim  printOperand(MI, OpNo, O);
269218885Sdim  return false;
270218885Sdim}
271218885Sdim
272218885Sdim// At the moment, all inline asm memory operands are a single register.
273218885Sdim// In any case, the output of this routine should always be just one
274218885Sdim// assembler operand.
275218885Sdim
276218885Sdimbool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
277218885Sdim                                          unsigned AsmVariant,
278218885Sdim                                          const char *ExtraCode,
279218885Sdim                                          raw_ostream &O) {
280243830Sdim  if (ExtraCode && ExtraCode[0]) {
281243830Sdim    if (ExtraCode[1] != 0) return true; // Unknown modifier.
282243830Sdim
283243830Sdim    switch (ExtraCode[0]) {
284243830Sdim    default: return true;  // Unknown modifier.
285243830Sdim    case 'y': // A memory reference for an X-form instruction
286243830Sdim      {
287243830Sdim        const char *RegName = "r0";
288243830Sdim        if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName);
289243830Sdim        O << RegName << ", ";
290243830Sdim        printOperand(MI, OpNo, O);
291243830Sdim        return false;
292243830Sdim      }
293243830Sdim    }
294243830Sdim  }
295243830Sdim
296218885Sdim  assert(MI->getOperand(OpNo).isReg());
297218885Sdim  O << "0(";
298218885Sdim  printOperand(MI, OpNo, O);
299218885Sdim  O << ")";
300218885Sdim  return false;
301218885Sdim}
302218885Sdim
303218885Sdim
304249423Sdim/// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry
305249423Sdim/// exists for it.  If not, create one.  Then return a symbol that references
306249423Sdim/// the TOC entry.
307249423SdimMCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MCSymbol *Sym) {
308249423Sdim
309249423Sdim  MCSymbol *&TOCEntry = TOC[Sym];
310249423Sdim
311249423Sdim  // To avoid name clash check if the name already exists.
312249423Sdim  while (TOCEntry == 0) {
313249423Sdim    if (OutContext.LookupSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
314249423Sdim                                "C" + Twine(TOCLabelID++)) == 0) {
315249423Sdim      TOCEntry = GetTempSymbol("C", TOCLabelID);
316249423Sdim    }
317249423Sdim  }
318249423Sdim
319249423Sdim  return TOCEntry;
320249423Sdim}
321249423Sdim
322249423Sdim
323218885Sdim/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
324218885Sdim/// the current output stream.
325218885Sdim///
326218885Sdimvoid PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
327218885Sdim  MCInst TmpInst;
328218885Sdim
329218885Sdim  // Lower multi-instruction pseudo operations.
330218885Sdim  switch (MI->getOpcode()) {
331218885Sdim  default: break;
332263508Sdim  case TargetOpcode::DBG_VALUE:
333263508Sdim    llvm_unreachable("Should be handled target independently");
334218885Sdim  case PPC::MovePCtoLR:
335218885Sdim  case PPC::MovePCtoLR8: {
336218885Sdim    // Transform %LR = MovePCtoLR
337218885Sdim    // Into this, where the label is the PIC base:
338218885Sdim    //     bl L1$pb
339218885Sdim    // L1$pb:
340218885Sdim    MCSymbol *PICBase = MF->getPICBaseSymbol();
341218885Sdim
342218885Sdim    // Emit the 'bl'.
343249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL)
344249423Sdim      // FIXME: We would like an efficient form for this, so we don't have to do
345249423Sdim      // a lot of extra uniquing.
346249423Sdim      .addExpr(MCSymbolRefExpr::Create(PICBase, OutContext)));
347218885Sdim
348218885Sdim    // Emit the label.
349218885Sdim    OutStreamer.EmitLabel(PICBase);
350218885Sdim    return;
351218885Sdim  }
352243830Sdim  case PPC::LDtocJTI:
353243830Sdim  case PPC::LDtocCPT:
354218885Sdim  case PPC::LDtoc: {
355218885Sdim    // Transform %X3 = LDtoc <ga:@min1>, %X2
356223017Sdim    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
357243830Sdim
358218885Sdim    // Change the opcode to LD, and the global address operand to be a
359218885Sdim    // reference to the TOC entry we will synthesize later.
360218885Sdim    TmpInst.setOpcode(PPC::LD);
361218885Sdim    const MachineOperand &MO = MI->getOperand(1);
362243830Sdim
363243830Sdim    // Map symbol -> label of TOC entry
364243830Sdim    assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());
365243830Sdim    MCSymbol *MOSymbol = 0;
366243830Sdim    if (MO.isGlobal())
367263508Sdim      MOSymbol = getSymbol(MO.getGlobal());
368243830Sdim    else if (MO.isCPI())
369243830Sdim      MOSymbol = GetCPISymbol(MO.getIndex());
370243830Sdim    else if (MO.isJTI())
371243830Sdim      MOSymbol = GetJTISymbol(MO.getIndex());
372243830Sdim
373249423Sdim    MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
374249423Sdim
375218885Sdim    const MCExpr *Exp =
376263508Sdim      MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC,
377218885Sdim                              OutContext);
378218885Sdim    TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
379218885Sdim    OutStreamer.EmitInstruction(TmpInst);
380218885Sdim    return;
381218885Sdim  }
382218885Sdim
383249423Sdim  case PPC::ADDIStocHA: {
384249423Sdim    // Transform %Xd = ADDIStocHA %X2, <ga:@sym>
385249423Sdim    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
386249423Sdim
387249423Sdim    // Change the opcode to ADDIS8.  If the global address is external,
388249423Sdim    // has common linkage, is a function address, or is a jump table
389249423Sdim    // address, then generate a TOC entry and reference that.  Otherwise
390249423Sdim    // reference the symbol directly.
391249423Sdim    TmpInst.setOpcode(PPC::ADDIS8);
392249423Sdim    const MachineOperand &MO = MI->getOperand(2);
393249423Sdim    assert((MO.isGlobal() || MO.isCPI() || MO.isJTI()) &&
394249423Sdim           "Invalid operand for ADDIStocHA!");
395249423Sdim    MCSymbol *MOSymbol = 0;
396249423Sdim    bool IsExternal = false;
397249423Sdim    bool IsFunction = false;
398249423Sdim    bool IsCommon = false;
399249423Sdim    bool IsAvailExt = false;
400249423Sdim
401249423Sdim    if (MO.isGlobal()) {
402249423Sdim      const GlobalValue *GValue = MO.getGlobal();
403249423Sdim      const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
404249423Sdim      const GlobalValue *RealGValue = GAlias ?
405249423Sdim        GAlias->resolveAliasedGlobal(false) : GValue;
406263508Sdim      MOSymbol = getSymbol(RealGValue);
407249423Sdim      const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
408249423Sdim      IsExternal = GVar && !GVar->hasInitializer();
409249423Sdim      IsCommon = GVar && RealGValue->hasCommonLinkage();
410249423Sdim      IsFunction = !GVar;
411249423Sdim      IsAvailExt = GVar && RealGValue->hasAvailableExternallyLinkage();
412249423Sdim    } else if (MO.isCPI())
413249423Sdim      MOSymbol = GetCPISymbol(MO.getIndex());
414249423Sdim    else if (MO.isJTI())
415249423Sdim      MOSymbol = GetJTISymbol(MO.getIndex());
416249423Sdim
417263508Sdim    if (IsExternal || IsFunction || IsCommon || IsAvailExt || MO.isJTI() ||
418263508Sdim        TM.getCodeModel() == CodeModel::Large)
419249423Sdim      MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
420249423Sdim
421249423Sdim    const MCExpr *Exp =
422263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_HA,
423249423Sdim                              OutContext);
424249423Sdim    TmpInst.getOperand(2) = MCOperand::CreateExpr(Exp);
425249423Sdim    OutStreamer.EmitInstruction(TmpInst);
426249423Sdim    return;
427249423Sdim  }
428249423Sdim  case PPC::LDtocL: {
429249423Sdim    // Transform %Xd = LDtocL <ga:@sym>, %Xs
430249423Sdim    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
431249423Sdim
432249423Sdim    // Change the opcode to LD.  If the global address is external, has
433249423Sdim    // common linkage, or is a jump table address, then reference the
434249423Sdim    // associated TOC entry.  Otherwise reference the symbol directly.
435249423Sdim    TmpInst.setOpcode(PPC::LD);
436249423Sdim    const MachineOperand &MO = MI->getOperand(1);
437249423Sdim    assert((MO.isGlobal() || MO.isJTI() || MO.isCPI()) &&
438249423Sdim           "Invalid operand for LDtocL!");
439249423Sdim    MCSymbol *MOSymbol = 0;
440249423Sdim
441249423Sdim    if (MO.isJTI())
442249423Sdim      MOSymbol = lookUpOrCreateTOCEntry(GetJTISymbol(MO.getIndex()));
443263508Sdim    else if (MO.isCPI()) {
444249423Sdim      MOSymbol = GetCPISymbol(MO.getIndex());
445263508Sdim      if (TM.getCodeModel() == CodeModel::Large)
446263508Sdim        MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
447263508Sdim    }
448249423Sdim    else if (MO.isGlobal()) {
449249423Sdim      const GlobalValue *GValue = MO.getGlobal();
450249423Sdim      const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
451249423Sdim      const GlobalValue *RealGValue = GAlias ?
452249423Sdim        GAlias->resolveAliasedGlobal(false) : GValue;
453263508Sdim      MOSymbol = getSymbol(RealGValue);
454249423Sdim      const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
455249423Sdim
456249423Sdim      if (!GVar || !GVar->hasInitializer() || RealGValue->hasCommonLinkage() ||
457263508Sdim          RealGValue->hasAvailableExternallyLinkage() ||
458263508Sdim          TM.getCodeModel() == CodeModel::Large)
459249423Sdim        MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
460249423Sdim    }
461249423Sdim
462249423Sdim    const MCExpr *Exp =
463263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO,
464249423Sdim                              OutContext);
465249423Sdim    TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
466249423Sdim    OutStreamer.EmitInstruction(TmpInst);
467249423Sdim    return;
468249423Sdim  }
469249423Sdim  case PPC::ADDItocL: {
470249423Sdim    // Transform %Xd = ADDItocL %Xs, <ga:@sym>
471249423Sdim    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
472249423Sdim
473249423Sdim    // Change the opcode to ADDI8.  If the global address is external, then
474249423Sdim    // generate a TOC entry and reference that.  Otherwise reference the
475249423Sdim    // symbol directly.
476249423Sdim    TmpInst.setOpcode(PPC::ADDI8);
477249423Sdim    const MachineOperand &MO = MI->getOperand(2);
478249423Sdim    assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL");
479249423Sdim    MCSymbol *MOSymbol = 0;
480249423Sdim    bool IsExternal = false;
481249423Sdim    bool IsFunction = false;
482249423Sdim
483249423Sdim    if (MO.isGlobal()) {
484249423Sdim      const GlobalValue *GValue = MO.getGlobal();
485249423Sdim      const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
486249423Sdim      const GlobalValue *RealGValue = GAlias ?
487249423Sdim        GAlias->resolveAliasedGlobal(false) : GValue;
488263508Sdim      MOSymbol = getSymbol(RealGValue);
489249423Sdim      const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
490249423Sdim      IsExternal = GVar && !GVar->hasInitializer();
491249423Sdim      IsFunction = !GVar;
492249423Sdim    } else if (MO.isCPI())
493249423Sdim      MOSymbol = GetCPISymbol(MO.getIndex());
494249423Sdim
495263508Sdim    if (IsFunction || IsExternal || TM.getCodeModel() == CodeModel::Large)
496249423Sdim      MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
497249423Sdim
498249423Sdim    const MCExpr *Exp =
499263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO,
500249423Sdim                              OutContext);
501249423Sdim    TmpInst.getOperand(2) = MCOperand::CreateExpr(Exp);
502249423Sdim    OutStreamer.EmitInstruction(TmpInst);
503249423Sdim    return;
504249423Sdim  }
505249423Sdim  case PPC::ADDISgotTprelHA: {
506249423Sdim    // Transform: %Xd = ADDISgotTprelHA %X2, <ga:@sym>
507249423Sdim    // Into:      %Xd = ADDIS8 %X2, sym@got@tlsgd@ha
508249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
509249423Sdim    const MachineOperand &MO = MI->getOperand(2);
510249423Sdim    const GlobalValue *GValue = MO.getGlobal();
511263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
512249423Sdim    const MCExpr *SymGotTprel =
513263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA,
514249423Sdim                              OutContext);
515249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8)
516249423Sdim                                .addReg(MI->getOperand(0).getReg())
517249423Sdim                                .addReg(PPC::X2)
518249423Sdim                                .addExpr(SymGotTprel));
519249423Sdim    return;
520249423Sdim  }
521249423Sdim  case PPC::LDgotTprelL: {
522249423Sdim    // Transform %Xd = LDgotTprelL <ga:@sym>, %Xs
523249423Sdim    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
524249423Sdim
525249423Sdim    // Change the opcode to LD.
526249423Sdim    TmpInst.setOpcode(PPC::LD);
527249423Sdim    const MachineOperand &MO = MI->getOperand(1);
528249423Sdim    const GlobalValue *GValue = MO.getGlobal();
529263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
530249423Sdim    const MCExpr *Exp =
531263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO,
532249423Sdim                              OutContext);
533249423Sdim    TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
534249423Sdim    OutStreamer.EmitInstruction(TmpInst);
535249423Sdim    return;
536249423Sdim  }
537249423Sdim  case PPC::ADDIStlsgdHA: {
538249423Sdim    // Transform: %Xd = ADDIStlsgdHA %X2, <ga:@sym>
539249423Sdim    // Into:      %Xd = ADDIS8 %X2, sym@got@tlsgd@ha
540249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
541249423Sdim    const MachineOperand &MO = MI->getOperand(2);
542249423Sdim    const GlobalValue *GValue = MO.getGlobal();
543263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
544249423Sdim    const MCExpr *SymGotTlsGD =
545263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA,
546249423Sdim                              OutContext);
547249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8)
548249423Sdim                                .addReg(MI->getOperand(0).getReg())
549249423Sdim                                .addReg(PPC::X2)
550249423Sdim                                .addExpr(SymGotTlsGD));
551249423Sdim    return;
552249423Sdim  }
553249423Sdim  case PPC::ADDItlsgdL: {
554249423Sdim    // Transform: %Xd = ADDItlsgdL %Xs, <ga:@sym>
555249423Sdim    // Into:      %Xd = ADDI8 %Xs, sym@got@tlsgd@l
556249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
557249423Sdim    const MachineOperand &MO = MI->getOperand(2);
558249423Sdim    const GlobalValue *GValue = MO.getGlobal();
559263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
560249423Sdim    const MCExpr *SymGotTlsGD =
561263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO,
562249423Sdim                              OutContext);
563249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8)
564249423Sdim                                .addReg(MI->getOperand(0).getReg())
565249423Sdim                                .addReg(MI->getOperand(1).getReg())
566249423Sdim                                .addExpr(SymGotTlsGD));
567249423Sdim    return;
568249423Sdim  }
569249423Sdim  case PPC::GETtlsADDR: {
570249423Sdim    // Transform: %X3 = GETtlsADDR %X3, <ga:@sym>
571263508Sdim    // Into:      BL8_NOP_TLS __tls_get_addr(sym@tlsgd)
572249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
573249423Sdim
574249423Sdim    StringRef Name = "__tls_get_addr";
575249423Sdim    MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);
576249423Sdim    const MCSymbolRefExpr *TlsRef =
577249423Sdim      MCSymbolRefExpr::Create(TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext);
578249423Sdim    const MachineOperand &MO = MI->getOperand(2);
579249423Sdim    const GlobalValue *GValue = MO.getGlobal();
580263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
581249423Sdim    const MCExpr *SymVar =
582249423Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSGD,
583249423Sdim                              OutContext);
584263508Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL8_NOP_TLS)
585249423Sdim                                .addExpr(TlsRef)
586249423Sdim                                .addExpr(SymVar));
587249423Sdim    return;
588249423Sdim  }
589249423Sdim  case PPC::ADDIStlsldHA: {
590249423Sdim    // Transform: %Xd = ADDIStlsldHA %X2, <ga:@sym>
591249423Sdim    // Into:      %Xd = ADDIS8 %X2, sym@got@tlsld@ha
592249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
593249423Sdim    const MachineOperand &MO = MI->getOperand(2);
594249423Sdim    const GlobalValue *GValue = MO.getGlobal();
595263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
596249423Sdim    const MCExpr *SymGotTlsLD =
597263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA,
598249423Sdim                              OutContext);
599249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8)
600249423Sdim                                .addReg(MI->getOperand(0).getReg())
601249423Sdim                                .addReg(PPC::X2)
602249423Sdim                                .addExpr(SymGotTlsLD));
603249423Sdim    return;
604249423Sdim  }
605249423Sdim  case PPC::ADDItlsldL: {
606249423Sdim    // Transform: %Xd = ADDItlsldL %Xs, <ga:@sym>
607249423Sdim    // Into:      %Xd = ADDI8 %Xs, sym@got@tlsld@l
608249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
609249423Sdim    const MachineOperand &MO = MI->getOperand(2);
610249423Sdim    const GlobalValue *GValue = MO.getGlobal();
611263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
612249423Sdim    const MCExpr *SymGotTlsLD =
613263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO,
614249423Sdim                              OutContext);
615249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8)
616249423Sdim                                .addReg(MI->getOperand(0).getReg())
617249423Sdim                                .addReg(MI->getOperand(1).getReg())
618249423Sdim                                .addExpr(SymGotTlsLD));
619249423Sdim    return;
620249423Sdim  }
621249423Sdim  case PPC::GETtlsldADDR: {
622249423Sdim    // Transform: %X3 = GETtlsldADDR %X3, <ga:@sym>
623263508Sdim    // Into:      BL8_NOP_TLS __tls_get_addr(sym@tlsld)
624249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
625249423Sdim
626249423Sdim    StringRef Name = "__tls_get_addr";
627249423Sdim    MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);
628249423Sdim    const MCSymbolRefExpr *TlsRef =
629249423Sdim      MCSymbolRefExpr::Create(TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext);
630249423Sdim    const MachineOperand &MO = MI->getOperand(2);
631249423Sdim    const GlobalValue *GValue = MO.getGlobal();
632263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
633249423Sdim    const MCExpr *SymVar =
634249423Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSLD,
635249423Sdim                              OutContext);
636263508Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL8_NOP_TLS)
637249423Sdim                                .addExpr(TlsRef)
638249423Sdim                                .addExpr(SymVar));
639249423Sdim    return;
640249423Sdim  }
641249423Sdim  case PPC::ADDISdtprelHA: {
642249423Sdim    // Transform: %Xd = ADDISdtprelHA %X3, <ga:@sym>
643249423Sdim    // Into:      %Xd = ADDIS8 %X3, sym@dtprel@ha
644249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
645249423Sdim    const MachineOperand &MO = MI->getOperand(2);
646249423Sdim    const GlobalValue *GValue = MO.getGlobal();
647263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
648249423Sdim    const MCExpr *SymDtprel =
649263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_HA,
650249423Sdim                              OutContext);
651249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8)
652249423Sdim                                .addReg(MI->getOperand(0).getReg())
653249423Sdim                                .addReg(PPC::X3)
654249423Sdim                                .addExpr(SymDtprel));
655249423Sdim    return;
656249423Sdim  }
657249423Sdim  case PPC::ADDIdtprelL: {
658249423Sdim    // Transform: %Xd = ADDIdtprelL %Xs, <ga:@sym>
659249423Sdim    // Into:      %Xd = ADDI8 %Xs, sym@dtprel@l
660249423Sdim    assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
661249423Sdim    const MachineOperand &MO = MI->getOperand(2);
662249423Sdim    const GlobalValue *GValue = MO.getGlobal();
663263508Sdim    MCSymbol *MOSymbol = getSymbol(GValue);
664249423Sdim    const MCExpr *SymDtprel =
665263508Sdim      MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_LO,
666249423Sdim                              OutContext);
667249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8)
668249423Sdim                                .addReg(MI->getOperand(0).getReg())
669249423Sdim                                .addReg(MI->getOperand(1).getReg())
670249423Sdim                                .addExpr(SymDtprel));
671249423Sdim    return;
672249423Sdim  }
673263508Sdim  case PPC::MFOCRF:
674263508Sdim  case PPC::MFOCRF8:
675263508Sdim    if (!Subtarget.hasMFOCRF()) {
676263508Sdim      // Transform: %R3 = MFOCRF %CR7
677263508Sdim      // Into:      %R3 = MFCR   ;; cr7
678263508Sdim      unsigned NewOpcode =
679263508Sdim        MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;
680263508Sdim      OutStreamer.AddComment(PPCInstPrinter::
681263508Sdim                             getRegisterName(MI->getOperand(1).getReg()));
682263508Sdim      OutStreamer.EmitInstruction(MCInstBuilder(NewOpcode)
683263508Sdim                                  .addReg(MI->getOperand(0).getReg()));
684263508Sdim      return;
685263508Sdim    }
686263508Sdim    break;
687263508Sdim  case PPC::MTOCRF:
688263508Sdim  case PPC::MTOCRF8:
689263508Sdim    if (!Subtarget.hasMFOCRF()) {
690263508Sdim      // Transform: %CR7 = MTOCRF %R3
691263508Sdim      // Into:      MTCRF mask, %R3 ;; cr7
692263508Sdim      unsigned NewOpcode =
693263508Sdim        MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
694263508Sdim      unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
695263508Sdim                              ->getEncodingValue(MI->getOperand(0).getReg());
696263508Sdim      OutStreamer.AddComment(PPCInstPrinter::
697263508Sdim                             getRegisterName(MI->getOperand(0).getReg()));
698263508Sdim      OutStreamer.EmitInstruction(MCInstBuilder(NewOpcode)
699263508Sdim                                  .addImm(Mask)
700263508Sdim                                  .addReg(MI->getOperand(1).getReg()));
701263508Sdim      return;
702263508Sdim    }
703263508Sdim    break;
704263508Sdim  case PPC::LD:
705263508Sdim  case PPC::STD:
706263508Sdim  case PPC::LWA_32:
707263508Sdim  case PPC::LWA: {
708263508Sdim    // Verify alignment is legal, so we don't create relocations
709263508Sdim    // that can't be supported.
710263508Sdim    // FIXME:  This test is currently disabled for Darwin.  The test
711263508Sdim    // suite shows a handful of test cases that fail this check for
712263508Sdim    // Darwin.  Those need to be investigated before this sanity test
713263508Sdim    // can be enabled for those subtargets.
714263508Sdim    if (!Subtarget.isDarwin()) {
715263508Sdim      unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;
716263508Sdim      const MachineOperand &MO = MI->getOperand(OpNum);
717263508Sdim      if (MO.isGlobal() && MO.getGlobal()->getAlignment() < 4)
718263508Sdim        llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");
719263508Sdim    }
720263508Sdim    // Now process the instruction normally.
721263508Sdim    break;
722218885Sdim  }
723263508Sdim  }
724218885Sdim
725223017Sdim  LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
726218885Sdim  OutStreamer.EmitInstruction(TmpInst);
727218885Sdim}
728218885Sdim
729218885Sdimvoid PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
730218885Sdim  if (!Subtarget.isPPC64())  // linux/ppc32 - Normal entry label.
731218885Sdim    return AsmPrinter::EmitFunctionEntryLabel();
732218885Sdim
733218885Sdim  // Emit an official procedure descriptor.
734251662Sdim  MCSectionSubPair Current = OutStreamer.getCurrentSection();
735234353Sdim  const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".opd",
736234353Sdim      ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
737234353Sdim      SectionKind::getReadOnly());
738234353Sdim  OutStreamer.SwitchSection(Section);
739218885Sdim  OutStreamer.EmitLabel(CurrentFnSym);
740234353Sdim  OutStreamer.EmitValueToAlignment(8);
741234353Sdim  MCSymbol *Symbol1 =
742234353Sdim    OutContext.GetOrCreateSymbol(".L." + Twine(CurrentFnSym->getName()));
743243830Sdim  // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function
744243830Sdim  // entry point.
745234353Sdim  OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol1, OutContext),
746249423Sdim			8 /*size*/);
747243830Sdim  MCSymbol *Symbol2 = OutContext.GetOrCreateSymbol(StringRef(".TOC."));
748243830Sdim  // Generates a R_PPC64_TOC relocation for TOC base insertion.
749243830Sdim  OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol2,
750263508Sdim                        MCSymbolRefExpr::VK_PPC_TOCBASE, OutContext),
751249423Sdim                        8/*size*/);
752243830Sdim  // Emit a null environment pointer.
753249423Sdim  OutStreamer.EmitIntValue(0, 8 /* size */);
754251662Sdim  OutStreamer.SwitchSection(Current.first, Current.second);
755234353Sdim
756234353Sdim  MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol(
757234353Sdim                          ".L." + Twine(CurrentFnSym->getName()));
758234353Sdim  OutStreamer.EmitLabel(RealFnSym);
759234353Sdim  CurrentFnSymForSize = RealFnSym;
760218885Sdim}
761218885Sdim
762218885Sdim
763218885Sdimbool PPCLinuxAsmPrinter::doFinalization(Module &M) {
764243830Sdim  const DataLayout *TD = TM.getDataLayout();
765218885Sdim
766218885Sdim  bool isPPC64 = TD->getPointerSizeInBits() == 64;
767218885Sdim
768263508Sdim  PPCTargetStreamer &TS =
769263508Sdim      static_cast<PPCTargetStreamer &>(OutStreamer.getTargetStreamer());
770263508Sdim
771218885Sdim  if (isPPC64 && !TOC.empty()) {
772234353Sdim    const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc",
773234353Sdim        ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
774234353Sdim        SectionKind::getReadOnly());
775234353Sdim    OutStreamer.SwitchSection(Section);
776218885Sdim
777243830Sdim    for (MapVector<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(),
778218885Sdim         E = TOC.end(); I != E; ++I) {
779218885Sdim      OutStreamer.EmitLabel(I->second);
780243830Sdim      MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName());
781263508Sdim      TS.emitTCEntry(*S);
782218885Sdim    }
783218885Sdim  }
784218885Sdim
785249423Sdim  MachineModuleInfoELF &MMIELF =
786249423Sdim    MMI->getObjFileInfo<MachineModuleInfoELF>();
787249423Sdim
788249423Sdim  MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
789249423Sdim  if (!Stubs.empty()) {
790249423Sdim    OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
791249423Sdim    for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
792249423Sdim      // L_foo$stub:
793249423Sdim      OutStreamer.EmitLabel(Stubs[i].first);
794249423Sdim      //   .long _foo
795249423Sdim      OutStreamer.EmitValue(MCSymbolRefExpr::Create(Stubs[i].second.getPointer(),
796249423Sdim                                                    OutContext),
797263508Sdim                            isPPC64 ? 8 : 4/*size*/);
798249423Sdim    }
799249423Sdim
800249423Sdim    Stubs.clear();
801249423Sdim    OutStreamer.AddBlankLine();
802249423Sdim  }
803249423Sdim
804218885Sdim  return AsmPrinter::doFinalization(M);
805218885Sdim}
806218885Sdim
807243830Sdim/// EmitFunctionBodyEnd - Print the traceback table before the .size
808243830Sdim/// directive.
809243830Sdim///
810243830Sdimvoid PPCLinuxAsmPrinter::EmitFunctionBodyEnd() {
811243830Sdim  // Only the 64-bit target requires a traceback table.  For now,
812243830Sdim  // we only emit the word of zeroes that GDB requires to find
813243830Sdim  // the end of the function, and zeroes for the eight-byte
814243830Sdim  // mandatory fields.
815243830Sdim  // FIXME: We should fill in the eight-byte mandatory fields as described in
816243830Sdim  // the PPC64 ELF ABI (this is a low-priority item because GDB does not
817243830Sdim  // currently make use of these fields).
818243830Sdim  if (Subtarget.isPPC64()) {
819243830Sdim    OutStreamer.EmitIntValue(0, 4/*size*/);
820243830Sdim    OutStreamer.EmitIntValue(0, 8/*size*/);
821243830Sdim  }
822243830Sdim}
823243830Sdim
824218885Sdimvoid PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) {
825218885Sdim  static const char *const CPUDirectives[] = {
826218885Sdim    "",
827218885Sdim    "ppc",
828234353Sdim    "ppc440",
829218885Sdim    "ppc601",
830218885Sdim    "ppc602",
831218885Sdim    "ppc603",
832218885Sdim    "ppc7400",
833218885Sdim    "ppc750",
834218885Sdim    "ppc970",
835234353Sdim    "ppcA2",
836243830Sdim    "ppce500mc",
837243830Sdim    "ppce5500",
838249423Sdim    "power3",
839249423Sdim    "power4",
840249423Sdim    "power5",
841249423Sdim    "power5x",
842239462Sdim    "power6",
843249423Sdim    "power6x",
844239462Sdim    "power7",
845263508Sdim    "ppc64",
846263508Sdim    "ppc64le"
847218885Sdim  };
848218885Sdim
849218885Sdim  unsigned Directive = Subtarget.getDarwinDirective();
850239462Sdim  if (Subtarget.hasMFOCRF() && Directive < PPC::DIR_970)
851218885Sdim    Directive = PPC::DIR_970;
852218885Sdim  if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400)
853218885Sdim    Directive = PPC::DIR_7400;
854234353Sdim  if (Subtarget.isPPC64() && Directive < PPC::DIR_64)
855218885Sdim    Directive = PPC::DIR_64;
856218885Sdim  assert(Directive <= PPC::DIR_64 && "Directive out of range.");
857218885Sdim
858218885Sdim  // FIXME: This is a total hack, finish mc'izing the PPC backend.
859249423Sdim  if (OutStreamer.hasRawTextSupport()) {
860263508Sdim    assert(Directive < array_lengthof(CPUDirectives) &&
861249423Sdim           "CPUDirectives[] might not be up-to-date!");
862218885Sdim    OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive]));
863249423Sdim  }
864218885Sdim
865218885Sdim  // Prime text sections so they are adjacent.  This reduces the likelihood a
866218885Sdim  // large data or debug section causes a branch to exceed 16M limit.
867218885Sdim  const TargetLoweringObjectFileMachO &TLOFMacho =
868218885Sdim    static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
869218885Sdim  OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
870218885Sdim  if (TM.getRelocationModel() == Reloc::PIC_) {
871218885Sdim    OutStreamer.SwitchSection(
872218885Sdim           OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
873218885Sdim                                      MCSectionMachO::S_SYMBOL_STUBS |
874218885Sdim                                      MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
875218885Sdim                                      32, SectionKind::getText()));
876218885Sdim  } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) {
877218885Sdim    OutStreamer.SwitchSection(
878218885Sdim           OutContext.getMachOSection("__TEXT","__symbol_stub1",
879218885Sdim                                      MCSectionMachO::S_SYMBOL_STUBS |
880218885Sdim                                      MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
881218885Sdim                                      16, SectionKind::getText()));
882218885Sdim  }
883218885Sdim  OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
884218885Sdim}
885218885Sdim
886218885Sdimstatic MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) {
887218885Sdim  // Remove $stub suffix, add $lazy_ptr.
888249423Sdim  StringRef NoStub = Sym->getName().substr(0, Sym->getName().size()-5);
889249423Sdim  return Ctx.GetOrCreateSymbol(NoStub + "$lazy_ptr");
890218885Sdim}
891218885Sdim
892218885Sdimstatic MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) {
893218885Sdim  // Add $tmp suffix to $stub, yielding $stub$tmp.
894249423Sdim  return Ctx.GetOrCreateSymbol(Sym->getName() + "$tmp");
895218885Sdim}
896218885Sdim
897218885Sdimvoid PPCDarwinAsmPrinter::
898218885SdimEmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) {
899243830Sdim  bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64;
900263508Sdim  bool isDarwin = Subtarget.isDarwin();
901218885Sdim
902218885Sdim  const TargetLoweringObjectFileMachO &TLOFMacho =
903218885Sdim    static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
904218885Sdim
905218885Sdim  // .lazy_symbol_pointer
906218885Sdim  const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection();
907218885Sdim
908218885Sdim  // Output stubs for dynamically-linked functions
909218885Sdim  if (TM.getRelocationModel() == Reloc::PIC_) {
910218885Sdim    const MCSection *StubSection =
911218885Sdim    OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
912218885Sdim                               MCSectionMachO::S_SYMBOL_STUBS |
913218885Sdim                               MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
914218885Sdim                               32, SectionKind::getText());
915218885Sdim    for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
916218885Sdim      OutStreamer.SwitchSection(StubSection);
917218885Sdim      EmitAlignment(4);
918218885Sdim
919218885Sdim      MCSymbol *Stub = Stubs[i].first;
920218885Sdim      MCSymbol *RawSym = Stubs[i].second.getPointer();
921218885Sdim      MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
922218885Sdim      MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext);
923218885Sdim
924218885Sdim      OutStreamer.EmitLabel(Stub);
925218885Sdim      OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
926249423Sdim
927249423Sdim      const MCExpr *Anon = MCSymbolRefExpr::Create(AnonSymbol, OutContext);
928263508Sdim      const MCExpr *LazyPtrExpr = MCSymbolRefExpr::Create(LazyPtr, OutContext);
929263508Sdim      const MCExpr *Sub =
930263508Sdim        MCBinaryExpr::CreateSub(LazyPtrExpr, Anon, OutContext);
931249423Sdim
932249423Sdim      // mflr r0
933249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R0));
934249423Sdim      // bcl 20, 31, AnonSymbol
935249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCLalways).addExpr(Anon));
936218885Sdim      OutStreamer.EmitLabel(AnonSymbol);
937249423Sdim      // mflr r11
938249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R11));
939249423Sdim      // addis r11, r11, ha16(LazyPtr - AnonSymbol)
940263508Sdim      const MCExpr *SubHa16 = PPCMCExpr::CreateHa(Sub, isDarwin, OutContext);
941249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS)
942249423Sdim        .addReg(PPC::R11)
943249423Sdim        .addReg(PPC::R11)
944263508Sdim        .addExpr(SubHa16));
945249423Sdim      // mtlr r0
946249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTLR).addReg(PPC::R0));
947249423Sdim
948249423Sdim      // ldu r12, lo16(LazyPtr - AnonSymbol)(r11)
949249423Sdim      // lwzu r12, lo16(LazyPtr - AnonSymbol)(r11)
950263508Sdim      const MCExpr *SubLo16 = PPCMCExpr::CreateLo(Sub, isDarwin, OutContext);
951249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU)
952249423Sdim        .addReg(PPC::R12)
953263508Sdim        .addExpr(SubLo16).addExpr(SubLo16)
954249423Sdim        .addReg(PPC::R11));
955249423Sdim      // mtctr r12
956249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12));
957249423Sdim      // bctr
958249423Sdim      OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR));
959249423Sdim
960218885Sdim      OutStreamer.SwitchSection(LSPSection);
961218885Sdim      OutStreamer.EmitLabel(LazyPtr);
962218885Sdim      OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
963249423Sdim
964249423Sdim      MCSymbol *DyldStubBindingHelper =
965249423Sdim        OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper"));
966249423Sdim      if (isPPC64) {
967249423Sdim        // .quad dyld_stub_binding_helper
968249423Sdim        OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8);
969249423Sdim      } else {
970249423Sdim        // .long dyld_stub_binding_helper
971249423Sdim        OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4);
972249423Sdim      }
973218885Sdim    }
974218885Sdim    OutStreamer.AddBlankLine();
975218885Sdim    return;
976218885Sdim  }
977218885Sdim
978218885Sdim  const MCSection *StubSection =
979218885Sdim    OutContext.getMachOSection("__TEXT","__symbol_stub1",
980218885Sdim                               MCSectionMachO::S_SYMBOL_STUBS |
981218885Sdim                               MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
982218885Sdim                               16, SectionKind::getText());
983218885Sdim  for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
984218885Sdim    MCSymbol *Stub = Stubs[i].first;
985218885Sdim    MCSymbol *RawSym = Stubs[i].second.getPointer();
986218885Sdim    MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
987263508Sdim    const MCExpr *LazyPtrExpr = MCSymbolRefExpr::Create(LazyPtr, OutContext);
988218885Sdim
989218885Sdim    OutStreamer.SwitchSection(StubSection);
990218885Sdim    EmitAlignment(4);
991218885Sdim    OutStreamer.EmitLabel(Stub);
992218885Sdim    OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
993263508Sdim
994249423Sdim    // lis r11, ha16(LazyPtr)
995249423Sdim    const MCExpr *LazyPtrHa16 =
996263508Sdim      PPCMCExpr::CreateHa(LazyPtrExpr, isDarwin, OutContext);
997249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::LIS)
998249423Sdim      .addReg(PPC::R11)
999249423Sdim      .addExpr(LazyPtrHa16));
1000249423Sdim
1001249423Sdim    // ldu r12, lo16(LazyPtr)(r11)
1002249423Sdim    // lwzu r12, lo16(LazyPtr)(r11)
1003263508Sdim    const MCExpr *LazyPtrLo16 =
1004263508Sdim      PPCMCExpr::CreateLo(LazyPtrExpr, isDarwin, OutContext);
1005249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU)
1006249423Sdim      .addReg(PPC::R12)
1007249423Sdim      .addExpr(LazyPtrLo16).addExpr(LazyPtrLo16)
1008249423Sdim      .addReg(PPC::R11));
1009249423Sdim
1010249423Sdim    // mtctr r12
1011249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12));
1012249423Sdim    // bctr
1013249423Sdim    OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR));
1014249423Sdim
1015218885Sdim    OutStreamer.SwitchSection(LSPSection);
1016218885Sdim    OutStreamer.EmitLabel(LazyPtr);
1017218885Sdim    OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
1018249423Sdim
1019249423Sdim    MCSymbol *DyldStubBindingHelper =
1020249423Sdim      OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper"));
1021249423Sdim    if (isPPC64) {
1022249423Sdim      // .quad dyld_stub_binding_helper
1023249423Sdim      OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8);
1024249423Sdim    } else {
1025249423Sdim      // .long dyld_stub_binding_helper
1026249423Sdim      OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4);
1027249423Sdim    }
1028218885Sdim  }
1029218885Sdim
1030218885Sdim  OutStreamer.AddBlankLine();
1031218885Sdim}
1032218885Sdim
1033218885Sdim
1034218885Sdimbool PPCDarwinAsmPrinter::doFinalization(Module &M) {
1035243830Sdim  bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64;
1036218885Sdim
1037218885Sdim  // Darwin/PPC always uses mach-o.
1038218885Sdim  const TargetLoweringObjectFileMachO &TLOFMacho =
1039218885Sdim    static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
1040218885Sdim  MachineModuleInfoMachO &MMIMacho =
1041218885Sdim    MMI->getObjFileInfo<MachineModuleInfoMachO>();
1042218885Sdim
1043218885Sdim  MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList();
1044218885Sdim  if (!Stubs.empty())
1045218885Sdim    EmitFunctionStubs(Stubs);
1046218885Sdim
1047218885Sdim  if (MAI->doesSupportExceptionHandling() && MMI) {
1048218885Sdim    // Add the (possibly multiple) personalities to the set of global values.
1049218885Sdim    // Only referenced functions get into the Personalities list.
1050218885Sdim    const std::vector<const Function*> &Personalities = MMI->getPersonalities();
1051218885Sdim    for (std::vector<const Function*>::const_iterator I = Personalities.begin(),
1052218885Sdim         E = Personalities.end(); I != E; ++I) {
1053218885Sdim      if (*I) {
1054218885Sdim        MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr");
1055218885Sdim        MachineModuleInfoImpl::StubValueTy &StubSym =
1056218885Sdim          MMIMacho.getGVStubEntry(NLPSym);
1057263508Sdim        StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(*I), true);
1058218885Sdim      }
1059218885Sdim    }
1060218885Sdim  }
1061218885Sdim
1062218885Sdim  // Output stubs for dynamically-linked functions.
1063218885Sdim  Stubs = MMIMacho.GetGVStubList();
1064218885Sdim
1065218885Sdim  // Output macho stubs for external and common global variables.
1066218885Sdim  if (!Stubs.empty()) {
1067218885Sdim    // Switch with ".non_lazy_symbol_pointer" directive.
1068218885Sdim    OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
1069218885Sdim    EmitAlignment(isPPC64 ? 3 : 2);
1070218885Sdim
1071218885Sdim    for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1072218885Sdim      // L_foo$stub:
1073218885Sdim      OutStreamer.EmitLabel(Stubs[i].first);
1074218885Sdim      //   .indirect_symbol _foo
1075218885Sdim      MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
1076218885Sdim      OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);
1077218885Sdim
1078218885Sdim      if (MCSym.getInt())
1079218885Sdim        // External to current translation unit.
1080249423Sdim        OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/);
1081218885Sdim      else
1082218885Sdim        // Internal to current translation unit.
1083218885Sdim        //
1084218885Sdim        // When we place the LSDA into the TEXT section, the type info pointers
1085218885Sdim        // need to be indirect and pc-rel. We accomplish this by using NLPs.
1086218885Sdim        // However, sometimes the types are local to the file. So we need to
1087218885Sdim        // fill in the value for the NLP in those cases.
1088218885Sdim        OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
1089218885Sdim                                                      OutContext),
1090249423Sdim                              isPPC64 ? 8 : 4/*size*/);
1091218885Sdim    }
1092218885Sdim
1093218885Sdim    Stubs.clear();
1094218885Sdim    OutStreamer.AddBlankLine();
1095218885Sdim  }
1096218885Sdim
1097218885Sdim  Stubs = MMIMacho.GetHiddenGVStubList();
1098218885Sdim  if (!Stubs.empty()) {
1099218885Sdim    OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
1100218885Sdim    EmitAlignment(isPPC64 ? 3 : 2);
1101218885Sdim
1102218885Sdim    for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1103218885Sdim      // L_foo$stub:
1104218885Sdim      OutStreamer.EmitLabel(Stubs[i].first);
1105218885Sdim      //   .long _foo
1106218885Sdim      OutStreamer.EmitValue(MCSymbolRefExpr::
1107218885Sdim                            Create(Stubs[i].second.getPointer(),
1108218885Sdim                                   OutContext),
1109249423Sdim                            isPPC64 ? 8 : 4/*size*/);
1110218885Sdim    }
1111218885Sdim
1112218885Sdim    Stubs.clear();
1113218885Sdim    OutStreamer.AddBlankLine();
1114218885Sdim  }
1115218885Sdim
1116218885Sdim  // Funny Darwin hack: This flag tells the linker that no global symbols
1117218885Sdim  // contain code that falls through to other global symbols (e.g. the obvious
1118218885Sdim  // implementation of multiple entry points).  If this doesn't occur, the
1119218885Sdim  // linker can safely perform dead code stripping.  Since LLVM never generates
1120218885Sdim  // code that does this, it is always safe to set.
1121218885Sdim  OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
1122218885Sdim
1123218885Sdim  return AsmPrinter::doFinalization(M);
1124218885Sdim}
1125218885Sdim
1126218885Sdim/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
1127218885Sdim/// for a MachineFunction to the given output stream, in a format that the
1128218885Sdim/// Darwin assembler can deal with.
1129218885Sdim///
1130218885Sdimstatic AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm,
1131218885Sdim                                           MCStreamer &Streamer) {
1132218885Sdim  const PPCSubtarget *Subtarget = &tm.getSubtarget<PPCSubtarget>();
1133218885Sdim
1134218885Sdim  if (Subtarget->isDarwin())
1135218885Sdim    return new PPCDarwinAsmPrinter(tm, Streamer);
1136218885Sdim  return new PPCLinuxAsmPrinter(tm, Streamer);
1137218885Sdim}
1138218885Sdim
1139218885Sdim// Force static initialization.
1140218885Sdimextern "C" void LLVMInitializePowerPCAsmPrinter() {
1141218885Sdim  TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass);
1142218885Sdim  TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass);
1143218885Sdim}
1144