1//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a printer that converts from our internal representation
10// of machine-dependent LLVM code to PowerPC assembly language. This printer is
11// the output mechanism used by `llc'.
12//
13// Documentation at http://developer.apple.com/documentation/DeveloperTools/
14// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
15//
16//===----------------------------------------------------------------------===//
17
18#include "MCTargetDesc/PPCInstPrinter.h"
19#include "MCTargetDesc/PPCMCExpr.h"
20#include "MCTargetDesc/PPCMCTargetDesc.h"
21#include "MCTargetDesc/PPCPredicates.h"
22#include "PPC.h"
23#include "PPCInstrInfo.h"
24#include "PPCMachineFunctionInfo.h"
25#include "PPCSubtarget.h"
26#include "PPCTargetMachine.h"
27#include "PPCTargetStreamer.h"
28#include "TargetInfo/PowerPCTargetInfo.h"
29#include "llvm/ADT/MapVector.h"
30#include "llvm/ADT/SmallPtrSet.h"
31#include "llvm/ADT/Statistic.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/ADT/StringRef.h"
34#include "llvm/ADT/Twine.h"
35#include "llvm/BinaryFormat/ELF.h"
36#include "llvm/CodeGen/AsmPrinter.h"
37#include "llvm/CodeGen/MachineBasicBlock.h"
38#include "llvm/CodeGen/MachineFrameInfo.h"
39#include "llvm/CodeGen/MachineFunction.h"
40#include "llvm/CodeGen/MachineInstr.h"
41#include "llvm/CodeGen/MachineModuleInfoImpls.h"
42#include "llvm/CodeGen/MachineOperand.h"
43#include "llvm/CodeGen/MachineRegisterInfo.h"
44#include "llvm/CodeGen/StackMaps.h"
45#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
46#include "llvm/IR/DataLayout.h"
47#include "llvm/IR/GlobalValue.h"
48#include "llvm/IR/GlobalVariable.h"
49#include "llvm/IR/Module.h"
50#include "llvm/MC/MCAsmInfo.h"
51#include "llvm/MC/MCContext.h"
52#include "llvm/MC/MCDirectives.h"
53#include "llvm/MC/MCExpr.h"
54#include "llvm/MC/MCInst.h"
55#include "llvm/MC/MCInstBuilder.h"
56#include "llvm/MC/MCSectionELF.h"
57#include "llvm/MC/MCSectionXCOFF.h"
58#include "llvm/MC/MCStreamer.h"
59#include "llvm/MC/MCSymbol.h"
60#include "llvm/MC/MCSymbolELF.h"
61#include "llvm/MC/MCSymbolXCOFF.h"
62#include "llvm/MC/SectionKind.h"
63#include "llvm/MC/TargetRegistry.h"
64#include "llvm/Support/Casting.h"
65#include "llvm/Support/CodeGen.h"
66#include "llvm/Support/Debug.h"
67#include "llvm/Support/Error.h"
68#include "llvm/Support/ErrorHandling.h"
69#include "llvm/Support/MathExtras.h"
70#include "llvm/Support/Process.h"
71#include "llvm/Support/Threading.h"
72#include "llvm/Support/raw_ostream.h"
73#include "llvm/Target/TargetMachine.h"
74#include "llvm/TargetParser/Triple.h"
75#include "llvm/Transforms/Utils/ModuleUtils.h"
76#include <algorithm>
77#include <cassert>
78#include <cstdint>
79#include <memory>
80#include <new>
81
82using namespace llvm;
83using namespace llvm::XCOFF;
84
85#define DEBUG_TYPE "asmprinter"
86
87STATISTIC(NumTOCEntries, "Number of Total TOC Entries Emitted.");
88STATISTIC(NumTOCConstPool, "Number of Constant Pool TOC Entries.");
89STATISTIC(NumTOCGlobalInternal,
90 "Number of Internal Linkage Global TOC Entries.");
91STATISTIC(NumTOCGlobalExternal,
92 "Number of External Linkage Global TOC Entries.");
93STATISTIC(NumTOCJumpTable, "Number of Jump Table TOC Entries.");
94STATISTIC(NumTOCThreadLocal, "Number of Thread Local TOC Entries.");
95STATISTIC(NumTOCBlockAddress, "Number of Block Address TOC Entries.");
96STATISTIC(NumTOCEHBlock, "Number of EH Block TOC Entries.");
97
98static cl::opt<bool> EnableSSPCanaryBitInTB(
99 "aix-ssp-tb-bit", cl::init(Val: false),
100 cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden);
101
102// Specialize DenseMapInfo to allow
103// std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind> in DenseMap.
104// This specialization is needed here because that type is used as keys in the
105// map representing TOC entries.
106namespace llvm {
107template <>
108struct DenseMapInfo<std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>> {
109 using TOCKey = std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>;
110
111 static inline TOCKey getEmptyKey() {
112 return {nullptr, MCSymbolRefExpr::VariantKind::VK_None};
113 }
114 static inline TOCKey getTombstoneKey() {
115 return {nullptr, MCSymbolRefExpr::VariantKind::VK_Invalid};
116 }
117 static unsigned getHashValue(const TOCKey &PairVal) {
118 return detail::combineHashValue(
119 a: DenseMapInfo<const MCSymbol *>::getHashValue(PtrVal: PairVal.first),
120 b: DenseMapInfo<int>::getHashValue(Val: PairVal.second));
121 }
122 static bool isEqual(const TOCKey &A, const TOCKey &B) { return A == B; }
123};
124} // end namespace llvm
125
126namespace {
127
128enum {
129 // GNU attribute tags for PowerPC ABI
130 Tag_GNU_Power_ABI_FP = 4,
131 Tag_GNU_Power_ABI_Vector = 8,
132 Tag_GNU_Power_ABI_Struct_Return = 12,
133
134 // GNU attribute values for PowerPC float ABI, as combination of two parts
135 Val_GNU_Power_ABI_NoFloat = 0b00,
136 Val_GNU_Power_ABI_HardFloat_DP = 0b01,
137 Val_GNU_Power_ABI_SoftFloat_DP = 0b10,
138 Val_GNU_Power_ABI_HardFloat_SP = 0b11,
139
140 Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,
141 Val_GNU_Power_ABI_LDBL_64 = 0b1000,
142 Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,
143};
144
145class PPCAsmPrinter : public AsmPrinter {
146protected:
147 // For TLS on AIX, we need to be able to identify TOC entries of specific
148 // VariantKind so we can add the right relocations when we generate the
149 // entries. So each entry is represented by a pair of MCSymbol and
150 // VariantKind. For example, we need to be able to identify the following
151 // entry as a TLSGD entry so we can add the @m relocation:
152 // .tc .i[TC],i[TL]@m
153 // By default, VK_None is used for the VariantKind.
154 MapVector<std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>,
155 MCSymbol *>
156 TOC;
157 const PPCSubtarget *Subtarget = nullptr;
158
159 // Keep track of the number of TLS variables and their corresponding
160 // addresses, which is then used for the assembly printing of
161 // non-TOC-based local-exec variables.
162 MapVector<const GlobalValue *, uint64_t> TLSVarsToAddressMapping;
163
164public:
165 explicit PPCAsmPrinter(TargetMachine &TM,
166 std::unique_ptr<MCStreamer> Streamer)
167 : AsmPrinter(TM, std::move(Streamer)) {}
168
169 StringRef getPassName() const override { return "PowerPC Assembly Printer"; }
170
171 enum TOCEntryType {
172 TOCType_ConstantPool,
173 TOCType_GlobalExternal,
174 TOCType_GlobalInternal,
175 TOCType_JumpTable,
176 TOCType_ThreadLocal,
177 TOCType_BlockAddress,
178 TOCType_EHBlock
179 };
180
181 MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,
182 MCSymbolRefExpr::VariantKind Kind =
183 MCSymbolRefExpr::VariantKind::VK_None);
184
185 bool doInitialization(Module &M) override {
186 if (!TOC.empty())
187 TOC.clear();
188 return AsmPrinter::doInitialization(M);
189 }
190
191 void emitInstruction(const MachineInstr *MI) override;
192
193 /// This function is for PrintAsmOperand and PrintAsmMemoryOperand,
194 /// invoked by EmitMSInlineAsmStr and EmitGCCInlineAsmStr only.
195 /// The \p MI would be INLINEASM ONLY.
196 void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
197
198 void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
199 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
200 const char *ExtraCode, raw_ostream &O) override;
201 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
202 const char *ExtraCode, raw_ostream &O) override;
203
204 void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);
205 void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI);
206 void EmitTlsCall(const MachineInstr *MI, MCSymbolRefExpr::VariantKind VK);
207 void EmitAIXTlsCallHelper(const MachineInstr *MI);
208 const MCExpr *getAdjustedLocalExecExpr(const MachineOperand &MO,
209 int64_t Offset);
210 bool runOnMachineFunction(MachineFunction &MF) override {
211 Subtarget = &MF.getSubtarget<PPCSubtarget>();
212 bool Changed = AsmPrinter::runOnMachineFunction(MF);
213 emitXRayTable();
214 return Changed;
215 }
216};
217
218/// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
219class PPCLinuxAsmPrinter : public PPCAsmPrinter {
220public:
221 explicit PPCLinuxAsmPrinter(TargetMachine &TM,
222 std::unique_ptr<MCStreamer> Streamer)
223 : PPCAsmPrinter(TM, std::move(Streamer)) {}
224
225 StringRef getPassName() const override {
226 return "Linux PPC Assembly Printer";
227 }
228
229 void emitGNUAttributes(Module &M);
230
231 void emitStartOfAsmFile(Module &M) override;
232 void emitEndOfAsmFile(Module &) override;
233
234 void emitFunctionEntryLabel() override;
235
236 void emitFunctionBodyStart() override;
237 void emitFunctionBodyEnd() override;
238 void emitInstruction(const MachineInstr *MI) override;
239};
240
241class PPCAIXAsmPrinter : public PPCAsmPrinter {
242private:
243 /// Symbols lowered from ExternalSymbolSDNodes, we will need to emit extern
244 /// linkage for them in AIX.
245 SmallPtrSet<MCSymbol *, 8> ExtSymSDNodeSymbols;
246
247 /// A format indicator and unique trailing identifier to form part of the
248 /// sinit/sterm function names.
249 std::string FormatIndicatorAndUniqueModId;
250
251 // Record a list of GlobalAlias associated with a GlobalObject.
252 // This is used for AIX's extra-label-at-definition aliasing strategy.
253 DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
254 GOAliasMap;
255
256 uint16_t getNumberOfVRSaved();
257 void emitTracebackTable();
258
259 SmallVector<const GlobalVariable *, 8> TOCDataGlobalVars;
260
261 void emitGlobalVariableHelper(const GlobalVariable *);
262
263 // Get the offset of an alias based on its AliaseeObject.
264 uint64_t getAliasOffset(const Constant *C);
265
266public:
267 PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
268 : PPCAsmPrinter(TM, std::move(Streamer)) {
269 if (MAI->isLittleEndian())
270 report_fatal_error(
271 reason: "cannot create AIX PPC Assembly Printer for a little-endian target");
272 }
273
274 StringRef getPassName() const override { return "AIX PPC Assembly Printer"; }
275
276 bool doInitialization(Module &M) override;
277
278 void emitXXStructorList(const DataLayout &DL, const Constant *List,
279 bool IsCtor) override;
280
281 void SetupMachineFunction(MachineFunction &MF) override;
282
283 void emitGlobalVariable(const GlobalVariable *GV) override;
284
285 void emitFunctionDescriptor() override;
286
287 void emitFunctionEntryLabel() override;
288
289 void emitFunctionBodyEnd() override;
290
291 void emitPGORefs(Module &M);
292
293 void emitEndOfAsmFile(Module &) override;
294
295 void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
296
297 void emitInstruction(const MachineInstr *MI) override;
298
299 bool doFinalization(Module &M) override;
300
301 void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override;
302
303 void emitModuleCommandLines(Module &M) override;
304};
305
306} // end anonymous namespace
307
308void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
309 raw_ostream &O) {
310 // Computing the address of a global symbol, not calling it.
311 const GlobalValue *GV = MO.getGlobal();
312 getSymbol(GV)->print(OS&: O, MAI);
313 printOffset(Offset: MO.getOffset(), OS&: O);
314}
315
316void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
317 raw_ostream &O) {
318 const DataLayout &DL = getDataLayout();
319 const MachineOperand &MO = MI->getOperand(i: OpNo);
320
321 switch (MO.getType()) {
322 case MachineOperand::MO_Register: {
323 // The MI is INLINEASM ONLY and UseVSXReg is always false.
324 const char *RegName = PPCInstPrinter::getRegisterName(Reg: MO.getReg());
325
326 // Linux assembler (Others?) does not take register mnemonics.
327 // FIXME - What about special registers used in mfspr/mtspr?
328 O << PPC::stripRegisterPrefix(RegName);
329 return;
330 }
331 case MachineOperand::MO_Immediate:
332 O << MO.getImm();
333 return;
334
335 case MachineOperand::MO_MachineBasicBlock:
336 MO.getMBB()->getSymbol()->print(OS&: O, MAI);
337 return;
338 case MachineOperand::MO_ConstantPoolIndex:
339 O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
340 << MO.getIndex();
341 return;
342 case MachineOperand::MO_BlockAddress:
343 GetBlockAddressSymbol(BA: MO.getBlockAddress())->print(OS&: O, MAI);
344 return;
345 case MachineOperand::MO_GlobalAddress: {
346 PrintSymbolOperand(MO, O);
347 return;
348 }
349
350 default:
351 O << "<unknown operand type: " << (unsigned)MO.getType() << ">";
352 return;
353 }
354}
355
356/// PrintAsmOperand - Print out an operand for an inline asm expression.
357///
358bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
359 const char *ExtraCode, raw_ostream &O) {
360 // Does this asm operand have a single letter operand modifier?
361 if (ExtraCode && ExtraCode[0]) {
362 if (ExtraCode[1] != 0) return true; // Unknown modifier.
363
364 switch (ExtraCode[0]) {
365 default:
366 // See if this is a generic print operand
367 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS&: O);
368 case 'L': // Write second word of DImode reference.
369 // Verify that this operand has two consecutive registers.
370 if (!MI->getOperand(i: OpNo).isReg() ||
371 OpNo+1 == MI->getNumOperands() ||
372 !MI->getOperand(i: OpNo+1).isReg())
373 return true;
374 ++OpNo; // Return the high-part.
375 break;
376 case 'I':
377 // Write 'i' if an integer constant, otherwise nothing. Used to print
378 // addi vs add, etc.
379 if (MI->getOperand(i: OpNo).isImm())
380 O << "i";
381 return false;
382 case 'x':
383 if(!MI->getOperand(i: OpNo).isReg())
384 return true;
385 // This operand uses VSX numbering.
386 // If the operand is a VMX register, convert it to a VSX register.
387 Register Reg = MI->getOperand(i: OpNo).getReg();
388 if (PPC::isVRRegister(Reg))
389 Reg = PPC::VSX32 + (Reg - PPC::V0);
390 else if (PPC::isVFRegister(Reg))
391 Reg = PPC::VSX32 + (Reg - PPC::VF0);
392 const char *RegName;
393 RegName = PPCInstPrinter::getRegisterName(Reg);
394 RegName = PPC::stripRegisterPrefix(RegName);
395 O << RegName;
396 return false;
397 }
398 }
399
400 printOperand(MI, OpNo, O);
401 return false;
402}
403
404// At the moment, all inline asm memory operands are a single register.
405// In any case, the output of this routine should always be just one
406// assembler operand.
407bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
408 const char *ExtraCode,
409 raw_ostream &O) {
410 if (ExtraCode && ExtraCode[0]) {
411 if (ExtraCode[1] != 0) return true; // Unknown modifier.
412
413 switch (ExtraCode[0]) {
414 default: return true; // Unknown modifier.
415 case 'L': // A memory reference to the upper word of a double word op.
416 O << getDataLayout().getPointerSize() << "(";
417 printOperand(MI, OpNo, O);
418 O << ")";
419 return false;
420 case 'y': // A memory reference for an X-form instruction
421 O << "0, ";
422 printOperand(MI, OpNo, O);
423 return false;
424 case 'I':
425 // Write 'i' if an integer constant, otherwise nothing. Used to print
426 // addi vs add, etc.
427 if (MI->getOperand(i: OpNo).isImm())
428 O << "i";
429 return false;
430 case 'U': // Print 'u' for update form.
431 case 'X': // Print 'x' for indexed form.
432 // FIXME: Currently for PowerPC memory operands are always loaded
433 // into a register, so we never get an update or indexed form.
434 // This is bad even for offset forms, since even if we know we
435 // have a value in -16(r1), we will generate a load into r<n>
436 // and then load from 0(r<n>). Until that issue is fixed,
437 // tolerate 'U' and 'X' but don't output anything.
438 assert(MI->getOperand(OpNo).isReg());
439 return false;
440 }
441 }
442
443 assert(MI->getOperand(OpNo).isReg());
444 O << "0(";
445 printOperand(MI, OpNo, O);
446 O << ")";
447 return false;
448}
449
450static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type) {
451 ++NumTOCEntries;
452 switch (Type) {
453 case PPCAsmPrinter::TOCType_ConstantPool:
454 ++NumTOCConstPool;
455 break;
456 case PPCAsmPrinter::TOCType_GlobalInternal:
457 ++NumTOCGlobalInternal;
458 break;
459 case PPCAsmPrinter::TOCType_GlobalExternal:
460 ++NumTOCGlobalExternal;
461 break;
462 case PPCAsmPrinter::TOCType_JumpTable:
463 ++NumTOCJumpTable;
464 break;
465 case PPCAsmPrinter::TOCType_ThreadLocal:
466 ++NumTOCThreadLocal;
467 break;
468 case PPCAsmPrinter::TOCType_BlockAddress:
469 ++NumTOCBlockAddress;
470 break;
471 case PPCAsmPrinter::TOCType_EHBlock:
472 ++NumTOCEHBlock;
473 break;
474 }
475}
476
477/// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry
478/// exists for it. If not, create one. Then return a symbol that references
479/// the TOC entry.
480MCSymbol *
481PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,
482 MCSymbolRefExpr::VariantKind Kind) {
483 // If this is a new TOC entry add statistics about it.
484 if (!TOC.contains(Key: {Sym, Kind}))
485 collectTOCStats(Type);
486
487 MCSymbol *&TOCEntry = TOC[{Sym, Kind}];
488 if (!TOCEntry)
489 TOCEntry = createTempSymbol(Name: "C");
490 return TOCEntry;
491}
492
493void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {
494 unsigned NumNOPBytes = MI.getOperand(i: 1).getImm();
495
496 auto &Ctx = OutStreamer->getContext();
497 MCSymbol *MILabel = Ctx.createTempSymbol();
498 OutStreamer->emitLabel(Symbol: MILabel);
499
500 SM.recordStackMap(L: *MILabel, MI);
501 assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
502
503 // Scan ahead to trim the shadow.
504 const MachineBasicBlock &MBB = *MI.getParent();
505 MachineBasicBlock::const_iterator MII(MI);
506 ++MII;
507 while (NumNOPBytes > 0) {
508 if (MII == MBB.end() || MII->isCall() ||
509 MII->getOpcode() == PPC::DBG_VALUE ||
510 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
511 MII->getOpcode() == TargetOpcode::STACKMAP)
512 break;
513 ++MII;
514 NumNOPBytes -= 4;
515 }
516
517 // Emit nops.
518 for (unsigned i = 0; i < NumNOPBytes; i += 4)
519 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
520}
521
522// Lower a patchpoint of the form:
523// [<def>], <id>, <numBytes>, <target>, <numArgs>
524void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {
525 auto &Ctx = OutStreamer->getContext();
526 MCSymbol *MILabel = Ctx.createTempSymbol();
527 OutStreamer->emitLabel(Symbol: MILabel);
528
529 SM.recordPatchPoint(L: *MILabel, MI);
530 PatchPointOpers Opers(&MI);
531
532 unsigned EncodedBytes = 0;
533 const MachineOperand &CalleeMO = Opers.getCallTarget();
534
535 if (CalleeMO.isImm()) {
536 int64_t CallTarget = CalleeMO.getImm();
537 if (CallTarget) {
538 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
539 "High 16 bits of call target should be zero.");
540 Register ScratchReg = MI.getOperand(i: Opers.getNextScratchIdx()).getReg();
541 EncodedBytes = 0;
542 // Materialize the jump address:
543 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)
544 .addReg(ScratchReg)
545 .addImm((CallTarget >> 32) & 0xFFFF));
546 ++EncodedBytes;
547 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC)
548 .addReg(ScratchReg)
549 .addReg(ScratchReg)
550 .addImm(32).addImm(16));
551 ++EncodedBytes;
552 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8)
553 .addReg(ScratchReg)
554 .addReg(ScratchReg)
555 .addImm((CallTarget >> 16) & 0xFFFF));
556 ++EncodedBytes;
557 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8)
558 .addReg(ScratchReg)
559 .addReg(ScratchReg)
560 .addImm(CallTarget & 0xFFFF));
561
562 // Save the current TOC pointer before the remote call.
563 int TOCSaveOffset = Subtarget->getFrameLowering()->getTOCSaveOffset();
564 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD)
565 .addReg(PPC::X2)
566 .addImm(TOCSaveOffset)
567 .addReg(PPC::X1));
568 ++EncodedBytes;
569
570 // If we're on ELFv1, then we need to load the actual function pointer
571 // from the function descriptor.
572 if (!Subtarget->isELFv2ABI()) {
573 // Load the new TOC pointer and the function address, but not r11
574 // (needing this is rare, and loading it here would prevent passing it
575 // via a 'nest' parameter.
576 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
577 .addReg(PPC::X2)
578 .addImm(8)
579 .addReg(ScratchReg));
580 ++EncodedBytes;
581 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
582 .addReg(ScratchReg)
583 .addImm(0)
584 .addReg(ScratchReg));
585 ++EncodedBytes;
586 }
587
588 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8)
589 .addReg(ScratchReg));
590 ++EncodedBytes;
591 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8));
592 ++EncodedBytes;
593
594 // Restore the TOC pointer after the call.
595 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
596 .addReg(PPC::X2)
597 .addImm(TOCSaveOffset)
598 .addReg(PPC::X1));
599 ++EncodedBytes;
600 }
601 } else if (CalleeMO.isGlobal()) {
602 const GlobalValue *GValue = CalleeMO.getGlobal();
603 MCSymbol *MOSymbol = getSymbol(GV: GValue);
604 const MCExpr *SymVar = MCSymbolRefExpr::create(Symbol: MOSymbol, Ctx&: OutContext);
605
606 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP)
607 .addExpr(SymVar));
608 EncodedBytes += 2;
609 }
610
611 // Each instruction is 4 bytes.
612 EncodedBytes *= 4;
613
614 // Emit padding.
615 unsigned NumBytes = Opers.getNumPatchBytes();
616 assert(NumBytes >= EncodedBytes &&
617 "Patchpoint can't request size less than the length of a call.");
618 assert((NumBytes - EncodedBytes) % 4 == 0 &&
619 "Invalid number of NOP bytes requested!");
620 for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
621 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
622}
623
624/// This helper function creates the TlsGetAddr MCSymbol for AIX. We will
625/// create the csect and use the qual-name symbol instead of creating just the
626/// external symbol.
627static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc) {
628 StringRef SymName =
629 MIOpc == PPC::GETtlsTpointer32AIX ? ".__get_tpointer" : ".__tls_get_addr";
630 return Ctx
631 .getXCOFFSection(Section: SymName, K: SectionKind::getText(),
632 CsectProp: XCOFF::CsectProperties(XCOFF::XMC_PR, XCOFF::XTY_ER))
633 ->getQualNameSymbol();
634}
635
636void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) {
637 assert(Subtarget->isAIXABI() &&
638 "Only expecting to emit calls to get the thread pointer on AIX!");
639
640 MCSymbol *TlsCall = createMCSymbolForTlsGetAddr(Ctx&: OutContext, MIOpc: MI->getOpcode());
641 const MCExpr *TlsRef =
642 MCSymbolRefExpr::create(Symbol: TlsCall, Kind: MCSymbolRefExpr::VK_None, Ctx&: OutContext);
643 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));
644}
645
646/// EmitTlsCall -- Given a GETtls[ld]ADDR[32] instruction, print a
647/// call to __tls_get_addr to the current output stream.
648void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
649 MCSymbolRefExpr::VariantKind VK) {
650 MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
651 unsigned Opcode = PPC::BL8_NOP_TLS;
652
653 assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI");
654 if (MI->getOperand(i: 2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
655 MI->getOperand(i: 2).getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) {
656 Kind = MCSymbolRefExpr::VK_PPC_NOTOC;
657 Opcode = PPC::BL8_NOTOC_TLS;
658 }
659 const Module *M = MF->getFunction().getParent();
660
661 assert(MI->getOperand(0).isReg() &&
662 ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||
663 (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&
664 "GETtls[ld]ADDR[32] must define GPR3");
665 assert(MI->getOperand(1).isReg() &&
666 ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||
667 (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&
668 "GETtls[ld]ADDR[32] must read GPR3");
669
670 if (Subtarget->isAIXABI()) {
671 // On AIX, the variable offset should already be in R4 and the region handle
672 // should already be in R3.
673 // For TLSGD, which currently is the only supported access model, we only
674 // need to generate an absolute branch to .__tls_get_addr.
675 Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;
676 (void)VarOffsetReg;
677 assert(MI->getOperand(2).isReg() &&
678 MI->getOperand(2).getReg() == VarOffsetReg &&
679 "GETtls[ld]ADDR[32] must read GPR4");
680 EmitAIXTlsCallHelper(MI);
681 return;
682 }
683
684 MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol(Name: "__tls_get_addr");
685
686 if (Subtarget->is32BitELFABI() && isPositionIndependent())
687 Kind = MCSymbolRefExpr::VK_PLT;
688
689 const MCExpr *TlsRef =
690 MCSymbolRefExpr::create(Symbol: TlsGetAddr, Kind, Ctx&: OutContext);
691
692 // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI.
693 if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt() &&
694 M->getPICLevel() == PICLevel::BigPIC)
695 TlsRef = MCBinaryExpr::createAdd(
696 LHS: TlsRef, RHS: MCConstantExpr::create(Value: 32768, Ctx&: OutContext), Ctx&: OutContext);
697 const MachineOperand &MO = MI->getOperand(i: 2);
698 const GlobalValue *GValue = MO.getGlobal();
699 MCSymbol *MOSymbol = getSymbol(GV: GValue);
700 const MCExpr *SymVar = MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: VK, Ctx&: OutContext);
701 EmitToStreamer(S&: *OutStreamer,
702 Inst: MCInstBuilder(Subtarget->isPPC64() ? Opcode
703 : (unsigned)PPC::BL_TLS)
704 .addExpr(Val: TlsRef)
705 .addExpr(Val: SymVar));
706}
707
708/// Map a machine operand for a TOC pseudo-machine instruction to its
709/// corresponding MCSymbol.
710static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
711 AsmPrinter &AP) {
712 switch (MO.getType()) {
713 case MachineOperand::MO_GlobalAddress:
714 return AP.getSymbol(GV: MO.getGlobal());
715 case MachineOperand::MO_ConstantPoolIndex:
716 return AP.GetCPISymbol(CPID: MO.getIndex());
717 case MachineOperand::MO_JumpTableIndex:
718 return AP.GetJTISymbol(JTID: MO.getIndex());
719 case MachineOperand::MO_BlockAddress:
720 return AP.GetBlockAddressSymbol(BA: MO.getBlockAddress());
721 default:
722 llvm_unreachable("Unexpected operand type to get symbol.");
723 }
724}
725
726static PPCAsmPrinter::TOCEntryType
727getTOCEntryTypeForMO(const MachineOperand &MO) {
728 // Use the target flags to determine if this MO is Thread Local.
729 // If we don't do this it comes out as Global.
730 if (PPCInstrInfo::hasTLSFlag(TF: MO.getTargetFlags()))
731 return PPCAsmPrinter::TOCType_ThreadLocal;
732
733 switch (MO.getType()) {
734 case MachineOperand::MO_GlobalAddress: {
735 const GlobalValue *GlobalV = MO.getGlobal();
736 GlobalValue::LinkageTypes Linkage = GlobalV->getLinkage();
737 if (Linkage == GlobalValue::ExternalLinkage ||
738 Linkage == GlobalValue::AvailableExternallyLinkage ||
739 Linkage == GlobalValue::ExternalWeakLinkage)
740 return PPCAsmPrinter::TOCType_GlobalExternal;
741
742 return PPCAsmPrinter::TOCType_GlobalInternal;
743 }
744 case MachineOperand::MO_ConstantPoolIndex:
745 return PPCAsmPrinter::TOCType_ConstantPool;
746 case MachineOperand::MO_JumpTableIndex:
747 return PPCAsmPrinter::TOCType_JumpTable;
748 case MachineOperand::MO_BlockAddress:
749 return PPCAsmPrinter::TOCType_BlockAddress;
750 default:
751 llvm_unreachable("Unexpected operand type to get TOC type.");
752 }
753}
754/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
755/// the current output stream.
756///
757void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
758 PPC_MC::verifyInstructionPredicates(MI->getOpcode(),
759 getSubtargetInfo().getFeatureBits());
760
761 MCInst TmpInst;
762 const bool IsPPC64 = Subtarget->isPPC64();
763 const bool IsAIX = Subtarget->isAIXABI();
764 const bool HasAIXSmallLocalExecTLS = Subtarget->hasAIXSmallLocalExecTLS();
765 const Module *M = MF->getFunction().getParent();
766 PICLevel::Level PL = M->getPICLevel();
767
768#ifndef NDEBUG
769 // Validate that SPE and FPU are mutually exclusive in codegen
770 if (!MI->isInlineAsm()) {
771 for (const MachineOperand &MO: MI->operands()) {
772 if (MO.isReg()) {
773 Register Reg = MO.getReg();
774 if (Subtarget->hasSPE()) {
775 if (PPC::F4RCRegClass.contains(Reg) ||
776 PPC::F8RCRegClass.contains(Reg) ||
777 PPC::VFRCRegClass.contains(Reg) ||
778 PPC::VRRCRegClass.contains(Reg) ||
779 PPC::VSFRCRegClass.contains(Reg) ||
780 PPC::VSSRCRegClass.contains(Reg)
781 )
782 llvm_unreachable("SPE targets cannot have FPRegs!");
783 } else {
784 if (PPC::SPERCRegClass.contains(Reg))
785 llvm_unreachable("SPE register found in FPU-targeted code!");
786 }
787 }
788 }
789 }
790#endif
791
792 auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,
793 ptrdiff_t OriginalOffset) {
794 // Apply an offset to the TOC-based expression such that the adjusted
795 // notional offset from the TOC base (to be encoded into the instruction's D
796 // or DS field) is the signed 16-bit truncation of the original notional
797 // offset from the TOC base.
798 // This is consistent with the treatment used both by XL C/C++ and
799 // by AIX ld -r.
800 ptrdiff_t Adjustment =
801 OriginalOffset - llvm::SignExtend32<16>(X: OriginalOffset);
802 return MCBinaryExpr::createAdd(
803 LHS: Expr, RHS: MCConstantExpr::create(Value: -Adjustment, Ctx&: OutContext), Ctx&: OutContext);
804 };
805
806 auto getTOCEntryLoadingExprForXCOFF =
807 [IsPPC64, getTOCRelocAdjustedExprForXCOFF,
808 this](const MCSymbol *MOSymbol, const MCExpr *Expr,
809 MCSymbolRefExpr::VariantKind VK =
810 MCSymbolRefExpr::VariantKind::VK_None) -> const MCExpr * {
811 const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
812 const auto TOCEntryIter = TOC.find(Key: {MOSymbol, VK});
813 assert(TOCEntryIter != TOC.end() &&
814 "Could not find the TOC entry for this symbol.");
815 const ptrdiff_t EntryDistanceFromTOCBase =
816 (TOCEntryIter - TOC.begin()) * EntryByteSize;
817 constexpr int16_t PositiveTOCRange = INT16_MAX;
818
819 if (EntryDistanceFromTOCBase > PositiveTOCRange)
820 return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);
821
822 return Expr;
823 };
824 auto GetVKForMO = [&](const MachineOperand &MO) {
825 // For TLS initial-exec and local-exec accesses on AIX, we have one TOC
826 // entry for the symbol (with the variable offset), which is differentiated
827 // by MO_TPREL_FLAG.
828 unsigned Flag = MO.getTargetFlags();
829 if (Flag == PPCII::MO_TPREL_FLAG ||
830 Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG ||
831 Flag == PPCII::MO_TPREL_PCREL_FLAG) {
832 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");
833 TLSModel::Model Model = TM.getTLSModel(GV: MO.getGlobal());
834 if (Model == TLSModel::LocalExec)
835 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
836 if (Model == TLSModel::InitialExec)
837 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
838 llvm_unreachable("Only expecting local-exec or initial-exec accesses!");
839 }
840 // For GD TLS access on AIX, we have two TOC entries for the symbol (one for
841 // the variable offset and the other for the region handle). They are
842 // differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG.
843 if (Flag == PPCII::MO_TLSGDM_FLAG)
844 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM;
845 if (Flag == PPCII::MO_TLSGD_FLAG || Flag == PPCII::MO_GOT_TLSGD_PCREL_FLAG)
846 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD;
847 return MCSymbolRefExpr::VariantKind::VK_None;
848 };
849
850 // Lower multi-instruction pseudo operations.
851 switch (MI->getOpcode()) {
852 default: break;
853 case TargetOpcode::DBG_VALUE:
854 llvm_unreachable("Should be handled target independently");
855 case TargetOpcode::STACKMAP:
856 return LowerSTACKMAP(SM, MI: *MI);
857 case TargetOpcode::PATCHPOINT:
858 return LowerPATCHPOINT(SM, MI: *MI);
859
860 case PPC::MoveGOTtoLR: {
861 // Transform %lr = MoveGOTtoLR
862 // Into this: bl _GLOBAL_OFFSET_TABLE_@local-4
863 // _GLOBAL_OFFSET_TABLE_@local-4 (instruction preceding
864 // _GLOBAL_OFFSET_TABLE_) has exactly one instruction:
865 // blrl
866 // This will return the pointer to _GLOBAL_OFFSET_TABLE_@local
867 MCSymbol *GOTSymbol =
868 OutContext.getOrCreateSymbol(Name: StringRef("_GLOBAL_OFFSET_TABLE_"));
869 const MCExpr *OffsExpr =
870 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: GOTSymbol,
871 Kind: MCSymbolRefExpr::VK_PPC_LOCAL,
872 Ctx&: OutContext),
873 RHS: MCConstantExpr::create(Value: 4, Ctx&: OutContext),
874 Ctx&: OutContext);
875
876 // Emit the 'bl'.
877 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));
878 return;
879 }
880 case PPC::MovePCtoLR:
881 case PPC::MovePCtoLR8: {
882 // Transform %lr = MovePCtoLR
883 // Into this, where the label is the PIC base:
884 // bl L1$pb
885 // L1$pb:
886 MCSymbol *PICBase = MF->getPICBaseSymbol();
887
888 // Emit the 'bl'.
889 EmitToStreamer(*OutStreamer,
890 MCInstBuilder(PPC::BL)
891 // FIXME: We would like an efficient form for this, so we
892 // don't have to do a lot of extra uniquing.
893 .addExpr(MCSymbolRefExpr::create(PICBase, OutContext)));
894
895 // Emit the label.
896 OutStreamer->emitLabel(Symbol: PICBase);
897 return;
898 }
899 case PPC::UpdateGBR: {
900 // Transform %rd = UpdateGBR(%rt, %ri)
901 // Into: lwz %rt, .L0$poff - .L0$pb(%ri)
902 // add %rd, %rt, %ri
903 // or into (if secure plt mode is on):
904 // addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha
905 // addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l
906 // Get the offset from the GOT Base Register to the GOT
907 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
908 if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
909 unsigned PICR = TmpInst.getOperand(i: 0).getReg();
910 MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
911 Name: M->getPICLevel() == PICLevel::SmallPIC ? "_GLOBAL_OFFSET_TABLE_"
912 : ".LTOC");
913 const MCExpr *PB =
914 MCSymbolRefExpr::create(Symbol: MF->getPICBaseSymbol(), Ctx&: OutContext);
915
916 const MCExpr *DeltaExpr = MCBinaryExpr::createSub(
917 LHS: MCSymbolRefExpr::create(Symbol: BaseSymbol, Ctx&: OutContext), RHS: PB, Ctx&: OutContext);
918
919 const MCExpr *DeltaHi = PPCMCExpr::createHa(Expr: DeltaExpr, Ctx&: OutContext);
920 EmitToStreamer(
921 *OutStreamer,
922 MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));
923
924 const MCExpr *DeltaLo = PPCMCExpr::createLo(Expr: DeltaExpr, Ctx&: OutContext);
925 EmitToStreamer(
926 *OutStreamer,
927 MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));
928 return;
929 } else {
930 MCSymbol *PICOffset =
931 MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(MF&: *MF);
932 TmpInst.setOpcode(PPC::LWZ);
933 const MCExpr *Exp =
934 MCSymbolRefExpr::create(Symbol: PICOffset, Kind: MCSymbolRefExpr::VK_None, Ctx&: OutContext);
935 const MCExpr *PB =
936 MCSymbolRefExpr::create(Symbol: MF->getPICBaseSymbol(),
937 Kind: MCSymbolRefExpr::VK_None,
938 Ctx&: OutContext);
939 const MCOperand TR = TmpInst.getOperand(i: 1);
940 const MCOperand PICR = TmpInst.getOperand(i: 0);
941
942 // Step 1: lwz %rt, .L$poff - .L$pb(%ri)
943 TmpInst.getOperand(i: 1) =
944 MCOperand::createExpr(Val: MCBinaryExpr::createSub(LHS: Exp, RHS: PB, Ctx&: OutContext));
945 TmpInst.getOperand(i: 0) = TR;
946 TmpInst.getOperand(i: 2) = PICR;
947 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
948
949 TmpInst.setOpcode(PPC::ADD4);
950 TmpInst.getOperand(i: 0) = PICR;
951 TmpInst.getOperand(i: 1) = TR;
952 TmpInst.getOperand(i: 2) = PICR;
953 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
954 return;
955 }
956 }
957 case PPC::LWZtoc: {
958 // Transform %rN = LWZtoc @op1, %r2
959 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
960
961 // Change the opcode to LWZ.
962 TmpInst.setOpcode(PPC::LWZ);
963
964 const MachineOperand &MO = MI->getOperand(i: 1);
965 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
966 "Invalid operand for LWZtoc.");
967
968 // Map the operand to its corresponding MCSymbol.
969 const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, AP&: *this);
970
971 // Create a reference to the GOT entry for the symbol. The GOT entry will be
972 // synthesized later.
973 if (PL == PICLevel::SmallPIC && !IsAIX) {
974 const MCExpr *Exp =
975 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: MCSymbolRefExpr::VK_GOT,
976 Ctx&: OutContext);
977 TmpInst.getOperand(i: 1) = MCOperand::createExpr(Val: Exp);
978 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
979 return;
980 }
981
982 MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
983
984 // Otherwise, use the TOC. 'TOCEntry' is a label used to reference the
985 // storage allocated in the TOC which contains the address of
986 // 'MOSymbol'. Said TOC entry will be synthesized later.
987 MCSymbol *TOCEntry =
988 lookUpOrCreateTOCEntry(Sym: MOSymbol, Type: getTOCEntryTypeForMO(MO), Kind: VK);
989 const MCExpr *Exp =
990 MCSymbolRefExpr::create(Symbol: TOCEntry, Kind: MCSymbolRefExpr::VK_None, Ctx&: OutContext);
991
992 // AIX uses the label directly as the lwz displacement operand for
993 // references into the toc section. The displacement value will be generated
994 // relative to the toc-base.
995 if (IsAIX) {
996 assert(
997 TM.getCodeModel() == CodeModel::Small &&
998 "This pseudo should only be selected for 32-bit small code model.");
999 Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
1000 TmpInst.getOperand(i: 1) = MCOperand::createExpr(Val: Exp);
1001
1002 // Print MO for better readability
1003 if (isVerbose())
1004 OutStreamer->getCommentOS() << MO << '\n';
1005 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1006 return;
1007 }
1008
1009 // Create an explicit subtract expression between the local symbol and
1010 // '.LTOC' to manifest the toc-relative offset.
1011 const MCExpr *PB = MCSymbolRefExpr::create(
1012 Symbol: OutContext.getOrCreateSymbol(Name: Twine(".LTOC")), Ctx&: OutContext);
1013 Exp = MCBinaryExpr::createSub(LHS: Exp, RHS: PB, Ctx&: OutContext);
1014 TmpInst.getOperand(i: 1) = MCOperand::createExpr(Val: Exp);
1015 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1016 return;
1017 }
1018 case PPC::ADDItoc:
1019 case PPC::ADDItoc8: {
1020 assert(IsAIX && TM.getCodeModel() == CodeModel::Small &&
1021 "PseudoOp only valid for small code model AIX");
1022
1023 // Transform %rN = ADDItoc/8 @op1, %r2.
1024 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1025
1026 // Change the opcode to load address.
1027 TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
1028
1029 const MachineOperand &MO = MI->getOperand(i: 1);
1030 assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");
1031
1032 // Map the operand to its corresponding MCSymbol.
1033 const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, AP&: *this);
1034
1035 const MCExpr *Exp =
1036 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: MCSymbolRefExpr::VK_None, Ctx&: OutContext);
1037
1038 TmpInst.getOperand(i: 1) = TmpInst.getOperand(i: 2);
1039 TmpInst.getOperand(i: 2) = MCOperand::createExpr(Val: Exp);
1040 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1041 return;
1042 }
1043 case PPC::LDtocJTI:
1044 case PPC::LDtocCPT:
1045 case PPC::LDtocBA:
1046 case PPC::LDtoc: {
1047 // Transform %x3 = LDtoc @min1, %x2
1048 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1049
1050 // Change the opcode to LD.
1051 TmpInst.setOpcode(PPC::LD);
1052
1053 const MachineOperand &MO = MI->getOperand(i: 1);
1054 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1055 "Invalid operand!");
1056
1057 // Map the operand to its corresponding MCSymbol.
1058 const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, AP&: *this);
1059
1060 MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1061
1062 // Map the machine operand to its corresponding MCSymbol, then map the
1063 // global address operand to be a reference to the TOC entry we will
1064 // synthesize later.
1065 MCSymbol *TOCEntry =
1066 lookUpOrCreateTOCEntry(Sym: MOSymbol, Type: getTOCEntryTypeForMO(MO), Kind: VK);
1067
1068 MCSymbolRefExpr::VariantKind VKExpr =
1069 IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;
1070 const MCExpr *Exp = MCSymbolRefExpr::create(Symbol: TOCEntry, Kind: VKExpr, Ctx&: OutContext);
1071 TmpInst.getOperand(i: 1) = MCOperand::createExpr(
1072 Val: IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);
1073
1074 // Print MO for better readability
1075 if (isVerbose() && IsAIX)
1076 OutStreamer->getCommentOS() << MO << '\n';
1077 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1078 return;
1079 }
1080 case PPC::ADDIStocHA: {
1081 assert((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) &&
1082 "This pseudo should only be selected for 32-bit large code model on"
1083 " AIX.");
1084
1085 // Transform %rd = ADDIStocHA %rA, @sym(%r2)
1086 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1087
1088 // Change the opcode to ADDIS.
1089 TmpInst.setOpcode(PPC::ADDIS);
1090
1091 const MachineOperand &MO = MI->getOperand(i: 2);
1092 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1093 "Invalid operand for ADDIStocHA.");
1094
1095 // Map the machine operand to its corresponding MCSymbol.
1096 MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, AP&: *this);
1097
1098 MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1099
1100 // Always use TOC on AIX. Map the global address operand to be a reference
1101 // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
1102 // reference the storage allocated in the TOC which contains the address of
1103 // 'MOSymbol'.
1104 MCSymbol *TOCEntry =
1105 lookUpOrCreateTOCEntry(Sym: MOSymbol, Type: getTOCEntryTypeForMO(MO), Kind: VK);
1106 const MCExpr *Exp = MCSymbolRefExpr::create(Symbol: TOCEntry,
1107 Kind: MCSymbolRefExpr::VK_PPC_U,
1108 Ctx&: OutContext);
1109 TmpInst.getOperand(i: 2) = MCOperand::createExpr(Val: Exp);
1110 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1111 return;
1112 }
1113 case PPC::LWZtocL: {
1114 assert(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large &&
1115 "This pseudo should only be selected for 32-bit large code model on"
1116 " AIX.");
1117
1118 // Transform %rd = LWZtocL @sym, %rs.
1119 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1120
1121 // Change the opcode to lwz.
1122 TmpInst.setOpcode(PPC::LWZ);
1123
1124 const MachineOperand &MO = MI->getOperand(i: 1);
1125 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1126 "Invalid operand for LWZtocL.");
1127
1128 // Map the machine operand to its corresponding MCSymbol.
1129 MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, AP&: *this);
1130
1131 MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1132
1133 // Always use TOC on AIX. Map the global address operand to be a reference
1134 // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
1135 // reference the storage allocated in the TOC which contains the address of
1136 // 'MOSymbol'.
1137 MCSymbol *TOCEntry =
1138 lookUpOrCreateTOCEntry(Sym: MOSymbol, Type: getTOCEntryTypeForMO(MO), Kind: VK);
1139 const MCExpr *Exp = MCSymbolRefExpr::create(Symbol: TOCEntry,
1140 Kind: MCSymbolRefExpr::VK_PPC_L,
1141 Ctx&: OutContext);
1142 TmpInst.getOperand(i: 1) = MCOperand::createExpr(Val: Exp);
1143 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1144 return;
1145 }
1146 case PPC::ADDIStocHA8: {
1147 // Transform %xd = ADDIStocHA8 %x2, @sym
1148 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1149
1150 // Change the opcode to ADDIS8. If the global address is the address of
1151 // an external symbol, is a jump table address, is a block address, or is a
1152 // constant pool index with large code model enabled, then generate a TOC
1153 // entry and reference that. Otherwise, reference the symbol directly.
1154 TmpInst.setOpcode(PPC::ADDIS8);
1155
1156 const MachineOperand &MO = MI->getOperand(i: 2);
1157 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1158 "Invalid operand for ADDIStocHA8!");
1159
1160 const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, AP&: *this);
1161
1162 MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1163
1164 const bool GlobalToc =
1165 MO.isGlobal() && Subtarget->isGVIndirectSymbol(GV: MO.getGlobal());
1166 if (GlobalToc || MO.isJTI() || MO.isBlockAddress() ||
1167 (MO.isCPI() && TM.getCodeModel() == CodeModel::Large))
1168 MOSymbol = lookUpOrCreateTOCEntry(Sym: MOSymbol, Type: getTOCEntryTypeForMO(MO), Kind: VK);
1169
1170 VK = IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA;
1171
1172 const MCExpr *Exp =
1173 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: VK, Ctx&: OutContext);
1174
1175 if (!MO.isJTI() && MO.getOffset())
1176 Exp = MCBinaryExpr::createAdd(LHS: Exp,
1177 RHS: MCConstantExpr::create(Value: MO.getOffset(),
1178 Ctx&: OutContext),
1179 Ctx&: OutContext);
1180
1181 TmpInst.getOperand(i: 2) = MCOperand::createExpr(Val: Exp);
1182 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1183 return;
1184 }
1185 case PPC::LDtocL: {
1186 // Transform %xd = LDtocL @sym, %xs
1187 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1188
1189 // Change the opcode to LD. If the global address is the address of
1190 // an external symbol, is a jump table address, is a block address, or is
1191 // a constant pool index with large code model enabled, then generate a
1192 // TOC entry and reference that. Otherwise, reference the symbol directly.
1193 TmpInst.setOpcode(PPC::LD);
1194
1195 const MachineOperand &MO = MI->getOperand(i: 1);
1196 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||
1197 MO.isBlockAddress()) &&
1198 "Invalid operand for LDtocL!");
1199
1200 LLVM_DEBUG(assert(
1201 (!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&
1202 "LDtocL used on symbol that could be accessed directly is "
1203 "invalid. Must match ADDIStocHA8."));
1204
1205 const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, AP&: *this);
1206
1207 MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
1208
1209 if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)
1210 MOSymbol = lookUpOrCreateTOCEntry(Sym: MOSymbol, Type: getTOCEntryTypeForMO(MO), Kind: VK);
1211
1212 VK = IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO;
1213 const MCExpr *Exp =
1214 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: VK, Ctx&: OutContext);
1215 TmpInst.getOperand(i: 1) = MCOperand::createExpr(Val: Exp);
1216 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1217 return;
1218 }
1219 case PPC::ADDItocL: {
1220 // Transform %xd = ADDItocL %xs, @sym
1221 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1222
1223 // Change the opcode to ADDI8. If the global address is external, then
1224 // generate a TOC entry and reference that. Otherwise, reference the
1225 // symbol directly.
1226 TmpInst.setOpcode(PPC::ADDI8);
1227
1228 const MachineOperand &MO = MI->getOperand(i: 2);
1229 assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL.");
1230
1231 LLVM_DEBUG(assert(
1232 !(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&
1233 "Interposable definitions must use indirect access."));
1234
1235 const MCExpr *Exp =
1236 MCSymbolRefExpr::create(Symbol: getMCSymbolForTOCPseudoMO(MO, AP&: *this),
1237 Kind: MCSymbolRefExpr::VK_PPC_TOC_LO, Ctx&: OutContext);
1238 TmpInst.getOperand(i: 2) = MCOperand::createExpr(Val: Exp);
1239 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1240 return;
1241 }
1242 case PPC::ADDISgotTprelHA: {
1243 // Transform: %xd = ADDISgotTprelHA %x2, @sym
1244 // Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha
1245 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1246 const MachineOperand &MO = MI->getOperand(i: 2);
1247 const GlobalValue *GValue = MO.getGlobal();
1248 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1249 const MCExpr *SymGotTprel =
1250 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA,
1251 Ctx&: OutContext);
1252 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1253 .addReg(MI->getOperand(0).getReg())
1254 .addReg(MI->getOperand(1).getReg())
1255 .addExpr(SymGotTprel));
1256 return;
1257 }
1258 case PPC::LDgotTprelL:
1259 case PPC::LDgotTprelL32: {
1260 // Transform %xd = LDgotTprelL @sym, %xs
1261 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1262
1263 // Change the opcode to LD.
1264 TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);
1265 const MachineOperand &MO = MI->getOperand(i: 1);
1266 const GlobalValue *GValue = MO.getGlobal();
1267 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1268 const MCExpr *Exp = MCSymbolRefExpr::create(
1269 Symbol: MOSymbol, Kind: IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO
1270 : MCSymbolRefExpr::VK_PPC_GOT_TPREL,
1271 Ctx&: OutContext);
1272 TmpInst.getOperand(i: 1) = MCOperand::createExpr(Val: Exp);
1273 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1274 return;
1275 }
1276
1277 case PPC::PPC32PICGOT: {
1278 MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(Name: StringRef("_GLOBAL_OFFSET_TABLE_"));
1279 MCSymbol *GOTRef = OutContext.createTempSymbol();
1280 MCSymbol *NextInstr = OutContext.createTempSymbol();
1281
1282 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL)
1283 // FIXME: We would like an efficient form for this, so we don't have to do
1284 // a lot of extra uniquing.
1285 .addExpr(MCSymbolRefExpr::create(NextInstr, OutContext)));
1286 const MCExpr *OffsExpr =
1287 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: GOTSymbol, Ctx&: OutContext),
1288 RHS: MCSymbolRefExpr::create(Symbol: GOTRef, Ctx&: OutContext),
1289 Ctx&: OutContext);
1290 OutStreamer->emitLabel(Symbol: GOTRef);
1291 OutStreamer->emitValue(Value: OffsExpr, Size: 4);
1292 OutStreamer->emitLabel(Symbol: NextInstr);
1293 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)
1294 .addReg(MI->getOperand(0).getReg()));
1295 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)
1296 .addReg(MI->getOperand(1).getReg())
1297 .addImm(0)
1298 .addReg(MI->getOperand(0).getReg()));
1299 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4)
1300 .addReg(MI->getOperand(0).getReg())
1301 .addReg(MI->getOperand(1).getReg())
1302 .addReg(MI->getOperand(0).getReg()));
1303 return;
1304 }
1305 case PPC::PPC32GOT: {
1306 MCSymbol *GOTSymbol =
1307 OutContext.getOrCreateSymbol(Name: StringRef("_GLOBAL_OFFSET_TABLE_"));
1308 const MCExpr *SymGotTlsL = MCSymbolRefExpr::create(
1309 Symbol: GOTSymbol, Kind: MCSymbolRefExpr::VK_PPC_LO, Ctx&: OutContext);
1310 const MCExpr *SymGotTlsHA = MCSymbolRefExpr::create(
1311 Symbol: GOTSymbol, Kind: MCSymbolRefExpr::VK_PPC_HA, Ctx&: OutContext);
1312 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI)
1313 .addReg(MI->getOperand(0).getReg())
1314 .addExpr(SymGotTlsL));
1315 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
1316 .addReg(MI->getOperand(0).getReg())
1317 .addReg(MI->getOperand(0).getReg())
1318 .addExpr(SymGotTlsHA));
1319 return;
1320 }
1321 case PPC::ADDIStlsgdHA: {
1322 // Transform: %xd = ADDIStlsgdHA %x2, @sym
1323 // Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha
1324 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1325 const MachineOperand &MO = MI->getOperand(i: 2);
1326 const GlobalValue *GValue = MO.getGlobal();
1327 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1328 const MCExpr *SymGotTlsGD =
1329 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA,
1330 Ctx&: OutContext);
1331 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1332 .addReg(MI->getOperand(0).getReg())
1333 .addReg(MI->getOperand(1).getReg())
1334 .addExpr(SymGotTlsGD));
1335 return;
1336 }
1337 case PPC::ADDItlsgdL:
1338 // Transform: %xd = ADDItlsgdL %xs, @sym
1339 // Into: %xd = ADDI8 %xs, sym@got@tlsgd@l
1340 case PPC::ADDItlsgdL32: {
1341 // Transform: %rd = ADDItlsgdL32 %rs, @sym
1342 // Into: %rd = ADDI %rs, sym@got@tlsgd
1343 const MachineOperand &MO = MI->getOperand(i: 2);
1344 const GlobalValue *GValue = MO.getGlobal();
1345 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1346 const MCExpr *SymGotTlsGD = MCSymbolRefExpr::create(
1347 Symbol: MOSymbol, Kind: IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO
1348 : MCSymbolRefExpr::VK_PPC_GOT_TLSGD,
1349 Ctx&: OutContext);
1350 EmitToStreamer(*OutStreamer,
1351 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1352 .addReg(MI->getOperand(0).getReg())
1353 .addReg(MI->getOperand(1).getReg())
1354 .addExpr(SymGotTlsGD));
1355 return;
1356 }
1357 case PPC::GETtlsADDR:
1358 // Transform: %x3 = GETtlsADDR %x3, @sym
1359 // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsgd)
1360 case PPC::GETtlsADDRPCREL:
1361 case PPC::GETtlsADDR32AIX:
1362 case PPC::GETtlsADDR64AIX:
1363 // Transform: %r3 = GETtlsADDRNNAIX %r3, %r4 (for NN == 32/64).
1364 // Into: BLA .__tls_get_addr()
1365 // Unlike on Linux, there is no symbol or relocation needed for this call.
1366 case PPC::GETtlsADDR32: {
1367 // Transform: %r3 = GETtlsADDR32 %r3, @sym
1368 // Into: BL_TLS __tls_get_addr(sym at tlsgd)@PLT
1369 EmitTlsCall(MI, VK: MCSymbolRefExpr::VK_PPC_TLSGD);
1370 return;
1371 }
1372 case PPC::GETtlsTpointer32AIX: {
1373 // Transform: %r3 = GETtlsTpointer32AIX
1374 // Into: BLA .__get_tpointer()
1375 EmitAIXTlsCallHelper(MI);
1376 return;
1377 }
1378 case PPC::ADDIStlsldHA: {
1379 // Transform: %xd = ADDIStlsldHA %x2, @sym
1380 // Into: %xd = ADDIS8 %x2, sym@got@tlsld@ha
1381 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1382 const MachineOperand &MO = MI->getOperand(i: 2);
1383 const GlobalValue *GValue = MO.getGlobal();
1384 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1385 const MCExpr *SymGotTlsLD =
1386 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA,
1387 Ctx&: OutContext);
1388 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1389 .addReg(MI->getOperand(0).getReg())
1390 .addReg(MI->getOperand(1).getReg())
1391 .addExpr(SymGotTlsLD));
1392 return;
1393 }
1394 case PPC::ADDItlsldL:
1395 // Transform: %xd = ADDItlsldL %xs, @sym
1396 // Into: %xd = ADDI8 %xs, sym@got@tlsld@l
1397 case PPC::ADDItlsldL32: {
1398 // Transform: %rd = ADDItlsldL32 %rs, @sym
1399 // Into: %rd = ADDI %rs, sym@got@tlsld
1400 const MachineOperand &MO = MI->getOperand(i: 2);
1401 const GlobalValue *GValue = MO.getGlobal();
1402 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1403 const MCExpr *SymGotTlsLD = MCSymbolRefExpr::create(
1404 Symbol: MOSymbol, Kind: IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO
1405 : MCSymbolRefExpr::VK_PPC_GOT_TLSLD,
1406 Ctx&: OutContext);
1407 EmitToStreamer(*OutStreamer,
1408 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1409 .addReg(MI->getOperand(0).getReg())
1410 .addReg(MI->getOperand(1).getReg())
1411 .addExpr(SymGotTlsLD));
1412 return;
1413 }
1414 case PPC::GETtlsldADDR:
1415 // Transform: %x3 = GETtlsldADDR %x3, @sym
1416 // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsld)
1417 case PPC::GETtlsldADDRPCREL:
1418 case PPC::GETtlsldADDR32: {
1419 // Transform: %r3 = GETtlsldADDR32 %r3, @sym
1420 // Into: BL_TLS __tls_get_addr(sym at tlsld)@PLT
1421 EmitTlsCall(MI, VK: MCSymbolRefExpr::VK_PPC_TLSLD);
1422 return;
1423 }
1424 case PPC::ADDISdtprelHA:
1425 // Transform: %xd = ADDISdtprelHA %xs, @sym
1426 // Into: %xd = ADDIS8 %xs, sym@dtprel@ha
1427 case PPC::ADDISdtprelHA32: {
1428 // Transform: %rd = ADDISdtprelHA32 %rs, @sym
1429 // Into: %rd = ADDIS %rs, sym@dtprel@ha
1430 const MachineOperand &MO = MI->getOperand(i: 2);
1431 const GlobalValue *GValue = MO.getGlobal();
1432 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1433 const MCExpr *SymDtprel =
1434 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: MCSymbolRefExpr::VK_PPC_DTPREL_HA,
1435 Ctx&: OutContext);
1436 EmitToStreamer(
1437 *OutStreamer,
1438 MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)
1439 .addReg(MI->getOperand(0).getReg())
1440 .addReg(MI->getOperand(1).getReg())
1441 .addExpr(SymDtprel));
1442 return;
1443 }
1444 case PPC::PADDIdtprel: {
1445 // Transform: %rd = PADDIdtprel %rs, @sym
1446 // Into: %rd = PADDI8 %rs, sym@dtprel
1447 const MachineOperand &MO = MI->getOperand(i: 2);
1448 const GlobalValue *GValue = MO.getGlobal();
1449 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1450 const MCExpr *SymDtprel = MCSymbolRefExpr::create(
1451 Symbol: MOSymbol, Kind: MCSymbolRefExpr::VK_DTPREL, Ctx&: OutContext);
1452 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8)
1453 .addReg(MI->getOperand(0).getReg())
1454 .addReg(MI->getOperand(1).getReg())
1455 .addExpr(SymDtprel));
1456 return;
1457 }
1458
1459 case PPC::ADDIdtprelL:
1460 // Transform: %xd = ADDIdtprelL %xs, @sym
1461 // Into: %xd = ADDI8 %xs, sym@dtprel@l
1462 case PPC::ADDIdtprelL32: {
1463 // Transform: %rd = ADDIdtprelL32 %rs, @sym
1464 // Into: %rd = ADDI %rs, sym@dtprel@l
1465 const MachineOperand &MO = MI->getOperand(i: 2);
1466 const GlobalValue *GValue = MO.getGlobal();
1467 MCSymbol *MOSymbol = getSymbol(GV: GValue);
1468 const MCExpr *SymDtprel =
1469 MCSymbolRefExpr::create(Symbol: MOSymbol, Kind: MCSymbolRefExpr::VK_PPC_DTPREL_LO,
1470 Ctx&: OutContext);
1471 EmitToStreamer(*OutStreamer,
1472 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1473 .addReg(MI->getOperand(0).getReg())
1474 .addReg(MI->getOperand(1).getReg())
1475 .addExpr(SymDtprel));
1476 return;
1477 }
1478 case PPC::MFOCRF:
1479 case PPC::MFOCRF8:
1480 if (!Subtarget->hasMFOCRF()) {
1481 // Transform: %r3 = MFOCRF %cr7
1482 // Into: %r3 = MFCR ;; cr7
1483 unsigned NewOpcode =
1484 MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;
1485 OutStreamer->AddComment(T: PPCInstPrinter::
1486 getRegisterName(Reg: MI->getOperand(i: 1).getReg()));
1487 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(NewOpcode)
1488 .addReg(Reg: MI->getOperand(i: 0).getReg()));
1489 return;
1490 }
1491 break;
1492 case PPC::MTOCRF:
1493 case PPC::MTOCRF8:
1494 if (!Subtarget->hasMFOCRF()) {
1495 // Transform: %cr7 = MTOCRF %r3
1496 // Into: MTCRF mask, %r3 ;; cr7
1497 unsigned NewOpcode =
1498 MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
1499 unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
1500 ->getEncodingValue(RegNo: MI->getOperand(i: 0).getReg());
1501 OutStreamer->AddComment(T: PPCInstPrinter::
1502 getRegisterName(Reg: MI->getOperand(i: 0).getReg()));
1503 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(NewOpcode)
1504 .addImm(Val: Mask)
1505 .addReg(Reg: MI->getOperand(i: 1).getReg()));
1506 return;
1507 }
1508 break;
1509 case PPC::LD:
1510 case PPC::STD:
1511 case PPC::LWA_32:
1512 case PPC::LWA: {
1513 // Verify alignment is legal, so we don't create relocations
1514 // that can't be supported.
1515 unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;
1516 // For non-TOC-based local-exec TLS accesses with non-zero offsets, the
1517 // machine operand (which is a TargetGlobalTLSAddress) is expected to be
1518 // the same operand for both loads and stores.
1519 for (const MachineOperand &TempMO : MI->operands()) {
1520 if (((TempMO.getTargetFlags() == PPCII::MO_TPREL_FLAG)) &&
1521 TempMO.getOperandNo() == 1)
1522 OpNum = 1;
1523 }
1524 const MachineOperand &MO = MI->getOperand(i: OpNum);
1525 if (MO.isGlobal()) {
1526 const DataLayout &DL = MO.getGlobal()->getParent()->getDataLayout();
1527 if (MO.getGlobal()->getPointerAlignment(DL) < 4)
1528 llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");
1529 }
1530 // As these load/stores share common code with the following load/stores,
1531 // fall through to the subsequent cases in order to either process the
1532 // non-TOC-based local-exec sequence or to process the instruction normally.
1533 [[fallthrough]];
1534 }
1535 case PPC::LBZ:
1536 case PPC::LBZ8:
1537 case PPC::LHA:
1538 case PPC::LHA8:
1539 case PPC::LHZ:
1540 case PPC::LHZ8:
1541 case PPC::LWZ:
1542 case PPC::LWZ8:
1543 case PPC::STB:
1544 case PPC::STB8:
1545 case PPC::STH:
1546 case PPC::STH8:
1547 case PPC::STW:
1548 case PPC::STW8:
1549 case PPC::LFS:
1550 case PPC::STFS:
1551 case PPC::LFD:
1552 case PPC::STFD:
1553 case PPC::ADDI8: {
1554 // A faster non-TOC-based local-exec sequence is represented by `addi`
1555 // or a load/store instruction (that directly loads or stores off of the
1556 // thread pointer) with an immediate operand having the MO_TPREL_FLAG.
1557 // Such instructions do not otherwise arise.
1558 if (!HasAIXSmallLocalExecTLS)
1559 break;
1560 bool IsMIADDI8 = MI->getOpcode() == PPC::ADDI8;
1561 unsigned OpNum = IsMIADDI8 ? 2 : 1;
1562 const MachineOperand &MO = MI->getOperand(i: OpNum);
1563 unsigned Flag = MO.getTargetFlags();
1564 if (Flag == PPCII::MO_TPREL_FLAG ||
1565 Flag == PPCII::MO_GOT_TPREL_PCREL_FLAG ||
1566 Flag == PPCII::MO_TPREL_PCREL_FLAG) {
1567 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1568
1569 const MCExpr *Expr = getAdjustedLocalExecExpr(MO, Offset: MO.getOffset());
1570 if (Expr)
1571 TmpInst.getOperand(i: OpNum) = MCOperand::createExpr(Val: Expr);
1572
1573 // Change the opcode to load address if the original opcode is an `addi`.
1574 if (IsMIADDI8)
1575 TmpInst.setOpcode(PPC::LA8);
1576
1577 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1578 return;
1579 }
1580 // Now process the instruction normally.
1581 break;
1582 }
1583 case PPC::PseudoEIEIO: {
1584 EmitToStreamer(
1585 *OutStreamer,
1586 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1587 EmitToStreamer(
1588 *OutStreamer,
1589 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1590 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));
1591 return;
1592 }
1593 }
1594
1595 LowerPPCMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
1596 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
1597}
1598
1599// For non-TOC-based local-exec variables that have a non-zero offset,
1600// we need to create a new MCExpr that adds the non-zero offset to the address
1601// of the local-exec variable that will be used in either an addi, load or
1602// store. However, the final displacement for these instructions must be
1603// between [-32768, 32768), so if the TLS address + its non-zero offset is
1604// greater than 32KB, a new MCExpr is produced to accommodate this situation.
1605const MCExpr *PPCAsmPrinter::getAdjustedLocalExecExpr(const MachineOperand &MO,
1606 int64_t Offset) {
1607 // Non-zero offsets (for loads, stores or `addi`) require additional handling.
1608 // When the offset is zero, there is no need to create an adjusted MCExpr.
1609 if (!Offset)
1610 return nullptr;
1611
1612 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");
1613 const GlobalValue *GValue = MO.getGlobal();
1614 assert(TM.getTLSModel(GValue) == TLSModel::LocalExec &&
1615 "Only local-exec accesses are handled!");
1616
1617 bool IsGlobalADeclaration = GValue->isDeclarationForLinker();
1618 // Find the GlobalVariable that corresponds to the particular TLS variable
1619 // in the TLS variable-to-address mapping. All TLS variables should exist
1620 // within this map, with the exception of TLS variables marked as extern.
1621 const auto TLSVarsMapEntryIter = TLSVarsToAddressMapping.find(Key: GValue);
1622 if (TLSVarsMapEntryIter == TLSVarsToAddressMapping.end())
1623 assert(IsGlobalADeclaration &&
1624 "Only expecting to find extern TLS variables not present in the TLS "
1625 "variable-to-address map!");
1626
1627 unsigned TLSVarAddress =
1628 IsGlobalADeclaration ? 0 : TLSVarsMapEntryIter->second;
1629 ptrdiff_t FinalAddress = (TLSVarAddress + Offset);
1630 // If the address of the TLS variable + the offset is less than 32KB,
1631 // or if the TLS variable is extern, we simply produce an MCExpr to add the
1632 // non-zero offset to the TLS variable address.
1633 // For when TLS variables are extern, this is safe to do because we can
1634 // assume that the address of extern TLS variables are zero.
1635 const MCExpr *Expr = MCSymbolRefExpr::create(
1636 Symbol: getSymbol(GV: GValue), Kind: MCSymbolRefExpr::VK_PPC_AIX_TLSLE, Ctx&: OutContext);
1637 Expr = MCBinaryExpr::createAdd(
1638 LHS: Expr, RHS: MCConstantExpr::create(Value: Offset, Ctx&: OutContext), Ctx&: OutContext);
1639 if (FinalAddress >= 32768) {
1640 // Handle the written offset for cases where:
1641 // TLS variable address + Offset > 32KB.
1642
1643 // The assembly that is printed will look like:
1644 // TLSVar@le + Offset - Delta
1645 // where Delta is a multiple of 64KB: ((FinalAddress + 32768) & ~0xFFFF).
1646 ptrdiff_t Delta = ((FinalAddress + 32768) & ~0xFFFF);
1647 // Check that the total instruction displacement fits within [-32768,32768).
1648 [[maybe_unused]] ptrdiff_t InstDisp = TLSVarAddress + Offset - Delta;
1649 assert(((InstDisp < 32768) &&
1650 (InstDisp >= -32768)) &&
1651 "Expecting the instruction displacement for local-exec TLS "
1652 "variables to be between [-32768, 32768)!");
1653 Expr = MCBinaryExpr::createAdd(
1654 LHS: Expr, RHS: MCConstantExpr::create(Value: -Delta, Ctx&: OutContext), Ctx&: OutContext);
1655 }
1656
1657 return Expr;
1658}
1659
1660void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) {
1661 // Emit float ABI into GNU attribute
1662 Metadata *MD = M.getModuleFlag(Key: "float-abi");
1663 MDString *FloatABI = dyn_cast_or_null<MDString>(Val: MD);
1664 if (!FloatABI)
1665 return;
1666 StringRef flt = FloatABI->getString();
1667 // TODO: Support emitting soft-fp and hard double/single attributes.
1668 if (flt == "doubledouble")
1669 OutStreamer->emitGNUAttribute(Tag: Tag_GNU_Power_ABI_FP,
1670 Value: Val_GNU_Power_ABI_HardFloat_DP |
1671 Val_GNU_Power_ABI_LDBL_IBM128);
1672 else if (flt == "ieeequad")
1673 OutStreamer->emitGNUAttribute(Tag: Tag_GNU_Power_ABI_FP,
1674 Value: Val_GNU_Power_ABI_HardFloat_DP |
1675 Val_GNU_Power_ABI_LDBL_IEEE128);
1676 else if (flt == "ieeedouble")
1677 OutStreamer->emitGNUAttribute(Tag: Tag_GNU_Power_ABI_FP,
1678 Value: Val_GNU_Power_ABI_HardFloat_DP |
1679 Val_GNU_Power_ABI_LDBL_64);
1680}
1681
1682void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
1683 if (!Subtarget->isPPC64())
1684 return PPCAsmPrinter::emitInstruction(MI);
1685
1686 switch (MI->getOpcode()) {
1687 default:
1688 return PPCAsmPrinter::emitInstruction(MI);
1689 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1690 // .begin:
1691 // b .end # lis 0, FuncId[16..32]
1692 // nop # li 0, FuncId[0..15]
1693 // std 0, -8(1)
1694 // mflr 0
1695 // bl __xray_FunctionEntry
1696 // mtlr 0
1697 // .end:
1698 //
1699 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1700 // of instructions change.
1701 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1702 MCSymbol *EndOfSled = OutContext.createTempSymbol();
1703 OutStreamer->emitLabel(Symbol: BeginOfSled);
1704 EmitToStreamer(*OutStreamer,
1705 MCInstBuilder(PPC::B).addExpr(
1706 MCSymbolRefExpr::create(EndOfSled, OutContext)));
1707 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1708 EmitToStreamer(
1709 *OutStreamer,
1710 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1711 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1712 EmitToStreamer(*OutStreamer,
1713 MCInstBuilder(PPC::BL8_NOP)
1714 .addExpr(MCSymbolRefExpr::create(
1715 OutContext.getOrCreateSymbol("__xray_FunctionEntry"),
1716 OutContext)));
1717 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1718 OutStreamer->emitLabel(Symbol: EndOfSled);
1719 recordSled(Sled: BeginOfSled, MI: *MI, Kind: SledKind::FUNCTION_ENTER, Version: 2);
1720 break;
1721 }
1722 case TargetOpcode::PATCHABLE_RET: {
1723 unsigned RetOpcode = MI->getOperand(i: 0).getImm();
1724 MCInst RetInst;
1725 RetInst.setOpcode(RetOpcode);
1726 for (const auto &MO : llvm::drop_begin(RangeOrContainer: MI->operands())) {
1727 MCOperand MCOp;
1728 if (LowerPPCMachineOperandToMCOperand(MO, OutMO&: MCOp, AP&: *this))
1729 RetInst.addOperand(Op: MCOp);
1730 }
1731
1732 bool IsConditional;
1733 if (RetOpcode == PPC::BCCLR) {
1734 IsConditional = true;
1735 } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
1736 RetOpcode == PPC::TCRETURNai8) {
1737 break;
1738 } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
1739 IsConditional = false;
1740 } else {
1741 EmitToStreamer(S&: *OutStreamer, Inst: RetInst);
1742 break;
1743 }
1744
1745 MCSymbol *FallthroughLabel;
1746 if (IsConditional) {
1747 // Before:
1748 // bgtlr cr0
1749 //
1750 // After:
1751 // ble cr0, .end
1752 // .p2align 3
1753 // .begin:
1754 // blr # lis 0, FuncId[16..32]
1755 // nop # li 0, FuncId[0..15]
1756 // std 0, -8(1)
1757 // mflr 0
1758 // bl __xray_FunctionExit
1759 // mtlr 0
1760 // blr
1761 // .end:
1762 //
1763 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1764 // of instructions change.
1765 FallthroughLabel = OutContext.createTempSymbol();
1766 EmitToStreamer(
1767 *OutStreamer,
1768 MCInstBuilder(PPC::BCC)
1769 .addImm(PPC::InvertPredicate(
1770 static_cast<PPC::Predicate>(MI->getOperand(1).getImm())))
1771 .addReg(MI->getOperand(2).getReg())
1772 .addExpr(MCSymbolRefExpr::create(FallthroughLabel, OutContext)));
1773 RetInst = MCInst();
1774 RetInst.setOpcode(PPC::BLR8);
1775 }
1776 // .p2align 3
1777 // .begin:
1778 // b(lr)? # lis 0, FuncId[16..32]
1779 // nop # li 0, FuncId[0..15]
1780 // std 0, -8(1)
1781 // mflr 0
1782 // bl __xray_FunctionExit
1783 // mtlr 0
1784 // b(lr)?
1785 //
1786 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1787 // of instructions change.
1788 OutStreamer->emitCodeAlignment(Alignment: Align(8), STI: &getSubtargetInfo());
1789 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1790 OutStreamer->emitLabel(Symbol: BeginOfSled);
1791 EmitToStreamer(S&: *OutStreamer, Inst: RetInst);
1792 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1793 EmitToStreamer(
1794 *OutStreamer,
1795 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1796 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1797 EmitToStreamer(*OutStreamer,
1798 MCInstBuilder(PPC::BL8_NOP)
1799 .addExpr(MCSymbolRefExpr::create(
1800 OutContext.getOrCreateSymbol("__xray_FunctionExit"),
1801 OutContext)));
1802 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1803 EmitToStreamer(S&: *OutStreamer, Inst: RetInst);
1804 if (IsConditional)
1805 OutStreamer->emitLabel(Symbol: FallthroughLabel);
1806 recordSled(Sled: BeginOfSled, MI: *MI, Kind: SledKind::FUNCTION_EXIT, Version: 2);
1807 break;
1808 }
1809 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1810 llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
1811 case TargetOpcode::PATCHABLE_TAIL_CALL:
1812 // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a
1813 // normal function exit from a tail exit.
1814 llvm_unreachable("Tail call is handled in the normal case. See comments "
1815 "around this assert.");
1816 }
1817}
1818
1819void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {
1820 if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {
1821 PPCTargetStreamer *TS =
1822 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
1823 TS->emitAbiVersion(AbiVersion: 2);
1824 }
1825
1826 if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||
1827 !isPositionIndependent())
1828 return AsmPrinter::emitStartOfAsmFile(M);
1829
1830 if (M.getPICLevel() == PICLevel::SmallPIC)
1831 return AsmPrinter::emitStartOfAsmFile(M);
1832
1833 OutStreamer->switchSection(Section: OutContext.getELFSection(
1834 Section: ".got2", Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_WRITE | ELF::SHF_ALLOC));
1835
1836 MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Name: Twine(".LTOC"));
1837 MCSymbol *CurrentPos = OutContext.createTempSymbol();
1838
1839 OutStreamer->emitLabel(Symbol: CurrentPos);
1840
1841 // The GOT pointer points to the middle of the GOT, in order to reference the
1842 // entire 64kB range. 0x8000 is the midpoint.
1843 const MCExpr *tocExpr =
1844 MCBinaryExpr::createAdd(LHS: MCSymbolRefExpr::create(Symbol: CurrentPos, Ctx&: OutContext),
1845 RHS: MCConstantExpr::create(Value: 0x8000, Ctx&: OutContext),
1846 Ctx&: OutContext);
1847
1848 OutStreamer->emitAssignment(Symbol: TOCSym, Value: tocExpr);
1849
1850 OutStreamer->switchSection(Section: getObjFileLowering().getTextSection());
1851}
1852
1853void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {
1854 // linux/ppc32 - Normal entry label.
1855 if (!Subtarget->isPPC64() &&
1856 (!isPositionIndependent() ||
1857 MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC))
1858 return AsmPrinter::emitFunctionEntryLabel();
1859
1860 if (!Subtarget->isPPC64()) {
1861 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
1862 if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {
1863 MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(MF&: *MF);
1864 MCSymbol *PICBase = MF->getPICBaseSymbol();
1865 OutStreamer->emitLabel(Symbol: RelocSymbol);
1866
1867 const MCExpr *OffsExpr =
1868 MCBinaryExpr::createSub(
1869 LHS: MCSymbolRefExpr::create(Symbol: OutContext.getOrCreateSymbol(Name: Twine(".LTOC")),
1870 Ctx&: OutContext),
1871 RHS: MCSymbolRefExpr::create(Symbol: PICBase, Ctx&: OutContext),
1872 Ctx&: OutContext);
1873 OutStreamer->emitValue(Value: OffsExpr, Size: 4);
1874 OutStreamer->emitLabel(Symbol: CurrentFnSym);
1875 return;
1876 } else
1877 return AsmPrinter::emitFunctionEntryLabel();
1878 }
1879
1880 // ELFv2 ABI - Normal entry label.
1881 if (Subtarget->isELFv2ABI()) {
1882 // In the Large code model, we allow arbitrary displacements between
1883 // the text section and its associated TOC section. We place the
1884 // full 8-byte offset to the TOC in memory immediately preceding
1885 // the function global entry point.
1886 if (TM.getCodeModel() == CodeModel::Large
1887 && !MF->getRegInfo().use_empty(PPC::X2)) {
1888 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
1889
1890 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(Name: StringRef(".TOC."));
1891 MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(MF&: *MF);
1892 const MCExpr *TOCDeltaExpr =
1893 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: TOCSymbol, Ctx&: OutContext),
1894 RHS: MCSymbolRefExpr::create(Symbol: GlobalEPSymbol,
1895 Ctx&: OutContext),
1896 Ctx&: OutContext);
1897
1898 OutStreamer->emitLabel(Symbol: PPCFI->getTOCOffsetSymbol(MF&: *MF));
1899 OutStreamer->emitValue(Value: TOCDeltaExpr, Size: 8);
1900 }
1901 return AsmPrinter::emitFunctionEntryLabel();
1902 }
1903
1904 // Emit an official procedure descriptor.
1905 MCSectionSubPair Current = OutStreamer->getCurrentSection();
1906 MCSectionELF *Section = OutStreamer->getContext().getELFSection(
1907 Section: ".opd", Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_WRITE | ELF::SHF_ALLOC);
1908 OutStreamer->switchSection(Section);
1909 OutStreamer->emitLabel(Symbol: CurrentFnSym);
1910 OutStreamer->emitValueToAlignment(Alignment: Align(8));
1911 MCSymbol *Symbol1 = CurrentFnSymForSize;
1912 // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function
1913 // entry point.
1914 OutStreamer->emitValue(Value: MCSymbolRefExpr::create(Symbol: Symbol1, Ctx&: OutContext),
1915 Size: 8 /*size*/);
1916 MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(Name: StringRef(".TOC."));
1917 // Generates a R_PPC64_TOC relocation for TOC base insertion.
1918 OutStreamer->emitValue(
1919 Value: MCSymbolRefExpr::create(Symbol: Symbol2, Kind: MCSymbolRefExpr::VK_PPC_TOCBASE, Ctx&: OutContext),
1920 Size: 8/*size*/);
1921 // Emit a null environment pointer.
1922 OutStreamer->emitIntValue(Value: 0, Size: 8 /* size */);
1923 OutStreamer->switchSection(Section: Current.first, Subsection: Current.second);
1924}
1925
1926void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {
1927 const DataLayout &DL = getDataLayout();
1928
1929 bool isPPC64 = DL.getPointerSizeInBits() == 64;
1930
1931 PPCTargetStreamer *TS =
1932 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
1933
1934 // If we are using any values provided by Glibc at fixed addresses,
1935 // we need to ensure that the Glibc used at link time actually provides
1936 // those values. All versions of Glibc that do will define the symbol
1937 // named "__parse_hwcap_and_convert_at_platform".
1938 if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess())
1939 OutStreamer->emitSymbolValue(
1940 Sym: GetExternalSymbolSymbol(Sym: "__parse_hwcap_and_convert_at_platform"),
1941 Size: MAI->getCodePointerSize());
1942 emitGNUAttributes(M);
1943
1944 if (!TOC.empty()) {
1945 const char *Name = isPPC64 ? ".toc" : ".got2";
1946 MCSectionELF *Section = OutContext.getELFSection(
1947 Section: Name, Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_WRITE | ELF::SHF_ALLOC);
1948 OutStreamer->switchSection(Section);
1949 if (!isPPC64)
1950 OutStreamer->emitValueToAlignment(Alignment: Align(4));
1951
1952 for (const auto &TOCMapPair : TOC) {
1953 const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;
1954 MCSymbol *const TOCEntryLabel = TOCMapPair.second;
1955
1956 OutStreamer->emitLabel(Symbol: TOCEntryLabel);
1957 if (isPPC64)
1958 TS->emitTCEntry(S: *TOCEntryTarget, Kind: TOCMapPair.first.second);
1959 else
1960 OutStreamer->emitSymbolValue(Sym: TOCEntryTarget, Size: 4);
1961 }
1962 }
1963
1964 PPCAsmPrinter::emitEndOfAsmFile(M);
1965}
1966
1967/// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2.
1968void PPCLinuxAsmPrinter::emitFunctionBodyStart() {
1969 // In the ELFv2 ABI, in functions that use the TOC register, we need to
1970 // provide two entry points. The ABI guarantees that when calling the
1971 // local entry point, r2 is set up by the caller to contain the TOC base
1972 // for this function, and when calling the global entry point, r12 is set
1973 // up by the caller to hold the address of the global entry point. We
1974 // thus emit a prefix sequence along the following lines:
1975 //
1976 // func:
1977 // .Lfunc_gepNN:
1978 // # global entry point
1979 // addis r2,r12,(.TOC.-.Lfunc_gepNN)@ha
1980 // addi r2,r2,(.TOC.-.Lfunc_gepNN)@l
1981 // .Lfunc_lepNN:
1982 // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN
1983 // # local entry point, followed by function body
1984 //
1985 // For the Large code model, we create
1986 //
1987 // .Lfunc_tocNN:
1988 // .quad .TOC.-.Lfunc_gepNN # done by EmitFunctionEntryLabel
1989 // func:
1990 // .Lfunc_gepNN:
1991 // # global entry point
1992 // ld r2,.Lfunc_tocNN-.Lfunc_gepNN(r12)
1993 // add r2,r2,r12
1994 // .Lfunc_lepNN:
1995 // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN
1996 // # local entry point, followed by function body
1997 //
1998 // This ensures we have r2 set up correctly while executing the function
1999 // body, no matter which entry point is called.
2000 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
2001 const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||
2002 !MF->getRegInfo().use_empty(PPC::R2);
2003 const bool PCrelGEPRequired = Subtarget->isUsingPCRelativeCalls() &&
2004 UsesX2OrR2 && PPCFI->usesTOCBasePtr();
2005 const bool NonPCrelGEPRequired = !Subtarget->isUsingPCRelativeCalls() &&
2006 Subtarget->isELFv2ABI() && UsesX2OrR2;
2007
2008 // Only do all that if the function uses R2 as the TOC pointer
2009 // in the first place. We don't need the global entry point if the
2010 // function uses R2 as an allocatable register.
2011 if (NonPCrelGEPRequired || PCrelGEPRequired) {
2012 // Note: The logic here must be synchronized with the code in the
2013 // branch-selection pass which sets the offset of the first block in the
2014 // function. This matters because it affects the alignment.
2015 MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(MF&: *MF);
2016 OutStreamer->emitLabel(Symbol: GlobalEntryLabel);
2017 const MCSymbolRefExpr *GlobalEntryLabelExp =
2018 MCSymbolRefExpr::create(Symbol: GlobalEntryLabel, Ctx&: OutContext);
2019
2020 if (TM.getCodeModel() != CodeModel::Large) {
2021 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(Name: StringRef(".TOC."));
2022 const MCExpr *TOCDeltaExpr =
2023 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: TOCSymbol, Ctx&: OutContext),
2024 RHS: GlobalEntryLabelExp, Ctx&: OutContext);
2025
2026 const MCExpr *TOCDeltaHi = PPCMCExpr::createHa(Expr: TOCDeltaExpr, Ctx&: OutContext);
2027 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
2028 .addReg(PPC::X2)
2029 .addReg(PPC::X12)
2030 .addExpr(TOCDeltaHi));
2031
2032 const MCExpr *TOCDeltaLo = PPCMCExpr::createLo(Expr: TOCDeltaExpr, Ctx&: OutContext);
2033 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
2034 .addReg(PPC::X2)
2035 .addReg(PPC::X2)
2036 .addExpr(TOCDeltaLo));
2037 } else {
2038 MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(MF&: *MF);
2039 const MCExpr *TOCOffsetDeltaExpr =
2040 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: TOCOffset, Ctx&: OutContext),
2041 RHS: GlobalEntryLabelExp, Ctx&: OutContext);
2042
2043 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
2044 .addReg(PPC::X2)
2045 .addExpr(TOCOffsetDeltaExpr)
2046 .addReg(PPC::X12));
2047 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)
2048 .addReg(PPC::X2)
2049 .addReg(PPC::X2)
2050 .addReg(PPC::X12));
2051 }
2052
2053 MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(MF&: *MF);
2054 OutStreamer->emitLabel(Symbol: LocalEntryLabel);
2055 const MCSymbolRefExpr *LocalEntryLabelExp =
2056 MCSymbolRefExpr::create(Symbol: LocalEntryLabel, Ctx&: OutContext);
2057 const MCExpr *LocalOffsetExp =
2058 MCBinaryExpr::createSub(LHS: LocalEntryLabelExp,
2059 RHS: GlobalEntryLabelExp, Ctx&: OutContext);
2060
2061 PPCTargetStreamer *TS =
2062 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2063 TS->emitLocalEntry(S: cast<MCSymbolELF>(Val: CurrentFnSym), LocalOffset: LocalOffsetExp);
2064 } else if (Subtarget->isUsingPCRelativeCalls()) {
2065 // When generating the entry point for a function we have a few scenarios
2066 // based on whether or not that function uses R2 and whether or not that
2067 // function makes calls (or is a leaf function).
2068 // 1) A leaf function that does not use R2 (or treats it as callee-saved
2069 // and preserves it). In this case st_other=0 and both
2070 // the local and global entry points for the function are the same.
2071 // No special entry point code is required.
2072 // 2) A function uses the TOC pointer R2. This function may or may not have
2073 // calls. In this case st_other=[2,6] and the global and local entry
2074 // points are different. Code to correctly setup the TOC pointer in R2
2075 // is put between the global and local entry points. This case is
2076 // covered by the if statatement above.
2077 // 3) A function does not use the TOC pointer R2 but does have calls.
2078 // In this case st_other=1 since we do not know whether or not any
2079 // of the callees clobber R2. This case is dealt with in this else if
2080 // block. Tail calls are considered calls and the st_other should also
2081 // be set to 1 in that case as well.
2082 // 4) The function does not use the TOC pointer but R2 is used inside
2083 // the function. In this case st_other=1 once again.
2084 // 5) This function uses inline asm. We mark R2 as reserved if the function
2085 // has inline asm as we have to assume that it may be used.
2086 if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||
2087 MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) {
2088 PPCTargetStreamer *TS =
2089 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2090 TS->emitLocalEntry(S: cast<MCSymbolELF>(Val: CurrentFnSym),
2091 LocalOffset: MCConstantExpr::create(Value: 1, Ctx&: OutContext));
2092 }
2093 }
2094}
2095
2096/// EmitFunctionBodyEnd - Print the traceback table before the .size
2097/// directive.
2098///
2099void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
2100 // Only the 64-bit target requires a traceback table. For now,
2101 // we only emit the word of zeroes that GDB requires to find
2102 // the end of the function, and zeroes for the eight-byte
2103 // mandatory fields.
2104 // FIXME: We should fill in the eight-byte mandatory fields as described in
2105 // the PPC64 ELF ABI (this is a low-priority item because GDB does not
2106 // currently make use of these fields).
2107 if (Subtarget->isPPC64()) {
2108 OutStreamer->emitIntValue(Value: 0, Size: 4/*size*/);
2109 OutStreamer->emitIntValue(Value: 0, Size: 8/*size*/);
2110 }
2111}
2112
2113void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
2114 MCSymbol *GVSym) const {
2115
2116 assert(MAI->hasVisibilityOnlyWithLinkage() &&
2117 "AIX's linkage directives take a visibility setting.");
2118
2119 MCSymbolAttr LinkageAttr = MCSA_Invalid;
2120 switch (GV->getLinkage()) {
2121 case GlobalValue::ExternalLinkage:
2122 LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;
2123 break;
2124 case GlobalValue::LinkOnceAnyLinkage:
2125 case GlobalValue::LinkOnceODRLinkage:
2126 case GlobalValue::WeakAnyLinkage:
2127 case GlobalValue::WeakODRLinkage:
2128 case GlobalValue::ExternalWeakLinkage:
2129 LinkageAttr = MCSA_Weak;
2130 break;
2131 case GlobalValue::AvailableExternallyLinkage:
2132 LinkageAttr = MCSA_Extern;
2133 break;
2134 case GlobalValue::PrivateLinkage:
2135 return;
2136 case GlobalValue::InternalLinkage:
2137 assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&
2138 "InternalLinkage should not have other visibility setting.");
2139 LinkageAttr = MCSA_LGlobal;
2140 break;
2141 case GlobalValue::AppendingLinkage:
2142 llvm_unreachable("Should never emit this");
2143 case GlobalValue::CommonLinkage:
2144 llvm_unreachable("CommonLinkage of XCOFF should not come to this path");
2145 }
2146
2147 assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");
2148
2149 MCSymbolAttr VisibilityAttr = MCSA_Invalid;
2150 if (!TM.getIgnoreXCOFFVisibility()) {
2151 if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())
2152 report_fatal_error(
2153 reason: "Cannot not be both dllexport and non-default visibility");
2154 switch (GV->getVisibility()) {
2155
2156 // TODO: "internal" Visibility needs to go here.
2157 case GlobalValue::DefaultVisibility:
2158 if (GV->hasDLLExportStorageClass())
2159 VisibilityAttr = MAI->getExportedVisibilityAttr();
2160 break;
2161 case GlobalValue::HiddenVisibility:
2162 VisibilityAttr = MAI->getHiddenVisibilityAttr();
2163 break;
2164 case GlobalValue::ProtectedVisibility:
2165 VisibilityAttr = MAI->getProtectedVisibilityAttr();
2166 break;
2167 }
2168 }
2169
2170 OutStreamer->emitXCOFFSymbolLinkageWithVisibility(Symbol: GVSym, Linkage: LinkageAttr,
2171 Visibility: VisibilityAttr);
2172}
2173
2174void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
2175 // Setup CurrentFnDescSym and its containing csect.
2176 MCSectionXCOFF *FnDescSec =
2177 cast<MCSectionXCOFF>(Val: getObjFileLowering().getSectionForFunctionDescriptor(
2178 F: &MF.getFunction(), TM));
2179 FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4));
2180
2181 CurrentFnDescSym = FnDescSec->getQualNameSymbol();
2182
2183 return AsmPrinter::SetupMachineFunction(MF);
2184}
2185
2186uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {
2187 // Calculate the number of VRs be saved.
2188 // Vector registers 20 through 31 are marked as reserved and cannot be used
2189 // in the default ABI.
2190 const PPCSubtarget &Subtarget = MF->getSubtarget<PPCSubtarget>();
2191 if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&
2192 TM.getAIXExtendedAltivecABI()) {
2193 const MachineRegisterInfo &MRI = MF->getRegInfo();
2194 for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg)
2195 if (MRI.isPhysRegModified(Reg))
2196 // Number of VRs saved.
2197 return PPC::V31 - Reg + 1;
2198 }
2199 return 0;
2200}
2201
2202void PPCAIXAsmPrinter::emitFunctionBodyEnd() {
2203
2204 if (!TM.getXCOFFTracebackTable())
2205 return;
2206
2207 emitTracebackTable();
2208
2209 // If ShouldEmitEHBlock returns true, then the eh info table
2210 // will be emitted via `AIXException::endFunction`. Otherwise, we
2211 // need to emit a dumy eh info table when VRs are saved. We could not
2212 // consolidate these two places into one because there is no easy way
2213 // to access register information in `AIXException` class.
2214 if (!TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) &&
2215 (getNumberOfVRSaved() > 0)) {
2216 // Emit dummy EH Info Table.
2217 OutStreamer->switchSection(Section: getObjFileLowering().getCompactUnwindSection());
2218 MCSymbol *EHInfoLabel =
2219 TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF);
2220 OutStreamer->emitLabel(Symbol: EHInfoLabel);
2221
2222 // Version number.
2223 OutStreamer->emitInt32(Value: 0);
2224
2225 const DataLayout &DL = MMI->getModule()->getDataLayout();
2226 const unsigned PointerSize = DL.getPointerSize();
2227 // Add necessary paddings in 64 bit mode.
2228 OutStreamer->emitValueToAlignment(Alignment: Align(PointerSize));
2229
2230 OutStreamer->emitIntValue(Value: 0, Size: PointerSize);
2231 OutStreamer->emitIntValue(Value: 0, Size: PointerSize);
2232 OutStreamer->switchSection(Section: MF->getSection());
2233 }
2234}
2235
2236void PPCAIXAsmPrinter::emitTracebackTable() {
2237
2238 // Create a symbol for the end of function.
2239 MCSymbol *FuncEnd = createTempSymbol(Name: MF->getName());
2240 OutStreamer->emitLabel(Symbol: FuncEnd);
2241
2242 OutStreamer->AddComment(T: "Traceback table begin");
2243 // Begin with a fullword of zero.
2244 OutStreamer->emitIntValueInHexWithPadding(Value: 0, Size: 4 /*size*/);
2245
2246 SmallString<128> CommentString;
2247 raw_svector_ostream CommentOS(CommentString);
2248
2249 auto EmitComment = [&]() {
2250 OutStreamer->AddComment(T: CommentOS.str());
2251 CommentString.clear();
2252 };
2253
2254 auto EmitCommentAndValue = [&](uint64_t Value, int Size) {
2255 EmitComment();
2256 OutStreamer->emitIntValueInHexWithPadding(Value, Size);
2257 };
2258
2259 unsigned int Version = 0;
2260 CommentOS << "Version = " << Version;
2261 EmitCommentAndValue(Version, 1);
2262
2263 // There is a lack of information in the IR to assist with determining the
2264 // source language. AIX exception handling mechanism would only search for
2265 // personality routine and LSDA area when such language supports exception
2266 // handling. So to be conservatively correct and allow runtime to do its job,
2267 // we need to set it to C++ for now.
2268 TracebackTable::LanguageID LanguageIdentifier =
2269 TracebackTable::CPlusPlus; // C++
2270
2271 CommentOS << "Language = "
2272 << getNameForTracebackTableLanguageId(LangId: LanguageIdentifier);
2273 EmitCommentAndValue(LanguageIdentifier, 1);
2274
2275 // This is only populated for the third and fourth bytes.
2276 uint32_t FirstHalfOfMandatoryField = 0;
2277
2278 // Emit the 3rd byte of the mandatory field.
2279
2280 // We always set traceback offset bit to true.
2281 FirstHalfOfMandatoryField |= TracebackTable::HasTraceBackTableOffsetMask;
2282
2283 const PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
2284 const MachineRegisterInfo &MRI = MF->getRegInfo();
2285
2286 // Check the function uses floating-point processor instructions or not
2287 for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {
2288 if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
2289 FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask;
2290 break;
2291 }
2292 }
2293
2294#define GENBOOLCOMMENT(Prefix, V, Field) \
2295 CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \
2296 << #Field
2297
2298#define GENVALUECOMMENT(PrefixAndName, V, Field) \
2299 CommentOS << (PrefixAndName) << " = " \
2300 << static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >> \
2301 (TracebackTable::Field##Shift))
2302
2303 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsGlobaLinkage);
2304 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);
2305 EmitComment();
2306
2307 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasTraceBackTableOffset);
2308 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsInternalProcedure);
2309 EmitComment();
2310
2311 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasControlledStorage);
2312 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsTOCless);
2313 EmitComment();
2314
2315 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsFloatingPointPresent);
2316 EmitComment();
2317 GENBOOLCOMMENT("", FirstHalfOfMandatoryField,
2318 IsFloatingPointOperationLogOrAbortEnabled);
2319 EmitComment();
2320
2321 OutStreamer->emitIntValueInHexWithPadding(
2322 Value: (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, Size: 1);
2323
2324 // Set the 4th byte of the mandatory field.
2325 FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask;
2326
2327 const PPCRegisterInfo *RegInfo =
2328 static_cast<const PPCRegisterInfo *>(Subtarget->getRegisterInfo());
2329 Register FrameReg = RegInfo->getFrameRegister(*MF);
2330 if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))
2331 FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask;
2332
2333 const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();
2334 if (!MustSaveCRs.empty())
2335 FirstHalfOfMandatoryField |= TracebackTable::IsCRSavedMask;
2336
2337 if (FI->mustSaveLR())
2338 FirstHalfOfMandatoryField |= TracebackTable::IsLRSavedMask;
2339
2340 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsInterruptHandler);
2341 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);
2342 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsAllocaUsed);
2343 EmitComment();
2344 GENVALUECOMMENT("OnConditionDirective", FirstHalfOfMandatoryField,
2345 OnConditionDirective);
2346 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsCRSaved);
2347 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsLRSaved);
2348 EmitComment();
2349 OutStreamer->emitIntValueInHexWithPadding(Value: (FirstHalfOfMandatoryField & 0xff),
2350 Size: 1);
2351
2352 // Set the 5th byte of mandatory field.
2353 uint32_t SecondHalfOfMandatoryField = 0;
2354
2355 SecondHalfOfMandatoryField |= MF->getFrameInfo().getStackSize()
2356 ? TracebackTable::IsBackChainStoredMask
2357 : 0;
2358
2359 uint32_t FPRSaved = 0;
2360 for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) {
2361 if (MRI.isPhysRegModified(Reg)) {
2362 FPRSaved = PPC::F31 - Reg + 1;
2363 break;
2364 }
2365 }
2366 SecondHalfOfMandatoryField |= (FPRSaved << TracebackTable::FPRSavedShift) &
2367 TracebackTable::FPRSavedMask;
2368 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, IsBackChainStored);
2369 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, IsFixup);
2370 GENVALUECOMMENT(", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);
2371 EmitComment();
2372 OutStreamer->emitIntValueInHexWithPadding(
2373 Value: (SecondHalfOfMandatoryField & 0xff000000) >> 24, Size: 1);
2374
2375 // Set the 6th byte of mandatory field.
2376
2377 // Check whether has Vector Instruction,We only treat instructions uses vector
2378 // register as vector instructions.
2379 bool HasVectorInst = false;
2380 for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)
2381 if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
2382 // Has VMX instruction.
2383 HasVectorInst = true;
2384 break;
2385 }
2386
2387 if (FI->hasVectorParms() || HasVectorInst)
2388 SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask;
2389
2390 uint16_t NumOfVRSaved = getNumberOfVRSaved();
2391 bool ShouldEmitEHBlock =
2392 TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(MF) || NumOfVRSaved > 0;
2393
2394 if (ShouldEmitEHBlock)
2395 SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask;
2396
2397 uint32_t GPRSaved = 0;
2398
2399 // X13 is reserved under 64-bit environment.
2400 unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;
2401 unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;
2402
2403 for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) {
2404 if (MRI.isPhysRegModified(PhysReg: Reg)) {
2405 GPRSaved = GPREnd - Reg + 1;
2406 break;
2407 }
2408 }
2409
2410 SecondHalfOfMandatoryField |= (GPRSaved << TracebackTable::GPRSavedShift) &
2411 TracebackTable::GPRSavedMask;
2412
2413 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, HasExtensionTable);
2414 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasVectorInfo);
2415 GENVALUECOMMENT(", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);
2416 EmitComment();
2417 OutStreamer->emitIntValueInHexWithPadding(
2418 Value: (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, Size: 1);
2419
2420 // Set the 7th byte of mandatory field.
2421 uint32_t NumberOfFixedParms = FI->getFixedParmsNum();
2422 SecondHalfOfMandatoryField |=
2423 (NumberOfFixedParms << TracebackTable::NumberOfFixedParmsShift) &
2424 TracebackTable::NumberOfFixedParmsMask;
2425 GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,
2426 NumberOfFixedParms);
2427 EmitComment();
2428 OutStreamer->emitIntValueInHexWithPadding(
2429 Value: (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, Size: 1);
2430
2431 // Set the 8th byte of mandatory field.
2432
2433 // Always set parameter on stack.
2434 SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask;
2435
2436 uint32_t NumberOfFPParms = FI->getFloatingPointParmsNum();
2437 SecondHalfOfMandatoryField |=
2438 (NumberOfFPParms << TracebackTable::NumberOfFloatingPointParmsShift) &
2439 TracebackTable::NumberOfFloatingPointParmsMask;
2440
2441 GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,
2442 NumberOfFloatingPointParms);
2443 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasParmsOnStack);
2444 EmitComment();
2445 OutStreamer->emitIntValueInHexWithPadding(Value: SecondHalfOfMandatoryField & 0xff,
2446 Size: 1);
2447
2448 // Generate the optional fields of traceback table.
2449
2450 // Parameter type.
2451 if (NumberOfFixedParms || NumberOfFPParms) {
2452 uint32_t ParmsTypeValue = FI->getParmsType();
2453
2454 Expected<SmallString<32>> ParmsType =
2455 FI->hasVectorParms()
2456 ? XCOFF::parseParmsTypeWithVecInfo(
2457 Value: ParmsTypeValue, FixedParmsNum: NumberOfFixedParms, FloatingParmsNum: NumberOfFPParms,
2458 VectorParmsNum: FI->getVectorParmsNum())
2459 : XCOFF::parseParmsType(Value: ParmsTypeValue, FixedParmsNum: NumberOfFixedParms,
2460 FloatingParmsNum: NumberOfFPParms);
2461
2462 assert(ParmsType && toString(ParmsType.takeError()).c_str());
2463 if (ParmsType) {
2464 CommentOS << "Parameter type = " << ParmsType.get();
2465 EmitComment();
2466 }
2467 OutStreamer->emitIntValueInHexWithPadding(Value: ParmsTypeValue,
2468 Size: sizeof(ParmsTypeValue));
2469 }
2470 // Traceback table offset.
2471 OutStreamer->AddComment(T: "Function size");
2472 if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) {
2473 MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(
2474 Func: &(MF->getFunction()), TM);
2475 OutStreamer->emitAbsoluteSymbolDiff(Hi: FuncEnd, Lo: FuncSectSym, Size: 4);
2476 }
2477
2478 // Since we unset the Int_Handler.
2479 if (FirstHalfOfMandatoryField & TracebackTable::IsInterruptHandlerMask)
2480 report_fatal_error(reason: "Hand_Mask not implement yet");
2481
2482 if (FirstHalfOfMandatoryField & TracebackTable::HasControlledStorageMask)
2483 report_fatal_error(reason: "Ctl_Info not implement yet");
2484
2485 if (FirstHalfOfMandatoryField & TracebackTable::IsFunctionNamePresentMask) {
2486 StringRef Name = MF->getName().substr(Start: 0, INT16_MAX);
2487 int16_t NameLength = Name.size();
2488 CommentOS << "Function name len = "
2489 << static_cast<unsigned int>(NameLength);
2490 EmitCommentAndValue(NameLength, 2);
2491 OutStreamer->AddComment(T: "Function Name");
2492 OutStreamer->emitBytes(Data: Name);
2493 }
2494
2495 if (FirstHalfOfMandatoryField & TracebackTable::IsAllocaUsedMask) {
2496 uint8_t AllocReg = XCOFF::AllocRegNo;
2497 OutStreamer->AddComment(T: "AllocaUsed");
2498 OutStreamer->emitIntValueInHex(Value: AllocReg, Size: sizeof(AllocReg));
2499 }
2500
2501 if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) {
2502 uint16_t VRData = 0;
2503 if (NumOfVRSaved) {
2504 // Number of VRs saved.
2505 VRData |= (NumOfVRSaved << TracebackTable::NumberOfVRSavedShift) &
2506 TracebackTable::NumberOfVRSavedMask;
2507 // This bit is supposed to set only when the special register
2508 // VRSAVE is saved on stack.
2509 // However, IBM XL compiler sets the bit when any vector registers
2510 // are saved on the stack. We will follow XL's behavior on AIX
2511 // so that we don't get surprise behavior change for C code.
2512 VRData |= TracebackTable::IsVRSavedOnStackMask;
2513 }
2514
2515 // Set has_varargs.
2516 if (FI->getVarArgsFrameIndex())
2517 VRData |= TracebackTable::HasVarArgsMask;
2518
2519 // Vector parameters number.
2520 unsigned VectorParmsNum = FI->getVectorParmsNum();
2521 VRData |= (VectorParmsNum << TracebackTable::NumberOfVectorParmsShift) &
2522 TracebackTable::NumberOfVectorParmsMask;
2523
2524 if (HasVectorInst)
2525 VRData |= TracebackTable::HasVMXInstructionMask;
2526
2527 GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved);
2528 GENBOOLCOMMENT(", ", VRData, IsVRSavedOnStack);
2529 GENBOOLCOMMENT(", ", VRData, HasVarArgs);
2530 EmitComment();
2531 OutStreamer->emitIntValueInHexWithPadding(Value: (VRData & 0xff00) >> 8, Size: 1);
2532
2533 GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms);
2534 GENBOOLCOMMENT(", ", VRData, HasVMXInstruction);
2535 EmitComment();
2536 OutStreamer->emitIntValueInHexWithPadding(Value: VRData & 0x00ff, Size: 1);
2537
2538 uint32_t VecParmTypeValue = FI->getVecExtParmsType();
2539
2540 Expected<SmallString<32>> VecParmsType =
2541 XCOFF::parseVectorParmsType(Value: VecParmTypeValue, ParmsNum: VectorParmsNum);
2542 assert(VecParmsType && toString(VecParmsType.takeError()).c_str());
2543 if (VecParmsType) {
2544 CommentOS << "Vector Parameter type = " << VecParmsType.get();
2545 EmitComment();
2546 }
2547 OutStreamer->emitIntValueInHexWithPadding(Value: VecParmTypeValue,
2548 Size: sizeof(VecParmTypeValue));
2549 // Padding 2 bytes.
2550 CommentOS << "Padding";
2551 EmitCommentAndValue(0, 2);
2552 }
2553
2554 uint8_t ExtensionTableFlag = 0;
2555 if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) {
2556 if (ShouldEmitEHBlock)
2557 ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;
2558 if (EnableSSPCanaryBitInTB &&
2559 TargetLoweringObjectFileXCOFF::ShouldSetSSPCanaryBitInTB(MF))
2560 ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;
2561
2562 CommentOS << "ExtensionTableFlag = "
2563 << getExtendedTBTableFlagString(Flag: ExtensionTableFlag);
2564 EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag));
2565 }
2566
2567 if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {
2568 auto &Ctx = OutStreamer->getContext();
2569 MCSymbol *EHInfoSym =
2570 TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF);
2571 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(Sym: EHInfoSym, Type: TOCType_EHBlock);
2572 const MCSymbol *TOCBaseSym =
2573 cast<MCSectionXCOFF>(Val: getObjFileLowering().getTOCBaseSection())
2574 ->getQualNameSymbol();
2575 const MCExpr *Exp =
2576 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: TOCEntry, Ctx),
2577 RHS: MCSymbolRefExpr::create(Symbol: TOCBaseSym, Ctx), Ctx);
2578
2579 const DataLayout &DL = getDataLayout();
2580 OutStreamer->emitValueToAlignment(Alignment: Align(4));
2581 OutStreamer->AddComment(T: "EHInfo Table");
2582 OutStreamer->emitValue(Value: Exp, Size: DL.getPointerSize());
2583 }
2584#undef GENBOOLCOMMENT
2585#undef GENVALUECOMMENT
2586}
2587
2588static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV) {
2589 return GV->hasAppendingLinkage() &&
2590 StringSwitch<bool>(GV->getName())
2591 // TODO: Linker could still eliminate the GV if we just skip
2592 // handling llvm.used array. Skipping them for now until we or the
2593 // AIX OS team come up with a good solution.
2594 .Case(S: "llvm.used", Value: true)
2595 // It's correct to just skip llvm.compiler.used array here.
2596 .Case(S: "llvm.compiler.used", Value: true)
2597 .Default(Value: false);
2598}
2599
2600static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) {
2601 return StringSwitch<bool>(GV->getName())
2602 .Cases(S0: "llvm.global_ctors", S1: "llvm.global_dtors", Value: true)
2603 .Default(Value: false);
2604}
2605
2606uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {
2607 if (auto *GA = dyn_cast<GlobalAlias>(Val: C))
2608 return getAliasOffset(C: GA->getAliasee());
2609 if (auto *CE = dyn_cast<ConstantExpr>(Val: C)) {
2610 const MCExpr *LowC = lowerConstant(CV: CE);
2611 const MCBinaryExpr *CBE = dyn_cast<MCBinaryExpr>(Val: LowC);
2612 if (!CBE)
2613 return 0;
2614 if (CBE->getOpcode() != MCBinaryExpr::Add)
2615 report_fatal_error(reason: "Only adding an offset is supported now.");
2616 auto *RHS = dyn_cast<MCConstantExpr>(Val: CBE->getRHS());
2617 if (!RHS)
2618 report_fatal_error(reason: "Unable to get the offset of alias.");
2619 return RHS->getValue();
2620 }
2621 return 0;
2622}
2623
2624void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
2625 // Special LLVM global arrays have been handled at the initialization.
2626 if (isSpecialLLVMGlobalArrayToSkip(GV) || isSpecialLLVMGlobalArrayForStaticInit(GV))
2627 return;
2628
2629 // If the Global Variable has the toc-data attribute, it needs to be emitted
2630 // when we emit the .toc section.
2631 if (GV->hasAttribute(Kind: "toc-data")) {
2632 TOCDataGlobalVars.push_back(Elt: GV);
2633 return;
2634 }
2635
2636 emitGlobalVariableHelper(GV);
2637}
2638
2639void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
2640 assert(!GV->getName().starts_with("llvm.") &&
2641 "Unhandled intrinsic global variable.");
2642
2643 if (GV->hasComdat())
2644 report_fatal_error(reason: "COMDAT not yet supported by AIX.");
2645
2646 MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(Val: getSymbol(GV));
2647
2648 if (GV->isDeclarationForLinker()) {
2649 emitLinkage(GV, GVSym);
2650 return;
2651 }
2652
2653 SectionKind GVKind = getObjFileLowering().getKindForGlobal(GO: GV, TM);
2654 if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly() &&
2655 !GVKind.isThreadLocal()) // Checks for both ThreadData and ThreadBSS.
2656 report_fatal_error(reason: "Encountered a global variable kind that is "
2657 "not supported yet.");
2658
2659 // Print GV in verbose mode
2660 if (isVerbose()) {
2661 if (GV->hasInitializer()) {
2662 GV->printAsOperand(O&: OutStreamer->getCommentOS(),
2663 /*PrintType=*/false, M: GV->getParent());
2664 OutStreamer->getCommentOS() << '\n';
2665 }
2666 }
2667
2668 MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
2669 Val: getObjFileLowering().SectionForGlobal(GO: GV, Kind: GVKind, TM));
2670
2671 // Switch to the containing csect.
2672 OutStreamer->switchSection(Section: Csect);
2673
2674 const DataLayout &DL = GV->getParent()->getDataLayout();
2675
2676 // Handle common and zero-initialized local symbols.
2677 if (GV->hasCommonLinkage() || GVKind.isBSSLocal() ||
2678 GVKind.isThreadBSSLocal()) {
2679 Align Alignment = GV->getAlign().value_or(u: DL.getPreferredAlign(GV));
2680 uint64_t Size = DL.getTypeAllocSize(Ty: GV->getValueType());
2681 GVSym->setStorageClass(
2682 TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
2683
2684 if (GVKind.isBSSLocal() && Csect->getMappingClass() == XCOFF::XMC_TD) {
2685 OutStreamer->emitZeros(NumBytes: Size);
2686 } else if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal()) {
2687 assert(Csect->getMappingClass() != XCOFF::XMC_TD &&
2688 "BSS local toc-data already handled and TLS variables "
2689 "incompatible with XMC_TD");
2690 OutStreamer->emitXCOFFLocalCommonSymbol(
2691 LabelSym: OutContext.getOrCreateSymbol(Name: GVSym->getSymbolTableName()), Size,
2692 CsectSym: GVSym, Alignment);
2693 } else {
2694 OutStreamer->emitCommonSymbol(Symbol: GVSym, Size, ByteAlignment: Alignment);
2695 }
2696 return;
2697 }
2698
2699 MCSymbol *EmittedInitSym = GVSym;
2700
2701 // Emit linkage for the global variable and its aliases.
2702 emitLinkage(GV, GVSym: EmittedInitSym);
2703 for (const GlobalAlias *GA : GOAliasMap[GV])
2704 emitLinkage(GV: GA, GVSym: getSymbol(GV: GA));
2705
2706 emitAlignment(Alignment: getGVAlignment(GV, DL), GV);
2707
2708 // When -fdata-sections is enabled, every GlobalVariable will
2709 // be put into its own csect; therefore, label is not necessary here.
2710 if (!TM.getDataSections() || GV->hasSection())
2711 OutStreamer->emitLabel(Symbol: EmittedInitSym);
2712
2713 // No alias to emit.
2714 if (!GOAliasMap[GV].size()) {
2715 emitGlobalConstant(DL: GV->getParent()->getDataLayout(), CV: GV->getInitializer());
2716 return;
2717 }
2718
2719 // Aliases with the same offset should be aligned. Record the list of aliases
2720 // associated with the offset.
2721 AliasMapTy AliasList;
2722 for (const GlobalAlias *GA : GOAliasMap[GV])
2723 AliasList[getAliasOffset(C: GA->getAliasee())].push_back(Elt: GA);
2724
2725 // Emit alias label and element value for global variable.
2726 emitGlobalConstant(DL: GV->getParent()->getDataLayout(), CV: GV->getInitializer(),
2727 AliasList: &AliasList);
2728}
2729
2730void PPCAIXAsmPrinter::emitFunctionDescriptor() {
2731 const DataLayout &DL = getDataLayout();
2732 const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;
2733
2734 MCSectionSubPair Current = OutStreamer->getCurrentSection();
2735 // Emit function descriptor.
2736 OutStreamer->switchSection(
2737 Section: cast<MCSymbolXCOFF>(Val: CurrentFnDescSym)->getRepresentedCsect());
2738
2739 // Emit aliasing label for function descriptor csect.
2740 for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])
2741 OutStreamer->emitLabel(Symbol: getSymbol(GV: Alias));
2742
2743 // Emit function entry point address.
2744 OutStreamer->emitValue(Value: MCSymbolRefExpr::create(Symbol: CurrentFnSym, Ctx&: OutContext),
2745 Size: PointerSize);
2746 // Emit TOC base address.
2747 const MCSymbol *TOCBaseSym =
2748 cast<MCSectionXCOFF>(Val: getObjFileLowering().getTOCBaseSection())
2749 ->getQualNameSymbol();
2750 OutStreamer->emitValue(Value: MCSymbolRefExpr::create(Symbol: TOCBaseSym, Ctx&: OutContext),
2751 Size: PointerSize);
2752 // Emit a null environment pointer.
2753 OutStreamer->emitIntValue(Value: 0, Size: PointerSize);
2754
2755 OutStreamer->switchSection(Section: Current.first, Subsection: Current.second);
2756}
2757
2758void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
2759 // It's not necessary to emit the label when we have individual
2760 // function in its own csect.
2761 if (!TM.getFunctionSections())
2762 PPCAsmPrinter::emitFunctionEntryLabel();
2763
2764 // Emit aliasing label for function entry point label.
2765 for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])
2766 OutStreamer->emitLabel(
2767 Symbol: getObjFileLowering().getFunctionEntryPointSymbol(Func: Alias, TM));
2768}
2769
2770void PPCAIXAsmPrinter::emitPGORefs(Module &M) {
2771 if (!OutContext.hasXCOFFSection(
2772 Section: "__llvm_prf_cnts",
2773 CsectProp: XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
2774 return;
2775
2776 // When inside a csect `foo`, a .ref directive referring to a csect `bar`
2777 // translates into a relocation entry from `foo` to` bar`. The referring
2778 // csect, `foo`, is identified by its address. If multiple csects have the
2779 // same address (because one or more of them are zero-length), the referring
2780 // csect cannot be determined. Hence, we don't generate the .ref directives
2781 // if `__llvm_prf_cnts` is an empty section.
2782 bool HasNonZeroLengthPrfCntsSection = false;
2783 const DataLayout &DL = M.getDataLayout();
2784 for (GlobalVariable &GV : M.globals())
2785 if (GV.hasSection() && GV.getSection().equals(RHS: "__llvm_prf_cnts") &&
2786 DL.getTypeAllocSize(Ty: GV.getValueType()) > 0) {
2787 HasNonZeroLengthPrfCntsSection = true;
2788 break;
2789 }
2790
2791 if (HasNonZeroLengthPrfCntsSection) {
2792 MCSection *CntsSection = OutContext.getXCOFFSection(
2793 Section: "__llvm_prf_cnts", K: SectionKind::getData(),
2794 CsectProp: XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),
2795 /*MultiSymbolsAllowed*/ true);
2796
2797 OutStreamer->switchSection(Section: CntsSection);
2798 if (OutContext.hasXCOFFSection(
2799 Section: "__llvm_prf_data",
2800 CsectProp: XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
2801 MCSymbol *S = OutContext.getOrCreateSymbol(Name: "__llvm_prf_data[RW]");
2802 OutStreamer->emitXCOFFRefDirective(Symbol: S);
2803 }
2804 if (OutContext.hasXCOFFSection(
2805 Section: "__llvm_prf_names",
2806 CsectProp: XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD))) {
2807 MCSymbol *S = OutContext.getOrCreateSymbol(Name: "__llvm_prf_names[RO]");
2808 OutStreamer->emitXCOFFRefDirective(Symbol: S);
2809 }
2810 if (OutContext.hasXCOFFSection(
2811 Section: "__llvm_prf_vnds",
2812 CsectProp: XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
2813 MCSymbol *S = OutContext.getOrCreateSymbol(Name: "__llvm_prf_vnds[RW]");
2814 OutStreamer->emitXCOFFRefDirective(Symbol: S);
2815 }
2816 }
2817}
2818
2819void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
2820 // If there are no functions and there are no toc-data definitions in this
2821 // module, we will never need to reference the TOC base.
2822 if (M.empty() && TOCDataGlobalVars.empty())
2823 return;
2824
2825 emitPGORefs(M);
2826
2827 // Switch to section to emit TOC base.
2828 OutStreamer->switchSection(Section: getObjFileLowering().getTOCBaseSection());
2829
2830 PPCTargetStreamer *TS =
2831 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2832
2833 for (auto &I : TOC) {
2834 MCSectionXCOFF *TCEntry;
2835 // Setup the csect for the current TC entry. If the variant kind is
2836 // VK_PPC_AIX_TLSGDM the entry represents the region handle, we create a
2837 // new symbol to prefix the name with a dot.
2838 if (I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM) {
2839 SmallString<128> Name;
2840 StringRef Prefix = ".";
2841 Name += Prefix;
2842 Name += cast<MCSymbolXCOFF>(Val: I.first.first)->getSymbolTableName();
2843 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
2844 TCEntry = cast<MCSectionXCOFF>(
2845 Val: getObjFileLowering().getSectionForTOCEntry(S, TM));
2846 } else {
2847 TCEntry = cast<MCSectionXCOFF>(
2848 Val: getObjFileLowering().getSectionForTOCEntry(S: I.first.first, TM));
2849 }
2850 OutStreamer->switchSection(Section: TCEntry);
2851
2852 OutStreamer->emitLabel(Symbol: I.second);
2853 TS->emitTCEntry(S: *I.first.first, Kind: I.first.second);
2854 }
2855
2856 // Traverse the list of global variables twice, emitting all of the
2857 // non-common global variables before the common ones, as emitting a
2858 // .comm directive changes the scope from .toc to the common symbol.
2859 for (const auto *GV : TOCDataGlobalVars) {
2860 if (!GV->hasCommonLinkage())
2861 emitGlobalVariableHelper(GV);
2862 }
2863 for (const auto *GV : TOCDataGlobalVars) {
2864 if (GV->hasCommonLinkage())
2865 emitGlobalVariableHelper(GV);
2866 }
2867}
2868
2869bool PPCAIXAsmPrinter::doInitialization(Module &M) {
2870 const bool Result = PPCAsmPrinter::doInitialization(M);
2871
2872 auto setCsectAlignment = [this](const GlobalObject *GO) {
2873 // Declarations have 0 alignment which is set by default.
2874 if (GO->isDeclarationForLinker())
2875 return;
2876
2877 SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);
2878 MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
2879 Val: getObjFileLowering().SectionForGlobal(GO, Kind: GOKind, TM));
2880
2881 Align GOAlign = getGVAlignment(GV: GO, DL: GO->getParent()->getDataLayout());
2882 Csect->ensureMinAlignment(MinAlignment: GOAlign);
2883 };
2884
2885 // For all TLS variables, calculate their corresponding addresses and store
2886 // them into TLSVarsToAddressMapping, which will be used to determine whether
2887 // or not local-exec TLS variables require special assembly printing.
2888 uint64_t TLSVarAddress = 0;
2889 auto DL = M.getDataLayout();
2890 for (const auto &G : M.globals()) {
2891 if (G.isThreadLocal() && !G.isDeclaration()) {
2892 TLSVarAddress = alignTo(Size: TLSVarAddress, A: getGVAlignment(GV: &G, DL));
2893 TLSVarsToAddressMapping[&G] = TLSVarAddress;
2894 TLSVarAddress += DL.getTypeAllocSize(Ty: G.getValueType());
2895 }
2896 }
2897
2898 // We need to know, up front, the alignment of csects for the assembly path,
2899 // because once a .csect directive gets emitted, we could not change the
2900 // alignment value on it.
2901 for (const auto &G : M.globals()) {
2902 if (isSpecialLLVMGlobalArrayToSkip(GV: &G))
2903 continue;
2904
2905 if (isSpecialLLVMGlobalArrayForStaticInit(GV: &G)) {
2906 // Generate a format indicator and a unique module id to be a part of
2907 // the sinit and sterm function names.
2908 if (FormatIndicatorAndUniqueModId.empty()) {
2909 std::string UniqueModuleId = getUniqueModuleId(M: &M);
2910 if (UniqueModuleId != "")
2911 // TODO: Use source file full path to generate the unique module id
2912 // and add a format indicator as a part of function name in case we
2913 // will support more than one format.
2914 FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(pos: 1);
2915 else {
2916 // Use threadId, Pid, and current time as the unique module id when we
2917 // cannot generate one based on a module's strong external symbols.
2918 auto CurTime =
2919 std::chrono::duration_cast<std::chrono::nanoseconds>(
2920 d: std::chrono::steady_clock::now().time_since_epoch())
2921 .count();
2922 FormatIndicatorAndUniqueModId =
2923 "clangPidTidTime_" + llvm::itostr(X: sys::Process::getProcessId()) +
2924 "_" + llvm::itostr(X: llvm::get_threadid()) + "_" +
2925 llvm::itostr(X: CurTime);
2926 }
2927 }
2928
2929 emitSpecialLLVMGlobal(GV: &G);
2930 continue;
2931 }
2932
2933 setCsectAlignment(&G);
2934 }
2935
2936 for (const auto &F : M)
2937 setCsectAlignment(&F);
2938
2939 // Construct an aliasing list for each GlobalObject.
2940 for (const auto &Alias : M.aliases()) {
2941 const GlobalObject *Aliasee = Alias.getAliaseeObject();
2942 if (!Aliasee)
2943 report_fatal_error(
2944 reason: "alias without a base object is not yet supported on AIX");
2945
2946 if (Aliasee->hasCommonLinkage()) {
2947 report_fatal_error(reason: "Aliases to common variables are not allowed on AIX:"
2948 "\n\tAlias attribute for " +
2949 Alias.getGlobalIdentifier() +
2950 " is invalid because " + Aliasee->getName() +
2951 " is common.",
2952 gen_crash_diag: false);
2953 }
2954
2955 GOAliasMap[Aliasee].push_back(Elt: &Alias);
2956 }
2957
2958 return Result;
2959}
2960
2961void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {
2962 switch (MI->getOpcode()) {
2963 default:
2964 break;
2965 case PPC::TW:
2966 case PPC::TWI:
2967 case PPC::TD:
2968 case PPC::TDI: {
2969 if (MI->getNumOperands() < 5)
2970 break;
2971 const MachineOperand &LangMO = MI->getOperand(i: 3);
2972 const MachineOperand &ReasonMO = MI->getOperand(i: 4);
2973 if (!LangMO.isImm() || !ReasonMO.isImm())
2974 break;
2975 MCSymbol *TempSym = OutContext.createNamedTempSymbol();
2976 OutStreamer->emitLabel(Symbol: TempSym);
2977 OutStreamer->emitXCOFFExceptDirective(Symbol: CurrentFnSym, Trap: TempSym,
2978 Lang: LangMO.getImm(), Reason: ReasonMO.getImm(),
2979 FunctionSize: Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 8 :
2980 MI->getMF()->getInstructionCount() * 4,
2981 hasDebug: MMI->hasDebugInfo());
2982 break;
2983 }
2984 case PPC::GETtlsTpointer32AIX:
2985 case PPC::GETtlsADDR64AIX:
2986 case PPC::GETtlsADDR32AIX: {
2987 // A reference to .__tls_get_addr/.__get_tpointer is unknown to the
2988 // assembler so we need to emit an external symbol reference.
2989 MCSymbol *TlsGetAddr =
2990 createMCSymbolForTlsGetAddr(Ctx&: OutContext, MIOpc: MI->getOpcode());
2991 ExtSymSDNodeSymbols.insert(Ptr: TlsGetAddr);
2992 break;
2993 }
2994 case PPC::BL8:
2995 case PPC::BL:
2996 case PPC::BL8_NOP:
2997 case PPC::BL_NOP: {
2998 const MachineOperand &MO = MI->getOperand(i: 0);
2999 if (MO.isSymbol()) {
3000 MCSymbolXCOFF *S =
3001 cast<MCSymbolXCOFF>(Val: OutContext.getOrCreateSymbol(Name: MO.getSymbolName()));
3002 ExtSymSDNodeSymbols.insert(Ptr: S);
3003 }
3004 } break;
3005 case PPC::BL_TLS:
3006 case PPC::BL8_TLS:
3007 case PPC::BL8_TLS_:
3008 case PPC::BL8_NOP_TLS:
3009 report_fatal_error(reason: "TLS call not yet implemented");
3010 case PPC::TAILB:
3011 case PPC::TAILB8:
3012 case PPC::TAILBA:
3013 case PPC::TAILBA8:
3014 case PPC::TAILBCTR:
3015 case PPC::TAILBCTR8:
3016 if (MI->getOperand(i: 0).isSymbol())
3017 report_fatal_error(reason: "Tail call for extern symbol not yet supported.");
3018 break;
3019 case PPC::DST:
3020 case PPC::DST64:
3021 case PPC::DSTT:
3022 case PPC::DSTT64:
3023 case PPC::DSTST:
3024 case PPC::DSTST64:
3025 case PPC::DSTSTT:
3026 case PPC::DSTSTT64:
3027 EmitToStreamer(
3028 *OutStreamer,
3029 MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));
3030 return;
3031 }
3032 return PPCAsmPrinter::emitInstruction(MI);
3033}
3034
3035bool PPCAIXAsmPrinter::doFinalization(Module &M) {
3036 // Do streamer related finalization for DWARF.
3037 if (!MAI->usesDwarfFileAndLocDirectives() && MMI->hasDebugInfo())
3038 OutStreamer->doFinalizationAtSectionEnd(
3039 Section: OutStreamer->getContext().getObjectFileInfo()->getTextSection());
3040
3041 for (MCSymbol *Sym : ExtSymSDNodeSymbols)
3042 OutStreamer->emitSymbolAttribute(Symbol: Sym, Attribute: MCSA_Extern);
3043 return PPCAsmPrinter::doFinalization(M);
3044}
3045
3046static unsigned mapToSinitPriority(int P) {
3047 if (P < 0 || P > 65535)
3048 report_fatal_error(reason: "invalid init priority");
3049
3050 if (P <= 20)
3051 return P;
3052
3053 if (P < 81)
3054 return 20 + (P - 20) * 16;
3055
3056 if (P <= 1124)
3057 return 1004 + (P - 81);
3058
3059 if (P < 64512)
3060 return 2047 + (P - 1124) * 33878;
3061
3062 return 2147482625u + (P - 64512);
3063}
3064
3065static std::string convertToSinitPriority(int Priority) {
3066 // This helper function converts clang init priority to values used in sinit
3067 // and sterm functions.
3068 //
3069 // The conversion strategies are:
3070 // We map the reserved clang/gnu priority range [0, 100] into the sinit/sterm
3071 // reserved priority range [0, 1023] by
3072 // - directly mapping the first 21 and the last 20 elements of the ranges
3073 // - linear interpolating the intermediate values with a step size of 16.
3074 //
3075 // We map the non reserved clang/gnu priority range of [101, 65535] into the
3076 // sinit/sterm priority range [1024, 2147483648] by:
3077 // - directly mapping the first and the last 1024 elements of the ranges
3078 // - linear interpolating the intermediate values with a step size of 33878.
3079 unsigned int P = mapToSinitPriority(P: Priority);
3080
3081 std::string PrioritySuffix;
3082 llvm::raw_string_ostream os(PrioritySuffix);
3083 os << llvm::format_hex_no_prefix(N: P, Width: 8);
3084 os.flush();
3085 return PrioritySuffix;
3086}
3087
3088void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL,
3089 const Constant *List, bool IsCtor) {
3090 SmallVector<Structor, 8> Structors;
3091 preprocessXXStructorList(DL, List, Structors);
3092 if (Structors.empty())
3093 return;
3094
3095 unsigned Index = 0;
3096 for (Structor &S : Structors) {
3097 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(Val: S.Func))
3098 S.Func = CE->getOperand(i_nocapture: 0);
3099
3100 llvm::GlobalAlias::create(
3101 Linkage: GlobalValue::ExternalLinkage,
3102 Name: (IsCtor ? llvm::Twine("__sinit") : llvm::Twine("__sterm")) +
3103 llvm::Twine(convertToSinitPriority(Priority: S.Priority)) +
3104 llvm::Twine("_", FormatIndicatorAndUniqueModId) +
3105 llvm::Twine("_", llvm::utostr(X: Index++)),
3106 Aliasee: cast<Function>(Val: S.Func));
3107 }
3108}
3109
3110void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV,
3111 unsigned Encoding) {
3112 if (GV) {
3113 TOCEntryType GlobalType = TOCType_GlobalInternal;
3114 GlobalValue::LinkageTypes Linkage = GV->getLinkage();
3115 if (Linkage == GlobalValue::ExternalLinkage ||
3116 Linkage == GlobalValue::AvailableExternallyLinkage ||
3117 Linkage == GlobalValue::ExternalWeakLinkage)
3118 GlobalType = TOCType_GlobalExternal;
3119 MCSymbol *TypeInfoSym = TM.getSymbol(GV);
3120 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(Sym: TypeInfoSym, Type: GlobalType);
3121 const MCSymbol *TOCBaseSym =
3122 cast<MCSectionXCOFF>(Val: getObjFileLowering().getTOCBaseSection())
3123 ->getQualNameSymbol();
3124 auto &Ctx = OutStreamer->getContext();
3125 const MCExpr *Exp =
3126 MCBinaryExpr::createSub(LHS: MCSymbolRefExpr::create(Symbol: TOCEntry, Ctx),
3127 RHS: MCSymbolRefExpr::create(Symbol: TOCBaseSym, Ctx), Ctx);
3128 OutStreamer->emitValue(Value: Exp, Size: GetSizeOfEncodedValue(Encoding));
3129 } else
3130 OutStreamer->emitIntValue(Value: 0, Size: GetSizeOfEncodedValue(Encoding));
3131}
3132
3133// Return a pass that prints the PPC assembly code for a MachineFunction to the
3134// given output stream.
3135static AsmPrinter *
3136createPPCAsmPrinterPass(TargetMachine &tm,
3137 std::unique_ptr<MCStreamer> &&Streamer) {
3138 if (tm.getTargetTriple().isOSAIX())
3139 return new PPCAIXAsmPrinter(tm, std::move(Streamer));
3140
3141 return new PPCLinuxAsmPrinter(tm, std::move(Streamer));
3142}
3143
3144void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {
3145 const NamedMDNode *NMD = M.getNamedMetadata(Name: "llvm.commandline");
3146 if (!NMD || !NMD->getNumOperands())
3147 return;
3148
3149 std::string S;
3150 raw_string_ostream RSOS(S);
3151 for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
3152 const MDNode *N = NMD->getOperand(i);
3153 assert(N->getNumOperands() == 1 &&
3154 "llvm.commandline metadata entry can have only one operand");
3155 const MDString *MDS = cast<MDString>(Val: N->getOperand(I: 0));
3156 // Add "@(#)" to support retrieving the command line information with the
3157 // AIX "what" command
3158 RSOS << "@(#)opt " << MDS->getString() << "\n";
3159 RSOS.write(C: '\0');
3160 }
3161 OutStreamer->emitXCOFFCInfoSym(Name: ".GCC.command.line", Metadata: RSOS.str());
3162}
3163
3164// Force static initialization.
3165extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmPrinter() {
3166 TargetRegistry::RegisterAsmPrinter(T&: getThePPC32Target(),
3167 Fn: createPPCAsmPrinterPass);
3168 TargetRegistry::RegisterAsmPrinter(T&: getThePPC32LETarget(),
3169 Fn: createPPCAsmPrinterPass);
3170 TargetRegistry::RegisterAsmPrinter(T&: getThePPC64Target(),
3171 Fn: createPPCAsmPrinterPass);
3172 TargetRegistry::RegisterAsmPrinter(T&: getThePPC64LETarget(),
3173 Fn: createPPCAsmPrinterPass);
3174}
3175

source code of llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp