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 "InstPrinter/PPCInstPrinter.h"
22 #include "MCTargetDesc/PPCPredicates.h"
23 #include "PPCSubtarget.h"
24 #include "PPCTargetMachine.h"
25 #include "llvm/ADT/MapVector.h"
26 #include "llvm/ADT/SmallString.h"
27 #include "llvm/ADT/StringExtras.h"
28 #include "llvm/Assembly/Writer.h"
29 #include "llvm/CodeGen/AsmPrinter.h"
30 #include "llvm/CodeGen/MachineFunctionPass.h"
31 #include "llvm/CodeGen/MachineInstr.h"
32 #include "llvm/CodeGen/MachineInstrBuilder.h"
33 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
34 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
35 #include "llvm/DebugInfo.h"
36 #include "llvm/IR/Constants.h"
37 #include "llvm/IR/DerivedTypes.h"
38 #include "llvm/IR/Module.h"
39 #include "llvm/MC/MCAsmInfo.h"
40 #include "llvm/MC/MCContext.h"
41 #include "llvm/MC/MCExpr.h"
42 #include "llvm/MC/MCInst.h"
43 #include "llvm/MC/MCInstBuilder.h"
44 #include "llvm/MC/MCSectionELF.h"
45 #include "llvm/MC/MCSectionMachO.h"
46 #include "llvm/MC/MCStreamer.h"
47 #include "llvm/MC/MCSymbol.h"
48 #include "llvm/Support/CommandLine.h"
49 #include "llvm/Support/Debug.h"
50 #include "llvm/Support/ELF.h"
51 #include "llvm/Support/ErrorHandling.h"
52 #include "llvm/Support/MathExtras.h"
53 #include "llvm/Support/TargetRegistry.h"
54 #include "llvm/Support/raw_ostream.h"
55 #include "llvm/Target/Mangler.h"
56 #include "llvm/Target/TargetInstrInfo.h"
57 #include "llvm/Target/TargetOptions.h"
58 #include "llvm/Target/TargetRegisterInfo.h"
59 using namespace llvm;
60
61 namespace {
62 class PPCAsmPrinter : public AsmPrinter {
63 protected:
64 MapVector<MCSymbol*, MCSymbol*> TOC;
65 const PPCSubtarget &Subtarget;
66 uint64_t TOCLabelID;
67 public:
PPCAsmPrinter(TargetMachine & TM,MCStreamer & Streamer)68 explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
69 : AsmPrinter(TM, Streamer),
70 Subtarget(TM.getSubtarget<PPCSubtarget>()), TOCLabelID(0) {}
71
getPassName() const72 virtual const char *getPassName() const {
73 return "PowerPC Assembly Printer";
74 }
75
76 MCSymbol *lookUpOrCreateTOCEntry(MCSymbol *Sym);
77
78 virtual void EmitInstruction(const MachineInstr *MI);
79
80 void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
81
82 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
83 unsigned AsmVariant, const char *ExtraCode,
84 raw_ostream &O);
85 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
86 unsigned AsmVariant, const char *ExtraCode,
87 raw_ostream &O);
88
getDebugValueLocation(const MachineInstr * MI) const89 MachineLocation getDebugValueLocation(const MachineInstr *MI) const {
90 MachineLocation Location;
91 assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
92 // Frame address. Currently handles register +- offset only.
93 if (MI->getOperand(0).isReg() && MI->getOperand(2).isImm())
94 Location.set(MI->getOperand(0).getReg(), MI->getOperand(2).getImm());
95 else {
96 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
97 }
98 return Location;
99 }
100 };
101
102 /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
103 class PPCLinuxAsmPrinter : public PPCAsmPrinter {
104 public:
PPCLinuxAsmPrinter(TargetMachine & TM,MCStreamer & Streamer)105 explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
106 : PPCAsmPrinter(TM, Streamer) {}
107
getPassName() const108 virtual const char *getPassName() const {
109 return "Linux PPC Assembly Printer";
110 }
111
112 bool doFinalization(Module &M);
113
114 virtual void EmitFunctionEntryLabel();
115
116 void EmitFunctionBodyEnd();
117 };
118
119 /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac
120 /// OS X
121 class PPCDarwinAsmPrinter : public PPCAsmPrinter {
122 public:
PPCDarwinAsmPrinter(TargetMachine & TM,MCStreamer & Streamer)123 explicit PPCDarwinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
124 : PPCAsmPrinter(TM, Streamer) {}
125
getPassName() const126 virtual const char *getPassName() const {
127 return "Darwin PPC Assembly Printer";
128 }
129
130 bool doFinalization(Module &M);
131 void EmitStartOfAsmFile(Module &M);
132
133 void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs);
134 };
135 } // end of anonymous namespace
136
137 /// stripRegisterPrefix - This method strips the character prefix from a
138 /// register name so that only the number is left. Used by for linux asm.
stripRegisterPrefix(const char * RegName)139 static const char *stripRegisterPrefix(const char *RegName) {
140 switch (RegName[0]) {
141 case 'r':
142 case 'f':
143 case 'v': return RegName + 1;
144 case 'c': if (RegName[1] == 'r') return RegName + 2;
145 }
146
147 return RegName;
148 }
149
printOperand(const MachineInstr * MI,unsigned OpNo,raw_ostream & O)150 void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
151 raw_ostream &O) {
152 const MachineOperand &MO = MI->getOperand(OpNo);
153
154 switch (MO.getType()) {
155 case MachineOperand::MO_Register: {
156 const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg());
157 // Linux assembler (Others?) does not take register mnemonics.
158 // FIXME - What about special registers used in mfspr/mtspr?
159 if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName);
160 O << RegName;
161 return;
162 }
163 case MachineOperand::MO_Immediate:
164 O << MO.getImm();
165 return;
166
167 case MachineOperand::MO_MachineBasicBlock:
168 O << *MO.getMBB()->getSymbol();
169 return;
170 case MachineOperand::MO_JumpTableIndex:
171 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
172 << '_' << MO.getIndex();
173 // FIXME: PIC relocation model
174 return;
175 case MachineOperand::MO_ConstantPoolIndex:
176 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
177 << '_' << MO.getIndex();
178 return;
179 case MachineOperand::MO_BlockAddress:
180 O << *GetBlockAddressSymbol(MO.getBlockAddress());
181 return;
182 case MachineOperand::MO_ExternalSymbol: {
183 // Computing the address of an external symbol, not calling it.
184 if (TM.getRelocationModel() == Reloc::Static) {
185 O << *GetExternalSymbolSymbol(MO.getSymbolName());
186 return;
187 }
188
189 MCSymbol *NLPSym =
190 OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+
191 MO.getSymbolName()+"$non_lazy_ptr");
192 MachineModuleInfoImpl::StubValueTy &StubSym =
193 MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(NLPSym);
194 if (StubSym.getPointer() == 0)
195 StubSym = MachineModuleInfoImpl::
196 StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true);
197
198 O << *NLPSym;
199 return;
200 }
201 case MachineOperand::MO_GlobalAddress: {
202 // Computing the address of a global symbol, not calling it.
203 const GlobalValue *GV = MO.getGlobal();
204 MCSymbol *SymToPrint;
205
206 // External or weakly linked global variables need non-lazily-resolved stubs
207 if (TM.getRelocationModel() != Reloc::Static &&
208 (GV->isDeclaration() || GV->isWeakForLinker())) {
209 if (!GV->hasHiddenVisibility()) {
210 SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
211 MachineModuleInfoImpl::StubValueTy &StubSym =
212 MMI->getObjFileInfo<MachineModuleInfoMachO>()
213 .getGVStubEntry(SymToPrint);
214 if (StubSym.getPointer() == 0)
215 StubSym = MachineModuleInfoImpl::
216 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
217 } else if (GV->isDeclaration() || GV->hasCommonLinkage() ||
218 GV->hasAvailableExternallyLinkage()) {
219 SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
220
221 MachineModuleInfoImpl::StubValueTy &StubSym =
222 MMI->getObjFileInfo<MachineModuleInfoMachO>().
223 getHiddenGVStubEntry(SymToPrint);
224 if (StubSym.getPointer() == 0)
225 StubSym = MachineModuleInfoImpl::
226 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
227 } else {
228 SymToPrint = Mang->getSymbol(GV);
229 }
230 } else {
231 SymToPrint = Mang->getSymbol(GV);
232 }
233
234 O << *SymToPrint;
235
236 printOffset(MO.getOffset(), O);
237 return;
238 }
239
240 default:
241 O << "<unknown operand type: " << MO.getType() << ">";
242 return;
243 }
244 }
245
246 /// PrintAsmOperand - Print out an operand for an inline asm expression.
247 ///
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)248 bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
249 unsigned AsmVariant,
250 const char *ExtraCode, raw_ostream &O) {
251 // Does this asm operand have a single letter operand modifier?
252 if (ExtraCode && ExtraCode[0]) {
253 if (ExtraCode[1] != 0) return true; // Unknown modifier.
254
255 switch (ExtraCode[0]) {
256 default:
257 // See if this is a generic print operand
258 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
259 case 'c': // Don't print "$" before a global var name or constant.
260 break; // PPC never has a prefix.
261 case 'L': // Write second word of DImode reference.
262 // Verify that this operand has two consecutive registers.
263 if (!MI->getOperand(OpNo).isReg() ||
264 OpNo+1 == MI->getNumOperands() ||
265 !MI->getOperand(OpNo+1).isReg())
266 return true;
267 ++OpNo; // Return the high-part.
268 break;
269 case 'I':
270 // Write 'i' if an integer constant, otherwise nothing. Used to print
271 // addi vs add, etc.
272 if (MI->getOperand(OpNo).isImm())
273 O << "i";
274 return false;
275 }
276 }
277
278 printOperand(MI, OpNo, O);
279 return false;
280 }
281
282 // At the moment, all inline asm memory operands are a single register.
283 // In any case, the output of this routine should always be just one
284 // assembler operand.
285
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)286 bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
287 unsigned AsmVariant,
288 const char *ExtraCode,
289 raw_ostream &O) {
290 if (ExtraCode && ExtraCode[0]) {
291 if (ExtraCode[1] != 0) return true; // Unknown modifier.
292
293 switch (ExtraCode[0]) {
294 default: return true; // Unknown modifier.
295 case 'y': // A memory reference for an X-form instruction
296 {
297 const char *RegName = "r0";
298 if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName);
299 O << RegName << ", ";
300 printOperand(MI, OpNo, O);
301 return false;
302 }
303 }
304 }
305
306 assert(MI->getOperand(OpNo).isReg());
307 O << "0(";
308 printOperand(MI, OpNo, O);
309 O << ")";
310 return false;
311 }
312
313
314 /// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry
315 /// exists for it. If not, create one. Then return a symbol that references
316 /// the TOC entry.
lookUpOrCreateTOCEntry(MCSymbol * Sym)317 MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MCSymbol *Sym) {
318
319 MCSymbol *&TOCEntry = TOC[Sym];
320
321 // To avoid name clash check if the name already exists.
322 while (TOCEntry == 0) {
323 if (OutContext.LookupSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
324 "C" + Twine(TOCLabelID++)) == 0) {
325 TOCEntry = GetTempSymbol("C", TOCLabelID);
326 }
327 }
328
329 return TOCEntry;
330 }
331
332
333 /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
334 /// the current output stream.
335 ///
EmitInstruction(const MachineInstr * MI)336 void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
337 MCInst TmpInst;
338
339 // Lower multi-instruction pseudo operations.
340 switch (MI->getOpcode()) {
341 default: break;
342 case TargetOpcode::DBG_VALUE: {
343 if (!isVerbose() || !OutStreamer.hasRawTextSupport()) return;
344
345 SmallString<32> Str;
346 raw_svector_ostream O(Str);
347 unsigned NOps = MI->getNumOperands();
348 assert(NOps==4);
349 O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
350 // cast away const; DIetc do not take const operands for some reason.
351 DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
352 O << V.getName();
353 O << " <- ";
354 // Frame address. Currently handles register +- offset only.
355 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
356 O << '['; printOperand(MI, 0, O); O << '+'; printOperand(MI, 1, O);
357 O << ']';
358 O << "+";
359 printOperand(MI, NOps-2, O);
360 OutStreamer.EmitRawText(O.str());
361 return;
362 }
363
364 case PPC::MovePCtoLR:
365 case PPC::MovePCtoLR8: {
366 // Transform %LR = MovePCtoLR
367 // Into this, where the label is the PIC base:
368 // bl L1$pb
369 // L1$pb:
370 MCSymbol *PICBase = MF->getPICBaseSymbol();
371
372 // Emit the 'bl'.
373 OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL_Darwin) // Darwin vs SVR4 doesn't matter here.
374 // FIXME: We would like an efficient form for this, so we don't have to do
375 // a lot of extra uniquing.
376 .addExpr(MCSymbolRefExpr::Create(PICBase, OutContext)));
377
378 // Emit the label.
379 OutStreamer.EmitLabel(PICBase);
380 return;
381 }
382 case PPC::LDtocJTI:
383 case PPC::LDtocCPT:
384 case PPC::LDtoc: {
385 // Transform %X3 = LDtoc <ga:@min1>, %X2
386 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
387
388 // Change the opcode to LD, and the global address operand to be a
389 // reference to the TOC entry we will synthesize later.
390 TmpInst.setOpcode(PPC::LD);
391 const MachineOperand &MO = MI->getOperand(1);
392
393 // Map symbol -> label of TOC entry
394 assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());
395 MCSymbol *MOSymbol = 0;
396 if (MO.isGlobal())
397 MOSymbol = Mang->getSymbol(MO.getGlobal());
398 else if (MO.isCPI())
399 MOSymbol = GetCPISymbol(MO.getIndex());
400 else if (MO.isJTI())
401 MOSymbol = GetJTISymbol(MO.getIndex());
402
403 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
404
405 const MCExpr *Exp =
406 MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC_ENTRY,
407 OutContext);
408 TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
409 OutStreamer.EmitInstruction(TmpInst);
410 return;
411 }
412
413 case PPC::ADDIStocHA: {
414 // Transform %Xd = ADDIStocHA %X2, <ga:@sym>
415 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
416
417 // Change the opcode to ADDIS8. If the global address is external,
418 // has common linkage, is a function address, or is a jump table
419 // address, then generate a TOC entry and reference that. Otherwise
420 // reference the symbol directly.
421 TmpInst.setOpcode(PPC::ADDIS8);
422 const MachineOperand &MO = MI->getOperand(2);
423 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI()) &&
424 "Invalid operand for ADDIStocHA!");
425 MCSymbol *MOSymbol = 0;
426 bool IsExternal = false;
427 bool IsFunction = false;
428 bool IsCommon = false;
429 bool IsAvailExt = false;
430
431 if (MO.isGlobal()) {
432 const GlobalValue *GValue = MO.getGlobal();
433 const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
434 const GlobalValue *RealGValue = GAlias ?
435 GAlias->resolveAliasedGlobal(false) : GValue;
436 MOSymbol = Mang->getSymbol(RealGValue);
437 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
438 IsExternal = GVar && !GVar->hasInitializer();
439 IsCommon = GVar && RealGValue->hasCommonLinkage();
440 IsFunction = !GVar;
441 IsAvailExt = GVar && RealGValue->hasAvailableExternallyLinkage();
442 } else if (MO.isCPI())
443 MOSymbol = GetCPISymbol(MO.getIndex());
444 else if (MO.isJTI())
445 MOSymbol = GetJTISymbol(MO.getIndex());
446
447 if (IsExternal || IsFunction || IsCommon || IsAvailExt || MO.isJTI())
448 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
449
450 const MCExpr *Exp =
451 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC16_HA,
452 OutContext);
453 TmpInst.getOperand(2) = MCOperand::CreateExpr(Exp);
454 OutStreamer.EmitInstruction(TmpInst);
455 return;
456 }
457 case PPC::LDtocL: {
458 // Transform %Xd = LDtocL <ga:@sym>, %Xs
459 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
460
461 // Change the opcode to LDrs, which is a form of LD with the offset
462 // specified by a SymbolLo. If the global address is external, has
463 // common linkage, or is a jump table address, then reference the
464 // associated TOC entry. Otherwise reference the symbol directly.
465 TmpInst.setOpcode(PPC::LDrs);
466 const MachineOperand &MO = MI->getOperand(1);
467 assert((MO.isGlobal() || MO.isJTI() || MO.isCPI()) &&
468 "Invalid operand for LDtocL!");
469 MCSymbol *MOSymbol = 0;
470
471 if (MO.isJTI())
472 MOSymbol = lookUpOrCreateTOCEntry(GetJTISymbol(MO.getIndex()));
473 else if (MO.isCPI())
474 MOSymbol = GetCPISymbol(MO.getIndex());
475 else if (MO.isGlobal()) {
476 const GlobalValue *GValue = MO.getGlobal();
477 const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
478 const GlobalValue *RealGValue = GAlias ?
479 GAlias->resolveAliasedGlobal(false) : GValue;
480 MOSymbol = Mang->getSymbol(RealGValue);
481 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
482
483 if (!GVar || !GVar->hasInitializer() || RealGValue->hasCommonLinkage() ||
484 RealGValue->hasAvailableExternallyLinkage())
485 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
486 }
487
488 const MCExpr *Exp =
489 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC16_LO,
490 OutContext);
491 TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
492 OutStreamer.EmitInstruction(TmpInst);
493 return;
494 }
495 case PPC::ADDItocL: {
496 // Transform %Xd = ADDItocL %Xs, <ga:@sym>
497 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
498
499 // Change the opcode to ADDI8L. If the global address is external, then
500 // generate a TOC entry and reference that. Otherwise reference the
501 // symbol directly.
502 TmpInst.setOpcode(PPC::ADDI8L);
503 const MachineOperand &MO = MI->getOperand(2);
504 assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL");
505 MCSymbol *MOSymbol = 0;
506 bool IsExternal = false;
507 bool IsFunction = false;
508
509 if (MO.isGlobal()) {
510 const GlobalValue *GValue = MO.getGlobal();
511 const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
512 const GlobalValue *RealGValue = GAlias ?
513 GAlias->resolveAliasedGlobal(false) : GValue;
514 MOSymbol = Mang->getSymbol(RealGValue);
515 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
516 IsExternal = GVar && !GVar->hasInitializer();
517 IsFunction = !GVar;
518 } else if (MO.isCPI())
519 MOSymbol = GetCPISymbol(MO.getIndex());
520
521 if (IsFunction || IsExternal)
522 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
523
524 const MCExpr *Exp =
525 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC16_LO,
526 OutContext);
527 TmpInst.getOperand(2) = MCOperand::CreateExpr(Exp);
528 OutStreamer.EmitInstruction(TmpInst);
529 return;
530 }
531 case PPC::ADDISgotTprelHA: {
532 // Transform: %Xd = ADDISgotTprelHA %X2, <ga:@sym>
533 // Into: %Xd = ADDIS8 %X2, sym@got@tlsgd@ha
534 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
535 const MachineOperand &MO = MI->getOperand(2);
536 const GlobalValue *GValue = MO.getGlobal();
537 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
538 const MCExpr *SymGotTprel =
539 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL16_HA,
540 OutContext);
541 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8)
542 .addReg(MI->getOperand(0).getReg())
543 .addReg(PPC::X2)
544 .addExpr(SymGotTprel));
545 return;
546 }
547 case PPC::LDgotTprelL: {
548 // Transform %Xd = LDgotTprelL <ga:@sym>, %Xs
549 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
550
551 // Change the opcode to LDrs, which is a form of LD with the offset
552 // specified by a SymbolLo.
553 TmpInst.setOpcode(PPC::LDrs);
554 const MachineOperand &MO = MI->getOperand(1);
555 const GlobalValue *GValue = MO.getGlobal();
556 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
557 const MCExpr *Exp =
558 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL16_LO,
559 OutContext);
560 TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
561 OutStreamer.EmitInstruction(TmpInst);
562 return;
563 }
564 case PPC::ADDIStlsgdHA: {
565 // Transform: %Xd = ADDIStlsgdHA %X2, <ga:@sym>
566 // Into: %Xd = ADDIS8 %X2, sym@got@tlsgd@ha
567 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
568 const MachineOperand &MO = MI->getOperand(2);
569 const GlobalValue *GValue = MO.getGlobal();
570 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
571 const MCExpr *SymGotTlsGD =
572 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_HA,
573 OutContext);
574 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8)
575 .addReg(MI->getOperand(0).getReg())
576 .addReg(PPC::X2)
577 .addExpr(SymGotTlsGD));
578 return;
579 }
580 case PPC::ADDItlsgdL: {
581 // Transform: %Xd = ADDItlsgdL %Xs, <ga:@sym>
582 // Into: %Xd = ADDI8L %Xs, sym@got@tlsgd@l
583 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
584 const MachineOperand &MO = MI->getOperand(2);
585 const GlobalValue *GValue = MO.getGlobal();
586 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
587 const MCExpr *SymGotTlsGD =
588 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_LO,
589 OutContext);
590 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8L)
591 .addReg(MI->getOperand(0).getReg())
592 .addReg(MI->getOperand(1).getReg())
593 .addExpr(SymGotTlsGD));
594 return;
595 }
596 case PPC::GETtlsADDR: {
597 // Transform: %X3 = GETtlsADDR %X3, <ga:@sym>
598 // Into: BL8_NOP_ELF_TLSGD __tls_get_addr(sym@tlsgd)
599 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
600
601 StringRef Name = "__tls_get_addr";
602 MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);
603 const MCSymbolRefExpr *TlsRef =
604 MCSymbolRefExpr::Create(TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext);
605 const MachineOperand &MO = MI->getOperand(2);
606 const GlobalValue *GValue = MO.getGlobal();
607 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
608 const MCExpr *SymVar =
609 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSGD,
610 OutContext);
611 OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL8_NOP_ELF_TLSGD)
612 .addExpr(TlsRef)
613 .addExpr(SymVar));
614 return;
615 }
616 case PPC::ADDIStlsldHA: {
617 // Transform: %Xd = ADDIStlsldHA %X2, <ga:@sym>
618 // Into: %Xd = ADDIS8 %X2, sym@got@tlsld@ha
619 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
620 const MachineOperand &MO = MI->getOperand(2);
621 const GlobalValue *GValue = MO.getGlobal();
622 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
623 const MCExpr *SymGotTlsLD =
624 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA,
625 OutContext);
626 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8)
627 .addReg(MI->getOperand(0).getReg())
628 .addReg(PPC::X2)
629 .addExpr(SymGotTlsLD));
630 return;
631 }
632 case PPC::ADDItlsldL: {
633 // Transform: %Xd = ADDItlsldL %Xs, <ga:@sym>
634 // Into: %Xd = ADDI8L %Xs, sym@got@tlsld@l
635 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
636 const MachineOperand &MO = MI->getOperand(2);
637 const GlobalValue *GValue = MO.getGlobal();
638 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
639 const MCExpr *SymGotTlsLD =
640 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO,
641 OutContext);
642 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8L)
643 .addReg(MI->getOperand(0).getReg())
644 .addReg(MI->getOperand(1).getReg())
645 .addExpr(SymGotTlsLD));
646 return;
647 }
648 case PPC::GETtlsldADDR: {
649 // Transform: %X3 = GETtlsldADDR %X3, <ga:@sym>
650 // Into: BL8_NOP_ELF_TLSLD __tls_get_addr(sym@tlsld)
651 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
652
653 StringRef Name = "__tls_get_addr";
654 MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);
655 const MCSymbolRefExpr *TlsRef =
656 MCSymbolRefExpr::Create(TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext);
657 const MachineOperand &MO = MI->getOperand(2);
658 const GlobalValue *GValue = MO.getGlobal();
659 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
660 const MCExpr *SymVar =
661 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSLD,
662 OutContext);
663 OutStreamer.EmitInstruction(MCInstBuilder(PPC::BL8_NOP_ELF_TLSLD)
664 .addExpr(TlsRef)
665 .addExpr(SymVar));
666 return;
667 }
668 case PPC::ADDISdtprelHA: {
669 // Transform: %Xd = ADDISdtprelHA %X3, <ga:@sym>
670 // Into: %Xd = ADDIS8 %X3, sym@dtprel@ha
671 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
672 const MachineOperand &MO = MI->getOperand(2);
673 const GlobalValue *GValue = MO.getGlobal();
674 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
675 const MCExpr *SymDtprel =
676 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL16_HA,
677 OutContext);
678 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS8)
679 .addReg(MI->getOperand(0).getReg())
680 .addReg(PPC::X3)
681 .addExpr(SymDtprel));
682 return;
683 }
684 case PPC::ADDIdtprelL: {
685 // Transform: %Xd = ADDIdtprelL %Xs, <ga:@sym>
686 // Into: %Xd = ADDI8L %Xs, sym@dtprel@l
687 assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
688 const MachineOperand &MO = MI->getOperand(2);
689 const GlobalValue *GValue = MO.getGlobal();
690 MCSymbol *MOSymbol = Mang->getSymbol(GValue);
691 const MCExpr *SymDtprel =
692 MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL16_LO,
693 OutContext);
694 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDI8L)
695 .addReg(MI->getOperand(0).getReg())
696 .addReg(MI->getOperand(1).getReg())
697 .addExpr(SymDtprel));
698 return;
699 }
700 case PPC::MFCRpseud:
701 case PPC::MFCR8pseud:
702 // Transform: %R3 = MFCRpseud %CR7
703 // Into: %R3 = MFCR ;; cr7
704 OutStreamer.AddComment(PPCInstPrinter::
705 getRegisterName(MI->getOperand(1).getReg()));
706 OutStreamer.EmitInstruction(MCInstBuilder(Subtarget.isPPC64() ? PPC::MFCR8 : PPC::MFCR)
707 .addReg(MI->getOperand(0).getReg()));
708 return;
709 case PPC::SYNC:
710 // In Book E sync is called msync, handle this special case here...
711 if (Subtarget.isBookE()) {
712 OutStreamer.EmitRawText(StringRef("\tmsync"));
713 return;
714 }
715 }
716
717 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
718 OutStreamer.EmitInstruction(TmpInst);
719 }
720
EmitFunctionEntryLabel()721 void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
722 if (!Subtarget.isPPC64()) // linux/ppc32 - Normal entry label.
723 return AsmPrinter::EmitFunctionEntryLabel();
724
725 // Emit an official procedure descriptor.
726 const MCSection *Current = OutStreamer.getCurrentSection();
727 const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".opd",
728 ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
729 SectionKind::getReadOnly());
730 OutStreamer.SwitchSection(Section);
731 OutStreamer.EmitLabel(CurrentFnSym);
732 OutStreamer.EmitValueToAlignment(8);
733 MCSymbol *Symbol1 =
734 OutContext.GetOrCreateSymbol(".L." + Twine(CurrentFnSym->getName()));
735 // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function
736 // entry point.
737 OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol1, OutContext),
738 8 /*size*/);
739 MCSymbol *Symbol2 = OutContext.GetOrCreateSymbol(StringRef(".TOC."));
740 // Generates a R_PPC64_TOC relocation for TOC base insertion.
741 OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol2,
742 MCSymbolRefExpr::VK_PPC_TOC, OutContext),
743 8/*size*/);
744 // Emit a null environment pointer.
745 OutStreamer.EmitIntValue(0, 8 /* size */);
746 OutStreamer.SwitchSection(Current);
747
748 MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol(
749 ".L." + Twine(CurrentFnSym->getName()));
750 OutStreamer.EmitLabel(RealFnSym);
751 CurrentFnSymForSize = RealFnSym;
752 }
753
754
doFinalization(Module & M)755 bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
756 const DataLayout *TD = TM.getDataLayout();
757
758 bool isPPC64 = TD->getPointerSizeInBits() == 64;
759
760 if (isPPC64 && !TOC.empty()) {
761 const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc",
762 ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
763 SectionKind::getReadOnly());
764 OutStreamer.SwitchSection(Section);
765
766 for (MapVector<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(),
767 E = TOC.end(); I != E; ++I) {
768 OutStreamer.EmitLabel(I->second);
769 MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName());
770 OutStreamer.EmitTCEntry(*S);
771 }
772 }
773
774 MachineModuleInfoELF &MMIELF =
775 MMI->getObjFileInfo<MachineModuleInfoELF>();
776
777 MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
778 if (!Stubs.empty()) {
779 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
780 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
781 // L_foo$stub:
782 OutStreamer.EmitLabel(Stubs[i].first);
783 // .long _foo
784 OutStreamer.EmitValue(MCSymbolRefExpr::Create(Stubs[i].second.getPointer(),
785 OutContext),
786 isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/);
787 }
788
789 Stubs.clear();
790 OutStreamer.AddBlankLine();
791 }
792
793 return AsmPrinter::doFinalization(M);
794 }
795
796 /// EmitFunctionBodyEnd - Print the traceback table before the .size
797 /// directive.
798 ///
EmitFunctionBodyEnd()799 void PPCLinuxAsmPrinter::EmitFunctionBodyEnd() {
800 // Only the 64-bit target requires a traceback table. For now,
801 // we only emit the word of zeroes that GDB requires to find
802 // the end of the function, and zeroes for the eight-byte
803 // mandatory fields.
804 // FIXME: We should fill in the eight-byte mandatory fields as described in
805 // the PPC64 ELF ABI (this is a low-priority item because GDB does not
806 // currently make use of these fields).
807 if (Subtarget.isPPC64()) {
808 OutStreamer.EmitIntValue(0, 4/*size*/);
809 OutStreamer.EmitIntValue(0, 8/*size*/);
810 }
811 }
812
EmitStartOfAsmFile(Module & M)813 void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) {
814 static const char *const CPUDirectives[] = {
815 "",
816 "ppc",
817 "ppc440",
818 "ppc601",
819 "ppc602",
820 "ppc603",
821 "ppc7400",
822 "ppc750",
823 "ppc970",
824 "ppcA2",
825 "ppce500mc",
826 "ppce5500",
827 "power3",
828 "power4",
829 "power5",
830 "power5x",
831 "power6",
832 "power6x",
833 "power7",
834 "ppc64"
835 };
836
837 unsigned Directive = Subtarget.getDarwinDirective();
838 if (Subtarget.hasMFOCRF() && Directive < PPC::DIR_970)
839 Directive = PPC::DIR_970;
840 if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400)
841 Directive = PPC::DIR_7400;
842 if (Subtarget.isPPC64() && Directive < PPC::DIR_64)
843 Directive = PPC::DIR_64;
844 assert(Directive <= PPC::DIR_64 && "Directive out of range.");
845
846 // FIXME: This is a total hack, finish mc'izing the PPC backend.
847 if (OutStreamer.hasRawTextSupport()) {
848 assert(Directive < sizeof(CPUDirectives) / sizeof(*CPUDirectives) &&
849 "CPUDirectives[] might not be up-to-date!");
850 OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive]));
851 }
852
853 // Prime text sections so they are adjacent. This reduces the likelihood a
854 // large data or debug section causes a branch to exceed 16M limit.
855 const TargetLoweringObjectFileMachO &TLOFMacho =
856 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
857 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
858 if (TM.getRelocationModel() == Reloc::PIC_) {
859 OutStreamer.SwitchSection(
860 OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
861 MCSectionMachO::S_SYMBOL_STUBS |
862 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
863 32, SectionKind::getText()));
864 } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) {
865 OutStreamer.SwitchSection(
866 OutContext.getMachOSection("__TEXT","__symbol_stub1",
867 MCSectionMachO::S_SYMBOL_STUBS |
868 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
869 16, SectionKind::getText()));
870 }
871 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
872 }
873
GetLazyPtr(MCSymbol * Sym,MCContext & Ctx)874 static MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) {
875 // Remove $stub suffix, add $lazy_ptr.
876 StringRef NoStub = Sym->getName().substr(0, Sym->getName().size()-5);
877 return Ctx.GetOrCreateSymbol(NoStub + "$lazy_ptr");
878 }
879
GetAnonSym(MCSymbol * Sym,MCContext & Ctx)880 static MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) {
881 // Add $tmp suffix to $stub, yielding $stub$tmp.
882 return Ctx.GetOrCreateSymbol(Sym->getName() + "$tmp");
883 }
884
885 void PPCDarwinAsmPrinter::
EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy & Stubs)886 EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) {
887 bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64;
888
889 const TargetLoweringObjectFileMachO &TLOFMacho =
890 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
891
892 // .lazy_symbol_pointer
893 const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection();
894
895 // Output stubs for dynamically-linked functions
896 if (TM.getRelocationModel() == Reloc::PIC_) {
897 const MCSection *StubSection =
898 OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
899 MCSectionMachO::S_SYMBOL_STUBS |
900 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
901 32, SectionKind::getText());
902 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
903 OutStreamer.SwitchSection(StubSection);
904 EmitAlignment(4);
905
906 MCSymbol *Stub = Stubs[i].first;
907 MCSymbol *RawSym = Stubs[i].second.getPointer();
908 MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
909 MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext);
910
911 OutStreamer.EmitLabel(Stub);
912 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
913
914 // mflr r0
915 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R0));
916 // FIXME: MCize this.
917 OutStreamer.EmitRawText("\tbcl 20, 31, " + Twine(AnonSymbol->getName()));
918 OutStreamer.EmitLabel(AnonSymbol);
919 // mflr r11
920 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MFLR).addReg(PPC::R11));
921 // addis r11, r11, ha16(LazyPtr - AnonSymbol)
922 const MCExpr *Sub =
923 MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(LazyPtr, OutContext),
924 MCSymbolRefExpr::Create(AnonSymbol, OutContext),
925 OutContext);
926 OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS)
927 .addReg(PPC::R11)
928 .addReg(PPC::R11)
929 .addExpr(Sub));
930 // mtlr r0
931 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTLR).addReg(PPC::R0));
932
933 // ldu r12, lo16(LazyPtr - AnonSymbol)(r11)
934 // lwzu r12, lo16(LazyPtr - AnonSymbol)(r11)
935 OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU)
936 .addReg(PPC::R12)
937 .addExpr(Sub).addExpr(Sub)
938 .addReg(PPC::R11));
939 // mtctr r12
940 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12));
941 // bctr
942 OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR));
943
944 OutStreamer.SwitchSection(LSPSection);
945 OutStreamer.EmitLabel(LazyPtr);
946 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
947
948 MCSymbol *DyldStubBindingHelper =
949 OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper"));
950 if (isPPC64) {
951 // .quad dyld_stub_binding_helper
952 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8);
953 } else {
954 // .long dyld_stub_binding_helper
955 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4);
956 }
957 }
958 OutStreamer.AddBlankLine();
959 return;
960 }
961
962 const MCSection *StubSection =
963 OutContext.getMachOSection("__TEXT","__symbol_stub1",
964 MCSectionMachO::S_SYMBOL_STUBS |
965 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
966 16, SectionKind::getText());
967 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
968 MCSymbol *Stub = Stubs[i].first;
969 MCSymbol *RawSym = Stubs[i].second.getPointer();
970 MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
971
972 OutStreamer.SwitchSection(StubSection);
973 EmitAlignment(4);
974 OutStreamer.EmitLabel(Stub);
975 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
976 // lis r11, ha16(LazyPtr)
977 const MCExpr *LazyPtrHa16 =
978 MCSymbolRefExpr::Create(LazyPtr, MCSymbolRefExpr::VK_PPC_DARWIN_HA16,
979 OutContext);
980 OutStreamer.EmitInstruction(MCInstBuilder(PPC::LIS)
981 .addReg(PPC::R11)
982 .addExpr(LazyPtrHa16));
983
984 const MCExpr *LazyPtrLo16 =
985 MCSymbolRefExpr::Create(LazyPtr, MCSymbolRefExpr::VK_PPC_DARWIN_LO16,
986 OutContext);
987 // ldu r12, lo16(LazyPtr)(r11)
988 // lwzu r12, lo16(LazyPtr)(r11)
989 OutStreamer.EmitInstruction(MCInstBuilder(isPPC64 ? PPC::LDU : PPC::LWZU)
990 .addReg(PPC::R12)
991 .addExpr(LazyPtrLo16).addExpr(LazyPtrLo16)
992 .addReg(PPC::R11));
993
994 // mtctr r12
995 OutStreamer.EmitInstruction(MCInstBuilder(PPC::MTCTR).addReg(PPC::R12));
996 // bctr
997 OutStreamer.EmitInstruction(MCInstBuilder(PPC::BCTR));
998
999 OutStreamer.SwitchSection(LSPSection);
1000 OutStreamer.EmitLabel(LazyPtr);
1001 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
1002
1003 MCSymbol *DyldStubBindingHelper =
1004 OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper"));
1005 if (isPPC64) {
1006 // .quad dyld_stub_binding_helper
1007 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8);
1008 } else {
1009 // .long dyld_stub_binding_helper
1010 OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4);
1011 }
1012 }
1013
1014 OutStreamer.AddBlankLine();
1015 }
1016
1017
doFinalization(Module & M)1018 bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
1019 bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64;
1020
1021 // Darwin/PPC always uses mach-o.
1022 const TargetLoweringObjectFileMachO &TLOFMacho =
1023 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
1024 MachineModuleInfoMachO &MMIMacho =
1025 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1026
1027 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList();
1028 if (!Stubs.empty())
1029 EmitFunctionStubs(Stubs);
1030
1031 if (MAI->doesSupportExceptionHandling() && MMI) {
1032 // Add the (possibly multiple) personalities to the set of global values.
1033 // Only referenced functions get into the Personalities list.
1034 const std::vector<const Function*> &Personalities = MMI->getPersonalities();
1035 for (std::vector<const Function*>::const_iterator I = Personalities.begin(),
1036 E = Personalities.end(); I != E; ++I) {
1037 if (*I) {
1038 MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr");
1039 MachineModuleInfoImpl::StubValueTy &StubSym =
1040 MMIMacho.getGVStubEntry(NLPSym);
1041 StubSym = MachineModuleInfoImpl::StubValueTy(Mang->getSymbol(*I), true);
1042 }
1043 }
1044 }
1045
1046 // Output stubs for dynamically-linked functions.
1047 Stubs = MMIMacho.GetGVStubList();
1048
1049 // Output macho stubs for external and common global variables.
1050 if (!Stubs.empty()) {
1051 // Switch with ".non_lazy_symbol_pointer" directive.
1052 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
1053 EmitAlignment(isPPC64 ? 3 : 2);
1054
1055 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1056 // L_foo$stub:
1057 OutStreamer.EmitLabel(Stubs[i].first);
1058 // .indirect_symbol _foo
1059 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
1060 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);
1061
1062 if (MCSym.getInt())
1063 // External to current translation unit.
1064 OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/);
1065 else
1066 // Internal to current translation unit.
1067 //
1068 // When we place the LSDA into the TEXT section, the type info pointers
1069 // need to be indirect and pc-rel. We accomplish this by using NLPs.
1070 // However, sometimes the types are local to the file. So we need to
1071 // fill in the value for the NLP in those cases.
1072 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
1073 OutContext),
1074 isPPC64 ? 8 : 4/*size*/);
1075 }
1076
1077 Stubs.clear();
1078 OutStreamer.AddBlankLine();
1079 }
1080
1081 Stubs = MMIMacho.GetHiddenGVStubList();
1082 if (!Stubs.empty()) {
1083 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
1084 EmitAlignment(isPPC64 ? 3 : 2);
1085
1086 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1087 // L_foo$stub:
1088 OutStreamer.EmitLabel(Stubs[i].first);
1089 // .long _foo
1090 OutStreamer.EmitValue(MCSymbolRefExpr::
1091 Create(Stubs[i].second.getPointer(),
1092 OutContext),
1093 isPPC64 ? 8 : 4/*size*/);
1094 }
1095
1096 Stubs.clear();
1097 OutStreamer.AddBlankLine();
1098 }
1099
1100 // Funny Darwin hack: This flag tells the linker that no global symbols
1101 // contain code that falls through to other global symbols (e.g. the obvious
1102 // implementation of multiple entry points). If this doesn't occur, the
1103 // linker can safely perform dead code stripping. Since LLVM never generates
1104 // code that does this, it is always safe to set.
1105 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
1106
1107 return AsmPrinter::doFinalization(M);
1108 }
1109
1110 /// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
1111 /// for a MachineFunction to the given output stream, in a format that the
1112 /// Darwin assembler can deal with.
1113 ///
createPPCAsmPrinterPass(TargetMachine & tm,MCStreamer & Streamer)1114 static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm,
1115 MCStreamer &Streamer) {
1116 const PPCSubtarget *Subtarget = &tm.getSubtarget<PPCSubtarget>();
1117
1118 if (Subtarget->isDarwin())
1119 return new PPCDarwinAsmPrinter(tm, Streamer);
1120 return new PPCLinuxAsmPrinter(tm, Streamer);
1121 }
1122
1123 // Force static initialization.
LLVMInitializePowerPCAsmPrinter()1124 extern "C" void LLVMInitializePowerPCAsmPrinter() {
1125 TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass);
1126 TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass);
1127 }
1128