LLVM 24.0.0git
PPCAsmPrinter.cpp
Go to the documentation of this file.
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
23#include "PPC.h"
24#include "PPCInstrInfo.h"
26#include "PPCSubtarget.h"
27#include "PPCTargetMachine.h"
29#include "llvm/ADT/MapVector.h"
30#include "llvm/ADT/SetVector.h"
31#include "llvm/ADT/Statistic.h"
33#include "llvm/ADT/StringRef.h"
34#include "llvm/ADT/Twine.h"
46#include "llvm/IR/DataLayout.h"
47#include "llvm/IR/GlobalValue.h"
49#include "llvm/IR/Module.h"
51#include "llvm/MC/MCAsmInfo.h"
52#include "llvm/MC/MCContext.h"
54#include "llvm/MC/MCExpr.h"
55#include "llvm/MC/MCInst.h"
59#include "llvm/MC/MCStreamer.h"
60#include "llvm/MC/MCSymbol.h"
61#include "llvm/MC/MCSymbolELF.h"
63#include "llvm/MC/SectionKind.h"
68#include "llvm/Support/Debug.h"
69#include "llvm/Support/Error.h"
79#include <cassert>
80#include <cstdint>
81#include <memory>
82#include <new>
83
84using namespace llvm;
85using namespace llvm::XCOFF;
86using namespace PatternMatch;
87
88#define DEBUG_TYPE "asmprinter"
89
90STATISTIC(NumTOCEntries, "Number of Total TOC Entries Emitted.");
91STATISTIC(NumTOCConstPool, "Number of Constant Pool TOC Entries.");
92STATISTIC(NumTOCGlobalInternal,
93 "Number of Internal Linkage Global TOC Entries.");
94STATISTIC(NumTOCGlobalExternal,
95 "Number of External Linkage Global TOC Entries.");
96STATISTIC(NumTOCJumpTable, "Number of Jump Table TOC Entries.");
97STATISTIC(NumTOCThreadLocal, "Number of Thread Local TOC Entries.");
98STATISTIC(NumTOCBlockAddress, "Number of Block Address TOC Entries.");
99STATISTIC(NumTOCEHBlock, "Number of EH Block TOC Entries.");
100
102 "ppc-aix-ssp-tb-bit", cl::init(false),
103 cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden);
104
106 "ppc-ifunc-local-if-proven", cl::init(false),
107 cl::desc("During ifunc lowering, the compiler assumes the resolver returns "
108 "dso-local functions and bails out if non-local functions are "
109 "detected; this flag flips the assumption: resolver returns "
110 "preemptible functions unless the compiler can prove all paths "
111 "return local functions."),
112 cl::Hidden);
113
114// this flag is used for testing only as it might generate bad code.
115static cl::opt<bool> IFuncWarnInsteadOfError("ppc-test-ifunc-warn-noerror",
116 cl::init(false), cl::ReallyHidden);
117
118// Specialize DenseMapInfo to allow
119// std::pair<const MCSymbol *, PPCMCExpr::Specifier> in DenseMap.
120// This specialization is needed here because that type is used as keys in the
121// map representing TOC entries.
122namespace llvm {
123template <>
124struct DenseMapInfo<std::pair<const MCSymbol *, PPCMCExpr::Specifier>> {
125 using TOCKey = std::pair<const MCSymbol *, PPCMCExpr::Specifier>;
126
127 static unsigned getHashValue(const TOCKey &PairVal) {
130 DenseMapInfo<int>::getHashValue(PairVal.second));
131 }
132 static bool isEqual(const TOCKey &A, const TOCKey &B) { return A == B; }
133};
134} // end namespace llvm
135
136namespace {
137
138enum {
139 // GNU attribute tags for PowerPC ABI
140 Tag_GNU_Power_ABI_FP = 4,
141 Tag_GNU_Power_ABI_Vector = 8,
142 Tag_GNU_Power_ABI_Struct_Return = 12,
143
144 // GNU attribute values for PowerPC float ABI, as combination of two parts
145 Val_GNU_Power_ABI_NoFloat = 0b00,
146 Val_GNU_Power_ABI_HardFloat_DP = 0b01,
147 Val_GNU_Power_ABI_SoftFloat_DP = 0b10,
148 Val_GNU_Power_ABI_HardFloat_SP = 0b11,
149
150 Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,
151 Val_GNU_Power_ABI_LDBL_64 = 0b1000,
152 Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,
153};
154
155class PPCAsmPrinter : public AsmPrinter {
156protected:
157 // For TLS on AIX, we need to be able to identify TOC entries of specific
158 // specifier so we can add the right relocations when we generate the
159 // entries. So each entry is represented by a pair of MCSymbol and
160 // VariantKind. For example, we need to be able to identify the following
161 // entry as a TLSGD entry so we can add the @m relocation:
162 // .tc .i[TC],i[TL]@m
163 // By default, 0 is used for the specifier.
164 MapVector<std::pair<const MCSymbol *, PPCMCExpr::Specifier>, MCSymbol *> TOC;
165 const PPCSubtarget *Subtarget = nullptr;
166
167 // Keep track of the number of TLS variables and their corresponding
168 // addresses, which is then used for the assembly printing of
169 // non-TOC-based local-exec variables.
170 MapVector<const GlobalValue *, uint64_t> TLSVarsToAddressMapping;
171
172public:
173 explicit PPCAsmPrinter(TargetMachine &TM,
174 std::unique_ptr<MCStreamer> Streamer, char &ID)
175 : AsmPrinter(TM, std::move(Streamer), ID) {}
176
177 StringRef getPassName() const override { return "PowerPC Assembly Printer"; }
178
179 enum TOCEntryType {
180 TOCType_ConstantPool,
181 TOCType_GlobalExternal,
182 TOCType_GlobalInternal,
183 TOCType_JumpTable,
184 TOCType_ThreadLocal,
185 TOCType_BlockAddress,
186 TOCType_EHBlock
187 };
188
189 MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,
191
192 bool doInitialization(Module &M) override {
193 if (!TOC.empty())
194 TOC.clear();
196 }
197
198 const MCExpr *symbolWithSpecifier(const MCSymbol *S,
200 void emitInstruction(const MachineInstr *MI) override;
201
202 /// This function is for PrintAsmOperand and PrintAsmMemoryOperand,
203 /// invoked by EmitMSInlineAsmStr and EmitGCCInlineAsmStr only.
204 /// The \p MI would be INLINEASM ONLY.
205 void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
206
207 void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
208 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
209 const char *ExtraCode, raw_ostream &O) override;
210 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
211 const char *ExtraCode, raw_ostream &O) override;
212
213 void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);
214 void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI);
215 void emitTlsCall(const MachineInstr *MI, PPCMCExpr::Specifier VK);
216 void EmitAIXTlsCallHelper(const MachineInstr *MI);
217 const MCExpr *getAdjustedFasterLocalExpr(const MachineOperand &MO,
218 int64_t Offset);
219 bool runOnMachineFunction(MachineFunction &MF) override {
220 Subtarget = &MF.getSubtarget<PPCSubtarget>();
222 emitXRayTable();
223 return Changed;
224 }
225};
226
227/// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux
228class PPCLinuxAsmPrinter : public PPCAsmPrinter {
229public:
230 static char ID;
231
232 explicit PPCLinuxAsmPrinter(TargetMachine &TM,
233 std::unique_ptr<MCStreamer> Streamer)
234 : PPCAsmPrinter(TM, std::move(Streamer), ID) {}
235
236 StringRef getPassName() const override {
237 return "Linux PPC Assembly Printer";
238 }
239
240 void emitGNUAttributes(Module &M);
241
242 void emitStartOfAsmFile(Module &M) override;
243 void emitEndOfAsmFile(Module &) override;
244
245 void emitFunctionEntryLabel() override;
246
247 void emitFunctionBodyStart() override;
248 void emitFunctionBodyEnd() override;
249 void emitInstruction(const MachineInstr *MI) override;
250};
251
252class PPCAIXAsmPrinter : public PPCAsmPrinter {
253private:
254 /// Symbols lowered from ExternalSymbolSDNodes, we will need to emit extern
255 /// linkage for them in AIX.
256 SmallSetVector<MCSymbol *, 8> ExtSymSDNodeSymbols;
257
258 /// A format indicator and unique trailing identifier to form part of the
259 /// sinit/sterm function names.
260 std::string FormatIndicatorAndUniqueModId;
261
262 // Record a list of GlobalAlias associated with a GlobalObject.
263 // This is used for AIX's extra-label-at-definition aliasing strategy.
264 DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
265 GOAliasMap;
266
267 uint16_t getNumberOfVRSaved();
268 void emitTracebackTable();
269
271
272 void emitGlobalVariableHelper(const GlobalVariable *);
273
274 // Get the offset of an alias based on its AliaseeObject.
275 uint64_t getAliasOffset(const Constant *C);
276
277public:
278 static char ID;
279
280 PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
281 : PPCAsmPrinter(TM, std::move(Streamer), ID) {
282 if (MAI.isLittleEndian())
284 "cannot create AIX PPC Assembly Printer for a little-endian target");
285 }
286
287 StringRef getPassName() const override { return "AIX PPC Assembly Printer"; }
288
289 bool doInitialization(Module &M) override;
290
291 void emitXXStructorList(const DataLayout &DL, const Constant *List,
292 bool IsCtor) override;
293
294 void SetupMachineFunction(MachineFunction &MF) override;
295
296 void emitGlobalVariable(const GlobalVariable *GV) override;
297
298 void emitFunctionDescriptor() override;
299
300 void emitFunctionEntryLabel() override;
301
302 void emitFunctionBodyEnd() override;
303
304 void emitPGORefs(Module &M);
305
306 void emitGCOVRefs();
307
308 void emitEndOfAsmFile(Module &) override;
309
310 void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
311
312 void emitInstruction(const MachineInstr *MI) override;
313
314 bool doFinalization(Module &M) override;
315
316 void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override;
317
318 void emitModuleCommandLines(Module &M) override;
319
320 void emitRefMetadata(const GlobalObject *);
321
322 void emitGlobalIFunc(Module &M, const GlobalIFunc &GI) override;
323};
324
325} // end anonymous namespace
326
327void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
328 raw_ostream &O) {
329 // Computing the address of a global symbol, not calling it.
330 const GlobalValue *GV = MO.getGlobal();
331 getSymbol(GV)->print(O, MAI);
332 printOffset(MO.getOffset(), O);
333}
334
335void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
336 raw_ostream &O) {
337 const DataLayout &DL = getDataLayout();
338 const MachineOperand &MO = MI->getOperand(OpNo);
339
340 switch (MO.getType()) {
342 // The MI is INLINEASM ONLY and UseVSXReg is always false.
344
345 // Linux assembler (Others?) does not take register mnemonics.
346 // FIXME - What about special registers used in mfspr/mtspr?
348 return;
349 }
351 O << MO.getImm();
352 return;
353
355 MO.getMBB()->getSymbol()->print(O, MAI);
356 return;
358 O << DL.getInternalSymbolPrefix() << "CPI" << getFunctionNumber() << '_'
359 << MO.getIndex();
360 return;
362 GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
363 return;
365 PrintSymbolOperand(MO, O);
366 return;
367 }
368
369 default:
370 O << "<unknown operand type: " << (unsigned)MO.getType() << ">";
371 return;
372 }
373}
374
375/// PrintAsmOperand - Print out an operand for an inline asm expression.
376///
377bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
378 const char *ExtraCode, raw_ostream &O) {
379 // Does this asm operand have a single letter operand modifier?
380 if (ExtraCode && ExtraCode[0]) {
381 if (ExtraCode[1] != 0) return true; // Unknown modifier.
382
383 switch (ExtraCode[0]) {
384 default:
385 // See if this is a generic print operand
386 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
387 case 'L': // Write second word of DImode reference.
388 // Verify that this operand has two consecutive registers.
389 if (!MI->getOperand(OpNo).isReg() ||
390 OpNo+1 == MI->getNumOperands() ||
391 !MI->getOperand(OpNo+1).isReg())
392 return true;
393 ++OpNo; // Return the high-part.
394 break;
395 case 'I':
396 // Write 'i' if an integer constant, otherwise nothing. Used to print
397 // addi vs add, etc.
398 if (MI->getOperand(OpNo).isImm())
399 O << "i";
400 return false;
401 case 'x':
402 if(!MI->getOperand(OpNo).isReg())
403 return true;
404 // This operand uses VSX numbering.
405 // If the operand is a VMX register, convert it to a VSX register.
406 Register Reg = MI->getOperand(OpNo).getReg();
408 Reg = PPC::VSX32 + (Reg - PPC::V0);
409 else if (PPC::isVFRegister(Reg))
410 Reg = PPC::VSX32 + (Reg - PPC::VF0);
411 const char *RegName;
414 O << RegName;
415 return false;
416 }
417 }
418
419 printOperand(MI, OpNo, O);
420 return false;
421}
422
423// At the moment, all inline asm memory operands are a single register.
424// In any case, the output of this routine should always be just one
425// assembler operand.
426bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
427 const char *ExtraCode,
428 raw_ostream &O) {
429 if (ExtraCode && ExtraCode[0]) {
430 if (ExtraCode[1] != 0) return true; // Unknown modifier.
431
432 switch (ExtraCode[0]) {
433 default: return true; // Unknown modifier.
434 case 'L': // A memory reference to the upper word of a double word op.
435 O << getDataLayout().getPointerSize() << "(";
436 printOperand(MI, OpNo, O);
437 O << ")";
438 return false;
439 case 'y': // A memory reference for an X-form instruction
440 O << "0, ";
441 printOperand(MI, OpNo, O);
442 return false;
443 case 'I':
444 // Write 'i' if an integer constant, otherwise nothing. Used to print
445 // addi vs add, etc.
446 if (MI->getOperand(OpNo).isImm())
447 O << "i";
448 return false;
449 case 'U': // Print 'u' for update form.
450 case 'X': // Print 'x' for indexed form.
451 // FIXME: Currently for PowerPC memory operands are always loaded
452 // into a register, so we never get an update or indexed form.
453 // This is bad even for offset forms, since even if we know we
454 // have a value in -16(r1), we will generate a load into r<n>
455 // and then load from 0(r<n>). Until that issue is fixed,
456 // tolerate 'U' and 'X' but don't output anything.
457 assert(MI->getOperand(OpNo).isReg());
458 return false;
459 }
460 }
461
462 assert(MI->getOperand(OpNo).isReg());
463 O << "0(";
464 printOperand(MI, OpNo, O);
465 O << ")";
466 return false;
467}
468
469static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type) {
470 ++NumTOCEntries;
471 switch (Type) {
472 case PPCAsmPrinter::TOCType_ConstantPool:
473 ++NumTOCConstPool;
474 break;
475 case PPCAsmPrinter::TOCType_GlobalInternal:
476 ++NumTOCGlobalInternal;
477 break;
478 case PPCAsmPrinter::TOCType_GlobalExternal:
479 ++NumTOCGlobalExternal;
480 break;
481 case PPCAsmPrinter::TOCType_JumpTable:
482 ++NumTOCJumpTable;
483 break;
484 case PPCAsmPrinter::TOCType_ThreadLocal:
485 ++NumTOCThreadLocal;
486 break;
487 case PPCAsmPrinter::TOCType_BlockAddress:
488 ++NumTOCBlockAddress;
489 break;
490 case PPCAsmPrinter::TOCType_EHBlock:
491 ++NumTOCEHBlock;
492 break;
493 }
494}
495
497 const TargetMachine &TM,
498 const MachineOperand &MO) {
499 CodeModel::Model ModuleModel = TM.getCodeModel();
500
501 // If the operand is not a global address then there is no
502 // global variable to carry an attribute.
504 return ModuleModel;
505
506 const GlobalValue *GV = MO.getGlobal();
507 assert(GV && "expected global for MO_GlobalAddress");
508
509 return S.getCodeModel(TM, GV);
510}
511
513 switch (CM) {
514 case CodeModel::Large:
516 return;
517 case CodeModel::Small:
519 return;
520 default:
521 report_fatal_error("Invalid code model for AIX");
522 }
523}
524
525/// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry
526/// exists for it. If not, create one. Then return a symbol that references
527/// the TOC entry.
528MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym,
529 TOCEntryType Type,
531 // If this is a new TOC entry add statistics about it.
532 auto [It, Inserted] = TOC.try_emplace({Sym, Spec});
533 if (Inserted)
535
536 MCSymbol *&TOCEntry = It->second;
537 if (!TOCEntry)
538 TOCEntry = createTempSymbol("C");
539 return TOCEntry;
540}
541
542void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {
543 unsigned NumNOPBytes = MI.getOperand(1).getImm();
544
545 auto &Ctx = OutStreamer->getContext();
546 MCSymbol *MILabel = Ctx.createTempSymbol();
547 OutStreamer->emitLabel(MILabel);
548
549 SM.recordStackMap(*MILabel, MI);
550 assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
551
552 // Scan ahead to trim the shadow.
553 const MachineBasicBlock &MBB = *MI.getParent();
555 ++MII;
556 while (NumNOPBytes > 0) {
557 if (MII != MBB.end() && MII->isDebugInstr()) {
558 ++MII;
559 continue;
560 }
561 if (MII == MBB.end() || MII->isCall() ||
562 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
563 MII->getOpcode() == TargetOpcode::STACKMAP)
564 break;
565 ++MII;
566 NumNOPBytes -= 4;
567 }
568
569 // Emit nops.
570 for (unsigned i = 0; i < NumNOPBytes; i += 4)
571 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
572}
573
574// Lower a patchpoint of the form:
575// [<def>], <id>, <numBytes>, <target>, <numArgs>
576void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {
577 auto &Ctx = OutStreamer->getContext();
578 MCSymbol *MILabel = Ctx.createTempSymbol();
579 OutStreamer->emitLabel(MILabel);
580
581 SM.recordPatchPoint(*MILabel, MI);
582 PatchPointOpers Opers(&MI);
583
584 unsigned EncodedBytes = 0;
585 const MachineOperand &CalleeMO = Opers.getCallTarget();
586
587 if (CalleeMO.isImm()) {
588 int64_t CallTarget = CalleeMO.getImm();
589 if (CallTarget) {
590 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
591 "High 16 bits of call target should be zero.");
592 Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
593 EncodedBytes = 0;
594 // Materialize the jump address:
595 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)
596 .addReg(ScratchReg)
597 .addImm((CallTarget >> 32) & 0xFFFF));
598 ++EncodedBytes;
599
600 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC)
601 .addReg(ScratchReg)
602 .addReg(ScratchReg)
603 .addImm(32).addImm(16));
604 ++EncodedBytes;
605
606 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8)
607 .addReg(ScratchReg)
608 .addReg(ScratchReg)
609 .addImm((CallTarget >> 16) & 0xFFFF));
610 ++EncodedBytes;
611
612 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8)
613 .addReg(ScratchReg)
614 .addReg(ScratchReg)
615 .addImm(CallTarget & 0xFFFF));
616 ++EncodedBytes;
617
618 // Save the current TOC pointer before the remote call.
619 int TOCSaveOffset = Subtarget->getFrameLowering()->getTOCSaveOffset();
620 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD)
621 .addReg(PPC::X2)
622 .addImm(TOCSaveOffset)
623 .addReg(PPC::X1));
624 ++EncodedBytes;
625
626 // If we're on ELFv1, then we need to load the actual function pointer
627 // from the function descriptor.
628 if (!Subtarget->isELFv2ABI()) {
629 // Load the new TOC pointer and the function address, but not r11
630 // (needing this is rare, and loading it here would prevent passing it
631 // via a 'nest' parameter.
632 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
633 .addReg(PPC::X2)
634 .addImm(8)
635 .addReg(ScratchReg));
636 ++EncodedBytes;
637
638 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
639 .addReg(ScratchReg)
640 .addImm(0)
641 .addReg(ScratchReg));
642 ++EncodedBytes;
643 }
644
645 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8)
646 .addReg(ScratchReg));
647 ++EncodedBytes;
648
649 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8));
650 ++EncodedBytes;
651
652 // Restore the TOC pointer after the call.
653 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
654 .addReg(PPC::X2)
655 .addImm(TOCSaveOffset)
656 .addReg(PPC::X1));
657 ++EncodedBytes;
658 }
659 } else if (CalleeMO.isGlobal()) {
660 const GlobalValue *GValue = CalleeMO.getGlobal();
661 MCSymbol *MOSymbol = getSymbol(GValue);
662 const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, OutContext);
663
664 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP)
665 .addExpr(SymVar));
666 EncodedBytes += 2;
667 }
668
669 // Each instruction is 4 bytes.
670 EncodedBytes *= 4;
671
672 // Emit padding.
673 unsigned NumBytes = Opers.getNumPatchBytes();
674 if (NumBytes < EncodedBytes)
676 "Patchpoint can't request size less than the length of a call.");
677
678 assert((NumBytes - EncodedBytes) % 4 == 0 &&
679 "Invalid number of NOP bytes requested!");
680 for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
681 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
682}
683
684/// This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX. We
685/// will create the csect and use the qual-name symbol instead of creating just
686/// the external symbol.
687static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc) {
688 StringRef SymName;
689 switch (MIOpc) {
690 default:
691 SymName = ".__tls_get_addr";
692 break;
693 case PPC::GETtlsTpointer32AIX:
694 SymName = ".__get_tpointer";
695 break;
696 case PPC::GETtlsMOD32AIX:
697 case PPC::GETtlsMOD64AIX:
698 SymName = ".__tls_get_mod";
699 break;
700 }
701 return Ctx
702 .getXCOFFSection(SymName, SectionKind::getText(),
704 ->getQualNameSymbol();
705}
706
707void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) {
708 assert(Subtarget->isAIXABI() &&
709 "Only expecting to emit calls to get the thread pointer on AIX!");
710
711 MCSymbol *TlsCall = createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode());
712 const MCExpr *TlsRef = MCSymbolRefExpr::create(TlsCall, OutContext);
713 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));
714}
715
716/// Given a GETtls[ld]ADDR[32] instruction, print a call to __tls_get_addr to
717/// the current output stream.
718void PPCAsmPrinter::emitTlsCall(const MachineInstr *MI,
721 unsigned Opcode = PPC::BL8_NOP_TLS;
722
723 assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI");
724 if (MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
725 MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) {
727 Opcode = PPC::BL8_NOTOC_TLS;
728 }
729 const Module *M = MF->getFunction().getParent();
730
731 assert(MI->getOperand(0).isReg() &&
732 ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||
733 (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&
734 "GETtls[ld]ADDR[32] must define GPR3");
735 assert(MI->getOperand(1).isReg() &&
736 ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||
737 (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&
738 "GETtls[ld]ADDR[32] must read GPR3");
739
740 if (Subtarget->isAIXABI()) {
741 // For TLSGD, the variable offset should already be in R4 and the region
742 // handle should already be in R3. We generate an absolute branch to
743 // .__tls_get_addr. For TLSLD, the module handle should already be in R3.
744 // We generate an absolute branch to .__tls_get_mod.
745 Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;
746 (void)VarOffsetReg;
747 assert((MI->getOpcode() == PPC::GETtlsMOD32AIX ||
748 MI->getOpcode() == PPC::GETtlsMOD64AIX ||
749 (MI->getOperand(2).isReg() &&
750 MI->getOperand(2).getReg() == VarOffsetReg)) &&
751 "GETtls[ld]ADDR[32] must read GPR4");
752 EmitAIXTlsCallHelper(MI);
753 return;
754 }
755
756 MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol("__tls_get_addr");
757
758 if (Subtarget->is32BitELFABI() && isPositionIndependent())
760
761 const MCExpr *TlsRef = MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext);
762
763 // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI.
764 if (Kind == PPC::S_PLT && Subtarget->isSecurePlt() &&
765 M->getPICLevel() == PICLevel::BigPIC)
767 TlsRef, MCConstantExpr::create(32768, OutContext), OutContext);
768 const MachineOperand &MO = MI->getOperand(2);
769 const GlobalValue *GValue = MO.getGlobal();
770 MCSymbol *MOSymbol = getSymbol(GValue);
771 const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
772 EmitToStreamer(*OutStreamer,
773 MCInstBuilder(Subtarget->isPPC64() ? Opcode
774 : (unsigned)PPC::BL_TLS)
775 .addExpr(TlsRef)
776 .addExpr(SymVar));
777}
778
779/// Map a machine operand for a TOC pseudo-machine instruction to its
780/// corresponding MCSymbol.
782 AsmPrinter &AP) {
783 switch (MO.getType()) {
785 return AP.getSymbol(MO.getGlobal());
787 return AP.GetCPISymbol(MO.getIndex());
789 return AP.GetJTISymbol(MO.getIndex());
792 default:
793 llvm_unreachable("Unexpected operand type to get symbol.");
794 }
795}
796
797static PPCAsmPrinter::TOCEntryType
802 return PPCAsmPrinter::TOCType_GlobalExternal;
803
804 return PPCAsmPrinter::TOCType_GlobalInternal;
805}
806
807static PPCAsmPrinter::TOCEntryType
809 // Use the target flags to determine if this MO is Thread Local.
810 // If we don't do this it comes out as Global.
812 return PPCAsmPrinter::TOCType_ThreadLocal;
813
814 switch (MO.getType()) {
816 const GlobalValue *GlobalV = MO.getGlobal();
817 return getTOCEntryTypeForLinkage(GlobalV->getLinkage());
818 }
820 return PPCAsmPrinter::TOCType_ConstantPool;
822 return PPCAsmPrinter::TOCType_JumpTable;
824 return PPCAsmPrinter::TOCType_BlockAddress;
825 default:
826 llvm_unreachable("Unexpected operand type to get TOC type.");
827 }
828}
829
830const MCExpr *PPCAsmPrinter::symbolWithSpecifier(const MCSymbol *S,
832 return MCSymbolRefExpr::create(S, Spec, OutContext);
833}
834
835/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
836/// the current output stream.
837///
838void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
839 PPC_MC::verifyInstructionPredicates(MI->getOpcode(),
840 getSubtargetInfo().getFeatureBits());
841
842 MCInst TmpInst;
843 const bool IsPPC64 = Subtarget->isPPC64();
844 const bool IsAIX = Subtarget->isAIXABI();
845 const bool HasAIXSmallLocalTLS = Subtarget->hasAIXSmallLocalExecTLS() ||
846 Subtarget->hasAIXSmallLocalDynamicTLS();
847 const Module *M = MF->getFunction().getParent();
848 PICLevel::Level PL = M->getPICLevel();
849
850#ifndef NDEBUG
851 // Validate that SPE and FPU are mutually exclusive in codegen
852 if (!MI->isInlineAsm()) {
853 for (const MachineOperand &MO: MI->operands()) {
854 if (MO.isReg()) {
855 Register Reg = MO.getReg();
856 if (Subtarget->hasSPE()) {
857 if (PPC::F4RCRegClass.contains(Reg) ||
858 PPC::F8RCRegClass.contains(Reg) ||
859 PPC::VFRCRegClass.contains(Reg) ||
860 PPC::VRRCRegClass.contains(Reg) ||
861 PPC::VSFRCRegClass.contains(Reg) ||
862 PPC::VSSRCRegClass.contains(Reg)
863 )
864 llvm_unreachable("SPE targets cannot have FPRegs!");
865 } else {
866 if (PPC::SPERCRegClass.contains(Reg))
867 llvm_unreachable("SPE register found in FPU-targeted code!");
868 }
869 }
870 }
871 }
872#endif
873
874 auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,
875 ptrdiff_t OriginalOffset) {
876 // Apply an offset to the TOC-based expression such that the adjusted
877 // notional offset from the TOC base (to be encoded into the instruction's D
878 // or DS field) is the signed 16-bit truncation of the original notional
879 // offset from the TOC base.
880 // This is consistent with the treatment used both by XL C/C++ and
881 // by AIX ld -r.
882 ptrdiff_t Adjustment =
883 OriginalOffset - llvm::SignExtend32<16>(OriginalOffset);
885 Expr, MCConstantExpr::create(-Adjustment, OutContext), OutContext);
886 };
887
888 auto getTOCEntryLoadingExprForXCOFF =
889 [IsPPC64, getTOCRelocAdjustedExprForXCOFF,
890 this](const MCSymbol *MOSymbol, const MCExpr *Expr,
891 PPCMCExpr::Specifier VK = PPC::S_None) -> const MCExpr * {
892 const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
893 const auto TOCEntryIter = TOC.find({MOSymbol, VK});
894 assert(TOCEntryIter != TOC.end() &&
895 "Could not find the TOC entry for this symbol.");
896 const ptrdiff_t EntryDistanceFromTOCBase =
897 (TOCEntryIter - TOC.begin()) * EntryByteSize;
898 constexpr int16_t PositiveTOCRange = INT16_MAX;
899
900 if (EntryDistanceFromTOCBase > PositiveTOCRange)
901 return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);
902
903 return Expr;
904 };
905 auto getSpecifier = [&](const MachineOperand &MO) {
906 // For TLS initial-exec and local-exec accesses on AIX, we have one TOC
907 // entry for the symbol (with the variable offset), which is differentiated
908 // by MO_TPREL_FLAG.
909 unsigned Flag = MO.getTargetFlags();
910 if (Flag == PPCII::MO_TPREL_FLAG ||
913 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");
914 TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());
915 if (Model == TLSModel::LocalExec)
916 return PPC::S_AIX_TLSLE;
917 if (Model == TLSModel::InitialExec)
918 return PPC::S_AIX_TLSIE;
919 // On AIX, TLS model opt may have turned local-dynamic accesses into
920 // initial-exec accesses.
921 PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
922 if (Model == TLSModel::LocalDynamic &&
923 FuncInfo->isAIXFuncUseTLSIEForLD()) {
925 dbgs() << "Current function uses IE access for default LD vars.\n");
926 return PPC::S_AIX_TLSIE;
927 }
928 llvm_unreachable("Only expecting local-exec or initial-exec accesses!");
929 }
930 // For GD TLS access on AIX, we have two TOC entries for the symbol (one for
931 // the variable offset and the other for the region handle). They are
932 // differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG.
933 if (Flag == PPCII::MO_TLSGDM_FLAG)
934 return PPC::S_AIX_TLSGDM;
936 return PPC::S_AIX_TLSGD;
937 // For local-dynamic TLS access on AIX, we have one TOC entry for the symbol
938 // (the variable offset) and one shared TOC entry for the module handle.
939 // They are differentiated by MO_TLSLD_FLAG and MO_TLSLDM_FLAG.
940 if (Flag == PPCII::MO_TLSLD_FLAG && IsAIX)
941 return PPC::S_AIX_TLSLD;
942 if (Flag == PPCII::MO_TLSLDM_FLAG && IsAIX)
943 return PPC::S_AIX_TLSML;
944 return PPC::S_None;
945 };
946
947 // Lower multi-instruction pseudo operations.
948 switch (MI->getOpcode()) {
949 default: break;
950 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
951 assert(!Subtarget->isAIXABI() &&
952 "AIX does not support patchable function entry!");
953 const Function &F = MF->getFunction();
954 unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry");
955 if (!Num)
956 return;
957 emitNops(Num);
958 return;
959 }
960 case TargetOpcode::DBG_VALUE:
961 llvm_unreachable("Should be handled target independently");
962 case TargetOpcode::STACKMAP:
963 return LowerSTACKMAP(SM, *MI);
964 case TargetOpcode::PATCHPOINT:
965 return LowerPATCHPOINT(SM, *MI);
966
967 case PPC::MoveGOTtoLR: {
968 // Transform %lr = MoveGOTtoLR
969 // Into this: bl _GLOBAL_OFFSET_TABLE_@local-4
970 // _GLOBAL_OFFSET_TABLE_@local-4 (instruction preceding
971 // _GLOBAL_OFFSET_TABLE_) has exactly one instruction:
972 // blrl
973 // This will return the pointer to _GLOBAL_OFFSET_TABLE_@local
974 MCSymbol *GOTSymbol =
975 OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
976 const MCExpr *OffsExpr = MCBinaryExpr::createSub(
977 MCSymbolRefExpr::create(GOTSymbol, PPC::S_LOCAL, OutContext),
978 MCConstantExpr::create(4, OutContext), OutContext);
979
980 // Emit the 'bl'.
981 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));
982 return;
983 }
984 case PPC::MovePCtoLR:
985 case PPC::MovePCtoLR8: {
986 // Transform %lr = MovePCtoLR
987 // Into this, where the label is the PIC base:
988 // bl L1$pb
989 // L1$pb:
990 MCSymbol *PICBase = MF->getPICBaseSymbol();
991
992 // Emit 'bcl 20,31,.+4' so the link stack is not corrupted.
993 EmitToStreamer(*OutStreamer,
994 MCInstBuilder(PPC::BCLalways)
995 // FIXME: We would like an efficient form for this, so we
996 // don't have to do a lot of extra uniquing.
997 .addExpr(MCSymbolRefExpr::create(PICBase, OutContext)));
998
999 // Emit the label.
1000 OutStreamer->emitLabel(PICBase);
1001 return;
1002 }
1003 case PPC::UpdateGBR: {
1004 // Transform %rd = UpdateGBR(%rt, %ri)
1005 // Into: lwz %rt, .L0$poff - .L0$pb(%ri)
1006 // add %rd, %rt, %ri
1007 // or into (if secure plt mode is on):
1008 // addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha
1009 // addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l
1010 // Get the offset from the GOT Base Register to the GOT
1011 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1012 if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
1013 MCRegister PICR = TmpInst.getOperand(0).getReg();
1014 MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
1015 M->getPICLevel() == PICLevel::SmallPIC ? "_GLOBAL_OFFSET_TABLE_"
1016 : ".LTOC");
1017 const MCExpr *PB =
1018 MCSymbolRefExpr::create(MF->getPICBaseSymbol(), OutContext);
1019
1020 const MCExpr *DeltaExpr = MCBinaryExpr::createSub(
1021 MCSymbolRefExpr::create(BaseSymbol, OutContext), PB, OutContext);
1022
1023 const MCExpr *DeltaHi =
1024 MCSpecifierExpr::create(DeltaExpr, PPC::S_HA, OutContext);
1025 EmitToStreamer(
1026 *OutStreamer,
1027 MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));
1028
1029 const MCExpr *DeltaLo =
1030 MCSpecifierExpr::create(DeltaExpr, PPC::S_LO, OutContext);
1031 EmitToStreamer(
1032 *OutStreamer,
1033 MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));
1034 return;
1035 } else {
1036 MCSymbol *PICOffset =
1037 MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(*MF);
1038 TmpInst.setOpcode(PPC::LWZ);
1039 const MCExpr *Exp = MCSymbolRefExpr::create(PICOffset, OutContext);
1040 const MCExpr *PB =
1041 MCSymbolRefExpr::create(MF->getPICBaseSymbol(),
1042 OutContext);
1043 const MCOperand TR = TmpInst.getOperand(1);
1044 const MCOperand PICR = TmpInst.getOperand(0);
1045
1046 // Step 1: lwz %rt, .L$poff - .L$pb(%ri)
1047 TmpInst.getOperand(1) =
1049 TmpInst.getOperand(0) = TR;
1050 TmpInst.getOperand(2) = PICR;
1051 EmitToStreamer(*OutStreamer, TmpInst);
1052
1053 TmpInst.setOpcode(PPC::ADD4);
1054 TmpInst.getOperand(0) = PICR;
1055 TmpInst.getOperand(1) = TR;
1056 TmpInst.getOperand(2) = PICR;
1057 EmitToStreamer(*OutStreamer, TmpInst);
1058 return;
1059 }
1060 }
1061 case PPC::LWZtoc: {
1062 // Transform %rN = LWZtoc @op1, %r2
1063 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1064
1065 // Change the opcode to LWZ.
1066 TmpInst.setOpcode(PPC::LWZ);
1067
1068 const MachineOperand &MO = MI->getOperand(1);
1069 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1070 "Invalid operand for LWZtoc.");
1071
1072 // Map the operand to its corresponding MCSymbol.
1073 const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1074
1075 // Create a reference to the GOT entry for the symbol. The GOT entry will be
1076 // synthesized later.
1077 if (PL == PICLevel::SmallPIC && !IsAIX) {
1078 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, PPC::S_GOT);
1079 TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
1080 EmitToStreamer(*OutStreamer, TmpInst);
1081 return;
1082 }
1083
1085
1086 // Otherwise, use the TOC. 'TOCEntry' is a label used to reference the
1087 // storage allocated in the TOC which contains the address of
1088 // 'MOSymbol'. Said TOC entry will be synthesized later.
1089 MCSymbol *TOCEntry =
1090 lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
1091 const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, OutContext);
1092
1093 // AIX uses the label directly as the lwz displacement operand for
1094 // references into the toc section. The displacement value will be generated
1095 // relative to the toc-base.
1096 if (IsAIX) {
1097 assert(
1098 getCodeModel(*Subtarget, TM, MO) == CodeModel::Small &&
1099 "This pseudo should only be selected for 32-bit small code model.");
1100 Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
1101 TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
1102
1103 // Print MO for better readability
1104 if (isVerbose())
1105 OutStreamer->getCommentOS() << MO << '\n';
1106 EmitToStreamer(*OutStreamer, TmpInst);
1107 return;
1108 }
1109
1110 // Create an explicit subtract expression between the local symbol and
1111 // '.LTOC' to manifest the toc-relative offset.
1112 const MCExpr *PB = MCSymbolRefExpr::create(
1113 OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext);
1114 Exp = MCBinaryExpr::createSub(Exp, PB, OutContext);
1115 TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
1116 EmitToStreamer(*OutStreamer, TmpInst);
1117 return;
1118 }
1119 case PPC::ADDItoc:
1120 case PPC::ADDItoc8: {
1121 assert(IsAIX && TM.getCodeModel() == CodeModel::Small &&
1122 "PseudoOp only valid for small code model AIX");
1123
1124 // Transform %rN = ADDItoc/8 %r2, @op1.
1125 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1126
1127 // Change the opcode to load address.
1128 TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
1129
1130 const MachineOperand &MO = MI->getOperand(2);
1131 assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");
1132
1133 // Map the operand to its corresponding MCSymbol.
1134 const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1135
1136 const MCExpr *Exp = MCSymbolRefExpr::create(MOSymbol, OutContext);
1137
1138 TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
1139 EmitToStreamer(*OutStreamer, TmpInst);
1140 return;
1141 }
1142 case PPC::LDtocJTI:
1143 case PPC::LDtocCPT:
1144 case PPC::LDtocBA:
1145 case PPC::LDtoc: {
1146 // Transform %x3 = LDtoc @min1, %x2
1147 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1148
1149 // Change the opcode to LD.
1150 TmpInst.setOpcode(PPC::LD);
1151
1152 const MachineOperand &MO = MI->getOperand(1);
1153 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1154 "Invalid operand!");
1155
1156 // Map the operand to its corresponding MCSymbol.
1157 const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1158
1160
1161 // Map the machine operand to its corresponding MCSymbol, then map the
1162 // global address operand to be a reference to the TOC entry we will
1163 // synthesize later.
1164 MCSymbol *TOCEntry =
1165 lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
1166
1167 PPCMCExpr::Specifier VKExpr = IsAIX ? PPC::S_None : PPC::S_TOC;
1168 const MCExpr *Exp = symbolWithSpecifier(TOCEntry, VKExpr);
1169 TmpInst.getOperand(1) = MCOperand::createExpr(
1170 IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);
1171
1172 // Print MO for better readability
1173 if (isVerbose() && IsAIX)
1174 OutStreamer->getCommentOS() << MO << '\n';
1175 EmitToStreamer(*OutStreamer, TmpInst);
1176 return;
1177 }
1178 case PPC::ADDIStocHA: {
1179 const MachineOperand &MO = MI->getOperand(2);
1180
1181 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1182 "Invalid operand for ADDIStocHA.");
1183 assert((IsAIX && !IsPPC64 &&
1184 getCodeModel(*Subtarget, TM, MO) == CodeModel::Large) &&
1185 "This pseudo should only be selected for 32-bit large code model on"
1186 " AIX.");
1187
1188 // Transform %rd = ADDIStocHA %rA, @sym(%r2)
1189 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1190
1191 // Change the opcode to ADDIS.
1192 TmpInst.setOpcode(PPC::ADDIS);
1193
1194 // Map the machine operand to its corresponding MCSymbol.
1195 MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1196
1198
1199 // Map the global address operand to be a reference to the TOC entry we
1200 // will synthesize later. 'TOCEntry' is a label used to reference the
1201 // storage allocated in the TOC which contains the address of 'MOSymbol'.
1202 // If the symbol does not have the toc-data attribute, then we create the
1203 // TOC entry on AIX. If the toc-data attribute is used, the TOC entry
1204 // contains the data rather than the address of the MOSymbol.
1205 if (![](const MachineOperand &MO) {
1206 if (!MO.isGlobal())
1207 return false;
1208
1209 const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal());
1210 if (!GV)
1211 return false;
1212 return GV->hasAttribute("toc-data");
1213 }(MO)) {
1214 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
1215 }
1216
1217 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, PPC::S_U);
1218 TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
1219 EmitToStreamer(*OutStreamer, TmpInst);
1220 return;
1221 }
1222 case PPC::LWZtocL: {
1223 const MachineOperand &MO = MI->getOperand(1);
1224
1225 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1226 "Invalid operand for LWZtocL.");
1227 assert(IsAIX && !IsPPC64 &&
1228 getCodeModel(*Subtarget, TM, MO) == CodeModel::Large &&
1229 "This pseudo should only be selected for 32-bit large code model on"
1230 " AIX.");
1231
1232 // Transform %rd = LWZtocL @sym, %rs.
1233 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1234
1235 // Change the opcode to lwz.
1236 TmpInst.setOpcode(PPC::LWZ);
1237
1238 // Map the machine operand to its corresponding MCSymbol.
1239 MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1240
1242
1243 // Always use TOC on AIX. Map the global address operand to be a reference
1244 // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
1245 // reference the storage allocated in the TOC which contains the address of
1246 // 'MOSymbol'.
1247 MCSymbol *TOCEntry =
1248 lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
1249 const MCExpr *Exp = symbolWithSpecifier(TOCEntry, PPC::S_L);
1250 TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
1251 EmitToStreamer(*OutStreamer, TmpInst);
1252 return;
1253 }
1254 case PPC::ADDIStocHA8: {
1255 // Transform %xd = ADDIStocHA8 %x2, @sym
1256 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1257
1258 // Change the opcode to ADDIS8. If the global address is the address of
1259 // an external symbol, is a jump table address, is a block address, or is a
1260 // constant pool index with large code model enabled, then generate a TOC
1261 // entry and reference that. Otherwise, reference the symbol directly.
1262 TmpInst.setOpcode(PPC::ADDIS8);
1263
1264 const MachineOperand &MO = MI->getOperand(2);
1265 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
1266 "Invalid operand for ADDIStocHA8!");
1267
1268 const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1269
1271
1272 const bool GlobalToc =
1273 MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());
1274
1275 const CodeModel::Model CM =
1276 IsAIX ? getCodeModel(*Subtarget, TM, MO) : TM.getCodeModel();
1277
1278 if (GlobalToc || MO.isJTI() || MO.isBlockAddress() ||
1279 (MO.isCPI() && CM == CodeModel::Large))
1280 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
1281
1282 VK = IsAIX ? PPC::S_U : PPC::S_TOC_HA;
1283
1284 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, VK);
1285
1286 if (!MO.isJTI() && MO.getOffset())
1289 OutContext),
1290 OutContext);
1291
1292 TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
1293 EmitToStreamer(*OutStreamer, TmpInst);
1294 return;
1295 }
1296 case PPC::LDtocL: {
1297 // Transform %xd = LDtocL @sym, %xs
1298 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1299
1300 // Change the opcode to LD. If the global address is the address of
1301 // an external symbol, is a jump table address, is a block address, or is
1302 // a constant pool index with large code model enabled, then generate a
1303 // TOC entry and reference that. Otherwise, reference the symbol directly.
1304 TmpInst.setOpcode(PPC::LD);
1305
1306 const MachineOperand &MO = MI->getOperand(1);
1307 assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||
1308 MO.isBlockAddress()) &&
1309 "Invalid operand for LDtocL!");
1310
1312 (!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&
1313 "LDtocL used on symbol that could be accessed directly is "
1314 "invalid. Must match ADDIStocHA8."));
1315
1316 const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1317
1319 CodeModel::Model CM =
1320 IsAIX ? getCodeModel(*Subtarget, TM, MO) : TM.getCodeModel();
1321 if (!MO.isCPI() || CM == CodeModel::Large)
1322 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
1323
1324 VK = IsAIX ? PPC::S_L : PPC::S_TOC_LO;
1325 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, VK);
1326 TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
1327 EmitToStreamer(*OutStreamer, TmpInst);
1328 return;
1329 }
1330 case PPC::ADDItocL:
1331 case PPC::ADDItocL8: {
1332 // Transform %xd = ADDItocL %xs, @sym
1333 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1334
1335 unsigned Op = MI->getOpcode();
1336
1337 // Change the opcode to load address for toc-data.
1338 // ADDItocL is only used for 32-bit toc-data on AIX and will always use LA.
1339 TmpInst.setOpcode(Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8)
1340 : PPC::LA);
1341
1342 const MachineOperand &MO = MI->getOperand(2);
1343 assert((Op == PPC::ADDItocL8)
1344 ? (MO.isGlobal() || MO.isCPI())
1345 : MO.isGlobal() && "Invalid operand for ADDItocL8.");
1346 assert(!(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&
1347 "Interposable definitions must use indirect accesses.");
1348
1349 // Map the operand to its corresponding MCSymbol.
1350 const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
1351
1352 const MCExpr *Exp = MCSymbolRefExpr::create(
1353 MOSymbol, IsAIX ? PPC::S_L : PPC::S_TOC_LO, OutContext);
1354
1355 TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
1356 EmitToStreamer(*OutStreamer, TmpInst);
1357 return;
1358 }
1359 case PPC::ADDISgotTprelHA: {
1360 // Transform: %xd = ADDISgotTprelHA %x2, @sym
1361 // Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha
1362 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1363 const MachineOperand &MO = MI->getOperand(2);
1364 const GlobalValue *GValue = MO.getGlobal();
1365 MCSymbol *MOSymbol = getSymbol(GValue);
1366 const MCExpr *SymGotTprel =
1367 symbolWithSpecifier(MOSymbol, PPC::S_GOT_TPREL_HA);
1368 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1369 .addReg(MI->getOperand(0).getReg())
1370 .addReg(MI->getOperand(1).getReg())
1371 .addExpr(SymGotTprel));
1372 return;
1373 }
1374 case PPC::LDgotTprelL:
1375 case PPC::LDgotTprelL32: {
1376 // Transform %xd = LDgotTprelL @sym, %xs
1377 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1378
1379 // Change the opcode to LD.
1380 TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);
1381 const MachineOperand &MO = MI->getOperand(1);
1382 const GlobalValue *GValue = MO.getGlobal();
1383 MCSymbol *MOSymbol = getSymbol(GValue);
1384 const MCExpr *Exp = symbolWithSpecifier(
1385 MOSymbol, IsPPC64 ? PPC::S_GOT_TPREL_LO : PPC::S_GOT_TPREL);
1386 TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
1387 EmitToStreamer(*OutStreamer, TmpInst);
1388 return;
1389 }
1390
1391 case PPC::PPC32PICGOT: {
1392 MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
1393 MCSymbol *GOTRef = OutContext.createTempSymbol();
1394 MCSymbol *NextInstr = OutContext.createTempSymbol();
1395
1396 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL)
1397 // FIXME: We would like an efficient form for this, so we don't have to do
1398 // a lot of extra uniquing.
1399 .addExpr(MCSymbolRefExpr::create(NextInstr, OutContext)));
1400 const MCExpr *OffsExpr =
1401 MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol, OutContext),
1402 MCSymbolRefExpr::create(GOTRef, OutContext),
1403 OutContext);
1404 OutStreamer->emitLabel(GOTRef);
1405 OutStreamer->emitValue(OffsExpr, 4);
1406 OutStreamer->emitLabel(NextInstr);
1407 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)
1408 .addReg(MI->getOperand(0).getReg()));
1409 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)
1410 .addReg(MI->getOperand(1).getReg())
1411 .addImm(0)
1412 .addReg(MI->getOperand(0).getReg()));
1413 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4)
1414 .addReg(MI->getOperand(0).getReg())
1415 .addReg(MI->getOperand(1).getReg())
1416 .addReg(MI->getOperand(0).getReg()));
1417 return;
1418 }
1419 case PPC::PPC32GOT: {
1420 MCSymbol *GOTSymbol =
1421 OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
1422 const MCExpr *SymGotTlsL =
1423 MCSpecifierExpr::create(GOTSymbol, PPC::S_LO, OutContext);
1424 const MCExpr *SymGotTlsHA =
1425 MCSpecifierExpr::create(GOTSymbol, PPC::S_HA, OutContext);
1426 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI)
1427 .addReg(MI->getOperand(0).getReg())
1428 .addExpr(SymGotTlsL));
1429 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
1430 .addReg(MI->getOperand(0).getReg())
1431 .addReg(MI->getOperand(0).getReg())
1432 .addExpr(SymGotTlsHA));
1433 return;
1434 }
1435 case PPC::ADDIStlsgdHA: {
1436 // Transform: %xd = ADDIStlsgdHA %x2, @sym
1437 // Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha
1438 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1439 const MachineOperand &MO = MI->getOperand(2);
1440 const GlobalValue *GValue = MO.getGlobal();
1441 MCSymbol *MOSymbol = getSymbol(GValue);
1442 const MCExpr *SymGotTlsGD =
1443 symbolWithSpecifier(MOSymbol, PPC::S_GOT_TLSGD_HA);
1444 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1445 .addReg(MI->getOperand(0).getReg())
1446 .addReg(MI->getOperand(1).getReg())
1447 .addExpr(SymGotTlsGD));
1448 return;
1449 }
1450 case PPC::ADDItlsgdL:
1451 // Transform: %xd = ADDItlsgdL %xs, @sym
1452 // Into: %xd = ADDI8 %xs, sym@got@tlsgd@l
1453 case PPC::ADDItlsgdL32: {
1454 // Transform: %rd = ADDItlsgdL32 %rs, @sym
1455 // Into: %rd = ADDI %rs, sym@got@tlsgd
1456 const MachineOperand &MO = MI->getOperand(2);
1457 const GlobalValue *GValue = MO.getGlobal();
1458 MCSymbol *MOSymbol = getSymbol(GValue);
1459 const MCExpr *SymGotTlsGD = symbolWithSpecifier(
1460 MOSymbol, IsPPC64 ? PPC::S_GOT_TLSGD_LO : PPC::S_GOT_TLSGD);
1461 EmitToStreamer(*OutStreamer,
1462 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1463 .addReg(MI->getOperand(0).getReg())
1464 .addReg(MI->getOperand(1).getReg())
1465 .addExpr(SymGotTlsGD));
1466 return;
1467 }
1468 case PPC::GETtlsMOD32AIX:
1469 case PPC::GETtlsMOD64AIX:
1470 // Transform: %r3 = GETtlsMODNNAIX %r3 (for NN == 32/64).
1471 // Into: BLA .__tls_get_mod()
1472 // Input parameter is a module handle (_$TLSML[TC]@ml) for all variables.
1473 case PPC::GETtlsADDR:
1474 // Transform: %x3 = GETtlsADDR %x3, @sym
1475 // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsgd)
1476 case PPC::GETtlsADDRPCREL:
1477 case PPC::GETtlsADDR32AIX:
1478 case PPC::GETtlsADDR64AIX:
1479 // Transform: %r3 = GETtlsADDRNNAIX %r3, %r4 (for NN == 32/64).
1480 // Into: BLA .__tls_get_addr()
1481 // Unlike on Linux, there is no symbol or relocation needed for this call.
1482 case PPC::GETtlsADDR32: {
1483 // Transform: %r3 = GETtlsADDR32 %r3, @sym
1484 // Into: BL_TLS __tls_get_addr(sym at tlsgd)@PLT
1485 emitTlsCall(MI, PPC::S_TLSGD);
1486 return;
1487 }
1488 case PPC::GETtlsTpointer32AIX: {
1489 // Transform: %r3 = GETtlsTpointer32AIX
1490 // Into: BLA .__get_tpointer()
1491 EmitAIXTlsCallHelper(MI);
1492 return;
1493 }
1494 case PPC::ADDIStlsldHA: {
1495 // Transform: %xd = ADDIStlsldHA %x2, @sym
1496 // Into: %xd = ADDIS8 %x2, sym@got@tlsld@ha
1497 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1498 const MachineOperand &MO = MI->getOperand(2);
1499 const GlobalValue *GValue = MO.getGlobal();
1500 MCSymbol *MOSymbol = getSymbol(GValue);
1501 const MCExpr *SymGotTlsLD =
1502 symbolWithSpecifier(MOSymbol, PPC::S_GOT_TLSLD_HA);
1503 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1504 .addReg(MI->getOperand(0).getReg())
1505 .addReg(MI->getOperand(1).getReg())
1506 .addExpr(SymGotTlsLD));
1507 return;
1508 }
1509 case PPC::ADDItlsldL:
1510 // Transform: %xd = ADDItlsldL %xs, @sym
1511 // Into: %xd = ADDI8 %xs, sym@got@tlsld@l
1512 case PPC::ADDItlsldL32: {
1513 // Transform: %rd = ADDItlsldL32 %rs, @sym
1514 // Into: %rd = ADDI %rs, sym@got@tlsld
1515 const MachineOperand &MO = MI->getOperand(2);
1516 const GlobalValue *GValue = MO.getGlobal();
1517 MCSymbol *MOSymbol = getSymbol(GValue);
1518 const MCExpr *SymGotTlsLD = symbolWithSpecifier(
1519 MOSymbol, IsPPC64 ? PPC::S_GOT_TLSLD_LO : PPC::S_GOT_TLSLD);
1520 EmitToStreamer(*OutStreamer,
1521 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1522 .addReg(MI->getOperand(0).getReg())
1523 .addReg(MI->getOperand(1).getReg())
1524 .addExpr(SymGotTlsLD));
1525 return;
1526 }
1527 case PPC::GETtlsldADDR:
1528 // Transform: %x3 = GETtlsldADDR %x3, @sym
1529 // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsld)
1530 case PPC::GETtlsldADDRPCREL:
1531 case PPC::GETtlsldADDR32: {
1532 // Transform: %r3 = GETtlsldADDR32 %r3, @sym
1533 // Into: BL_TLS __tls_get_addr(sym at tlsld)@PLT
1534 emitTlsCall(MI, PPC::S_TLSLD);
1535 return;
1536 }
1537 case PPC::ADDISdtprelHA:
1538 // Transform: %xd = ADDISdtprelHA %xs, @sym
1539 // Into: %xd = ADDIS8 %xs, sym@dtprel@ha
1540 case PPC::ADDISdtprelHA32: {
1541 // Transform: %rd = ADDISdtprelHA32 %rs, @sym
1542 // Into: %rd = ADDIS %rs, sym@dtprel@ha
1543 const MachineOperand &MO = MI->getOperand(2);
1544 const GlobalValue *GValue = MO.getGlobal();
1545 MCSymbol *MOSymbol = getSymbol(GValue);
1546 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL_HA);
1547 EmitToStreamer(
1548 *OutStreamer,
1549 MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)
1550 .addReg(MI->getOperand(0).getReg())
1551 .addReg(MI->getOperand(1).getReg())
1552 .addExpr(SymDtprel));
1553 return;
1554 }
1555 case PPC::PADDIdtprel: {
1556 // Transform: %rd = PADDIdtprel %rs, @sym
1557 // Into: %rd = PADDI8 %rs, sym@dtprel
1558 const MachineOperand &MO = MI->getOperand(2);
1559 const GlobalValue *GValue = MO.getGlobal();
1560 MCSymbol *MOSymbol = getSymbol(GValue);
1561 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL);
1562 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8)
1563 .addReg(MI->getOperand(0).getReg())
1564 .addReg(MI->getOperand(1).getReg())
1565 .addExpr(SymDtprel));
1566 return;
1567 }
1568
1569 case PPC::ADDIdtprelL:
1570 // Transform: %xd = ADDIdtprelL %xs, @sym
1571 // Into: %xd = ADDI8 %xs, sym@dtprel@l
1572 case PPC::ADDIdtprelL32: {
1573 // Transform: %rd = ADDIdtprelL32 %rs, @sym
1574 // Into: %rd = ADDI %rs, sym@dtprel@l
1575 const MachineOperand &MO = MI->getOperand(2);
1576 const GlobalValue *GValue = MO.getGlobal();
1577 MCSymbol *MOSymbol = getSymbol(GValue);
1578 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL_LO);
1579 EmitToStreamer(*OutStreamer,
1580 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1581 .addReg(MI->getOperand(0).getReg())
1582 .addReg(MI->getOperand(1).getReg())
1583 .addExpr(SymDtprel));
1584 return;
1585 }
1586 case PPC::MFOCRF:
1587 case PPC::MFOCRF8:
1588 if (!Subtarget->hasMFOCRF()) {
1589 // Transform: %r3 = MFOCRF %cr7
1590 // Into: %r3 = MFCR ;; cr7
1591 unsigned NewOpcode =
1592 MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;
1593 OutStreamer->AddComment(PPCInstPrinter::
1594 getRegisterName(MI->getOperand(1).getReg()));
1595 EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)
1596 .addReg(MI->getOperand(0).getReg()));
1597 return;
1598 }
1599 break;
1600 case PPC::MTOCRF:
1601 case PPC::MTOCRF8:
1602 if (!Subtarget->hasMFOCRF()) {
1603 // Transform: %cr7 = MTOCRF %r3
1604 // Into: MTCRF mask, %r3 ;; cr7
1605 unsigned NewOpcode =
1606 MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
1607 unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
1608 ->getEncodingValue(MI->getOperand(0).getReg());
1609 OutStreamer->AddComment(PPCInstPrinter::
1610 getRegisterName(MI->getOperand(0).getReg()));
1611 EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)
1612 .addImm(Mask)
1613 .addReg(MI->getOperand(1).getReg()));
1614 return;
1615 }
1616 break;
1617 case PPC::LD:
1618 case PPC::STD:
1619 case PPC::LWA_32:
1620 case PPC::LWA: {
1621 // Verify alignment is legal, so we don't create relocations
1622 // that can't be supported.
1623 unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;
1624 // For non-TOC-based local-exec TLS accesses with non-zero offsets, the
1625 // machine operand (which is a TargetGlobalTLSAddress) is expected to be
1626 // the same operand for both loads and stores.
1627 for (const MachineOperand &TempMO : MI->operands()) {
1628 if (((TempMO.getTargetFlags() == PPCII::MO_TPREL_FLAG ||
1629 TempMO.getTargetFlags() == PPCII::MO_TLSLD_FLAG)) &&
1630 TempMO.getOperandNo() == 1)
1631 OpNum = 1;
1632 }
1633 const MachineOperand &MO = MI->getOperand(OpNum);
1634 if (MO.isGlobal()) {
1635 const DataLayout &DL = MO.getGlobal()->getDataLayout();
1636 if (MO.getGlobal()->getPointerAlignment(DL) < 4)
1637 llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");
1638 }
1639 // As these load/stores share common code with the following load/stores,
1640 // fall through to the subsequent cases in order to either process the
1641 // non-TOC-based local-exec sequence or to process the instruction normally.
1642 [[fallthrough]];
1643 }
1644 case PPC::LBZ:
1645 case PPC::LBZ8:
1646 case PPC::LHA:
1647 case PPC::LHA8:
1648 case PPC::LHZ:
1649 case PPC::LHZ8:
1650 case PPC::LWZ:
1651 case PPC::LWZ8:
1652 case PPC::STB:
1653 case PPC::STB8:
1654 case PPC::STH:
1655 case PPC::STH8:
1656 case PPC::STW:
1657 case PPC::STW8:
1658 case PPC::LFS:
1659 case PPC::STFS:
1660 case PPC::LFD:
1661 case PPC::STFD:
1662 case PPC::ADDI8: {
1663 // A faster non-TOC-based local-[exec|dynamic] sequence is represented by
1664 // `addi` or a load/store instruction (that directly loads or stores off of
1665 // the thread pointer) with an immediate operand having the
1666 // [MO_TPREL_FLAG|MO_TLSLD_FLAG]. Such instructions do not otherwise arise.
1667 if (!HasAIXSmallLocalTLS)
1668 break;
1669 bool IsMIADDI8 = MI->getOpcode() == PPC::ADDI8;
1670 unsigned OpNum = IsMIADDI8 ? 2 : 1;
1671 const MachineOperand &MO = MI->getOperand(OpNum);
1672 unsigned Flag = MO.getTargetFlags();
1673 if (Flag == PPCII::MO_TPREL_FLAG ||
1676 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1677
1678 const MCExpr *Expr = getAdjustedFasterLocalExpr(MO, MO.getOffset());
1679 if (Expr)
1680 TmpInst.getOperand(OpNum) = MCOperand::createExpr(Expr);
1681
1682 // Change the opcode to load address if the original opcode is an `addi`.
1683 if (IsMIADDI8)
1684 TmpInst.setOpcode(PPC::LA8);
1685
1686 EmitToStreamer(*OutStreamer, TmpInst);
1687 return;
1688 }
1689 // Now process the instruction normally.
1690 break;
1691 }
1692 case PPC::PseudoEIEIO: {
1693 EmitToStreamer(
1694 *OutStreamer,
1695 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1696 EmitToStreamer(
1697 *OutStreamer,
1698 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1699 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));
1700 return;
1701 }
1702 }
1703
1704 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
1705 EmitToStreamer(*OutStreamer, TmpInst);
1706}
1707
1708// For non-TOC-based local-[exec|dynamic] variables that have a non-zero offset,
1709// we need to create a new MCExpr that adds the non-zero offset to the address
1710// of the local-[exec|dynamic] variable that will be used in either an addi,
1711// load or store. However, the final displacement for these instructions must be
1712// between [-32768, 32768), so if the TLS address + its non-zero offset is
1713// greater than 32KB, a new MCExpr is produced to accommodate this situation.
1714const MCExpr *
1715PPCAsmPrinter::getAdjustedFasterLocalExpr(const MachineOperand &MO,
1716 int64_t Offset) {
1717 // Non-zero offsets (for loads, stores or `addi`) require additional handling.
1718 // When the offset is zero, there is no need to create an adjusted MCExpr.
1719 if (!Offset)
1720 return nullptr;
1721
1722 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");
1723 const GlobalValue *GValue = MO.getGlobal();
1724 TLSModel::Model Model = TM.getTLSModel(GValue);
1725 assert((Model == TLSModel::LocalExec || Model == TLSModel::LocalDynamic) &&
1726 "Only local-[exec|dynamic] accesses are handled!");
1727
1728 bool IsGlobalADeclaration = GValue->isDeclarationForLinker();
1729 // Find the GlobalVariable that corresponds to the particular TLS variable
1730 // in the TLS variable-to-address mapping. All TLS variables should exist
1731 // within this map, with the exception of TLS variables marked as extern.
1732 const auto TLSVarsMapEntryIter = TLSVarsToAddressMapping.find(GValue);
1733 if (TLSVarsMapEntryIter == TLSVarsToAddressMapping.end())
1734 assert(IsGlobalADeclaration &&
1735 "Only expecting to find extern TLS variables not present in the TLS "
1736 "variable-to-address map!");
1737
1738 unsigned TLSVarAddress =
1739 IsGlobalADeclaration ? 0 : TLSVarsMapEntryIter->second;
1740 ptrdiff_t FinalAddress = (TLSVarAddress + Offset);
1741 // If the address of the TLS variable + the offset is less than 32KB,
1742 // or if the TLS variable is extern, we simply produce an MCExpr to add the
1743 // non-zero offset to the TLS variable address.
1744 // For when TLS variables are extern, this is safe to do because we can
1745 // assume that the address of extern TLS variables are zero.
1746 const MCExpr *Expr = MCSymbolRefExpr::create(
1747 getSymbol(GValue),
1749 OutContext);
1751 Expr, MCConstantExpr::create(Offset, OutContext), OutContext);
1752 if (FinalAddress >= 32768) {
1753 // Handle the written offset for cases where:
1754 // TLS variable address + Offset > 32KB.
1755
1756 // The assembly that is printed will look like:
1757 // TLSVar@le + Offset - Delta
1758 // where Delta is a multiple of 64KB: ((FinalAddress + 32768) & ~0xFFFF).
1759 ptrdiff_t Delta = ((FinalAddress + 32768) & ~0xFFFF);
1760 // Check that the total instruction displacement fits within [-32768,32768).
1761 [[maybe_unused]] ptrdiff_t InstDisp = TLSVarAddress + Offset - Delta;
1762 assert(
1763 ((InstDisp < 32768) && (InstDisp >= -32768)) &&
1764 "Expecting the instruction displacement for local-[exec|dynamic] TLS "
1765 "variables to be between [-32768, 32768)!");
1767 Expr, MCConstantExpr::create(-Delta, OutContext), OutContext);
1768 }
1769
1770 return Expr;
1771}
1772
1773void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) {
1774 // Emit long double format into GNU attribute
1775 MDString *LongDoubleType =
1776 cast_or_null<MDString>(M.getModuleFlag("long-double-type"));
1777 if (!LongDoubleType)
1778 return;
1779
1780 // TODO: Support emitting soft-fp and hard double/single attributes.
1781 switch (*parseLongDoubleFormat(LongDoubleType->getString())) {
1782 case LongDoubleFormat::PPCDoubleDouble:
1783 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1784 Val_GNU_Power_ABI_HardFloat_DP |
1785 Val_GNU_Power_ABI_LDBL_IBM128);
1786 break;
1787 case LongDoubleFormat::IEEEquad:
1788 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1789 Val_GNU_Power_ABI_HardFloat_DP |
1790 Val_GNU_Power_ABI_LDBL_IEEE128);
1791 break;
1792 case LongDoubleFormat::IEEEdouble:
1793 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1794 Val_GNU_Power_ABI_HardFloat_DP |
1795 Val_GNU_Power_ABI_LDBL_64);
1796 break;
1797 default:
1798 break;
1799 }
1800}
1801
1802void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
1803 if (!Subtarget->isPPC64())
1804 return PPCAsmPrinter::emitInstruction(MI);
1805
1806 switch (MI->getOpcode()) {
1807 default:
1808 break;
1809 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1810 // .begin:
1811 // b .end # lis 0, FuncId[16..32]
1812 // nop # li 0, FuncId[0..15]
1813 // std 0, -8(1)
1814 // mflr 0
1815 // bl __xray_FunctionEntry
1816 // mtlr 0
1817 // .end:
1818 //
1819 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1820 // of instructions change.
1821 // XRAY is only supported on PPC Linux little endian.
1822 const Function &F = MF->getFunction();
1823 unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry");
1824
1825 if (!MAI.isLittleEndian() || Num)
1826 break;
1827 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1828 MCSymbol *EndOfSled = OutContext.createTempSymbol();
1829 OutStreamer->emitLabel(BeginOfSled);
1830 EmitToStreamer(*OutStreamer,
1831 MCInstBuilder(PPC::B).addExpr(
1832 MCSymbolRefExpr::create(EndOfSled, OutContext)));
1833 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1834 EmitToStreamer(
1835 *OutStreamer,
1836 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1837 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1838 EmitToStreamer(*OutStreamer,
1839 MCInstBuilder(PPC::BL8_NOP)
1840 .addExpr(MCSymbolRefExpr::create(
1841 OutContext.getOrCreateSymbol("__xray_FunctionEntry"),
1842 OutContext)));
1843 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1844 OutStreamer->emitLabel(EndOfSled);
1845 recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER, 2);
1846 break;
1847 }
1848 case TargetOpcode::PATCHABLE_RET: {
1849 unsigned RetOpcode = MI->getOperand(0).getImm();
1850 MCInst RetInst;
1851 RetInst.setOpcode(RetOpcode);
1852 for (const auto &MO : llvm::drop_begin(MI->operands())) {
1853 MCOperand MCOp;
1854 if (LowerPPCMachineOperandToMCOperand(MI->getOpcode(), MO, MCOp, *this))
1855 RetInst.addOperand(MCOp);
1856 }
1857
1858 bool IsConditional;
1859 if (RetOpcode == PPC::BCCLR) {
1860 IsConditional = true;
1861 } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
1862 RetOpcode == PPC::TCRETURNai8) {
1863 break;
1864 } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
1865 IsConditional = false;
1866 } else {
1867 EmitToStreamer(*OutStreamer, RetInst);
1868 return;
1869 }
1870
1871 MCSymbol *FallthroughLabel;
1872 if (IsConditional) {
1873 // Before:
1874 // bgtlr cr0
1875 //
1876 // After:
1877 // ble cr0, .end
1878 // .p2align 3
1879 // .begin:
1880 // blr # lis 0, FuncId[16..32]
1881 // nop # li 0, FuncId[0..15]
1882 // std 0, -8(1)
1883 // mflr 0
1884 // bl __xray_FunctionExit
1885 // mtlr 0
1886 // blr
1887 // .end:
1888 //
1889 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1890 // of instructions change.
1891 FallthroughLabel = OutContext.createTempSymbol();
1892 EmitToStreamer(
1893 *OutStreamer,
1894 MCInstBuilder(PPC::BCC)
1895 .addImm(PPC::InvertPredicate(
1896 static_cast<PPC::Predicate>(MI->getOperand(1).getImm())))
1897 .addReg(MI->getOperand(2).getReg())
1898 .addExpr(MCSymbolRefExpr::create(FallthroughLabel, OutContext)));
1899 RetInst = MCInst();
1900 RetInst.setOpcode(PPC::BLR8);
1901 }
1902 // .p2align 3
1903 // .begin:
1904 // b(lr)? # lis 0, FuncId[16..32]
1905 // nop # li 0, FuncId[0..15]
1906 // std 0, -8(1)
1907 // mflr 0
1908 // bl __xray_FunctionExit
1909 // mtlr 0
1910 // b(lr)?
1911 //
1912 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1913 // of instructions change.
1914 OutStreamer->emitCodeAlignment(Align(8), getSubtargetInfo());
1915 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1916 OutStreamer->emitLabel(BeginOfSled);
1917 EmitToStreamer(*OutStreamer, RetInst);
1918 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1919 EmitToStreamer(
1920 *OutStreamer,
1921 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1922 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1923 EmitToStreamer(*OutStreamer,
1924 MCInstBuilder(PPC::BL8_NOP)
1925 .addExpr(MCSymbolRefExpr::create(
1926 OutContext.getOrCreateSymbol("__xray_FunctionExit"),
1927 OutContext)));
1928 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1929 EmitToStreamer(*OutStreamer, RetInst);
1930 if (IsConditional)
1931 OutStreamer->emitLabel(FallthroughLabel);
1932 recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT, 2);
1933 return;
1934 }
1935 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1936 llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
1937 case TargetOpcode::PATCHABLE_TAIL_CALL:
1938 // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a
1939 // normal function exit from a tail exit.
1940 llvm_unreachable("Tail call is handled in the normal case. See comments "
1941 "around this assert.");
1942 }
1943 return PPCAsmPrinter::emitInstruction(MI);
1944}
1945
1946void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {
1947 if (PPCTargetMachine::computeABI(M.getTargetTriple(),
1948 TM.getTargetABIName(M)) == PPC_ABI_ELFv2) {
1949 PPCTargetStreamer *TS =
1950 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
1951 TS->emitAbiVersion(2);
1952 }
1953
1954 if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||
1955 !isPositionIndependent())
1957
1958 if (M.getPICLevel() == PICLevel::SmallPIC)
1960
1961 OutStreamer->switchSection(OutContext.getELFSection(
1963
1964 MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC"));
1965 MCSymbol *CurrentPos = OutContext.createTempSymbol();
1966
1967 OutStreamer->emitLabel(CurrentPos);
1968
1969 // The GOT pointer points to the middle of the GOT, in order to reference the
1970 // entire 64kB range. 0x8000 is the midpoint.
1971 const MCExpr *tocExpr =
1972 MCBinaryExpr::createAdd(MCSymbolRefExpr::create(CurrentPos, OutContext),
1973 MCConstantExpr::create(0x8000, OutContext),
1974 OutContext);
1975
1976 OutStreamer->emitAssignment(TOCSym, tocExpr);
1977
1978 OutStreamer->switchSection(getObjFileLowering().getTextSection());
1979}
1980
1981void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {
1982 // linux/ppc32 - Normal entry label.
1983 if (!Subtarget->isPPC64() &&
1984 (!isPositionIndependent() ||
1985 MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC))
1987
1988 if (!Subtarget->isPPC64()) {
1989 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
1990 if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {
1991 MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(*MF);
1992 MCSymbol *PICBase = MF->getPICBaseSymbol();
1993 OutStreamer->emitLabel(RelocSymbol);
1994
1995 const MCExpr *OffsExpr =
1997 MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")),
1998 OutContext),
1999 MCSymbolRefExpr::create(PICBase, OutContext),
2000 OutContext);
2001 OutStreamer->emitValue(OffsExpr, 4);
2002 OutStreamer->emitLabel(CurrentFnSym);
2003 return;
2004 } else
2006 }
2007
2008 // ELFv2 ABI - Normal entry label.
2009 if (Subtarget->isELFv2ABI()) {
2010 // In the Large code model, we allow arbitrary displacements between
2011 // the text section and its associated TOC section. We place the
2012 // full 8-byte offset to the TOC in memory immediately preceding
2013 // the function global entry point.
2014 if (TM.getCodeModel() == CodeModel::Large
2015 && !MF->getRegInfo().use_empty(PPC::X2)) {
2016 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
2017
2018 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));
2019 MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(*MF);
2020 const MCExpr *TOCDeltaExpr =
2021 MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),
2022 MCSymbolRefExpr::create(GlobalEPSymbol,
2023 OutContext),
2024 OutContext);
2025
2026 OutStreamer->emitLabel(PPCFI->getTOCOffsetSymbol(*MF));
2027 OutStreamer->emitValue(TOCDeltaExpr, 8);
2028 }
2030 }
2031
2032 // Emit an official procedure descriptor.
2033 MCSectionSubPair Current = OutStreamer->getCurrentSection();
2034 MCSectionELF *Section = OutStreamer->getContext().getELFSection(
2036 OutStreamer->switchSection(Section);
2037 OutStreamer->emitLabel(CurrentFnSym);
2038 OutStreamer->emitValueToAlignment(Align(8));
2039 MCSymbol *Symbol1 = CurrentFnSymForSize;
2040 // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function
2041 // entry point.
2042 OutStreamer->emitValue(MCSymbolRefExpr::create(Symbol1, OutContext),
2043 8 /*size*/);
2044 MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC."));
2045 // Generates a R_PPC64_TOC relocation for TOC base insertion.
2046 OutStreamer->emitValue(
2047 MCSymbolRefExpr::create(Symbol2, PPC::S_TOCBASE, OutContext), 8 /*size*/);
2048 // Emit a null environment pointer.
2049 OutStreamer->emitIntValue(0, 8 /* size */);
2050 OutStreamer->switchSection(Current.first, Current.second);
2051}
2052
2053void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {
2054 const DataLayout &DL = getDataLayout();
2055
2056 bool isPPC64 = DL.getPointerSizeInBits() == 64;
2057
2058 PPCTargetStreamer *TS =
2059 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2060
2061 // If we are using any values provided by Glibc at fixed addresses,
2062 // we need to ensure that the Glibc used at link time actually provides
2063 // those values. All versions of Glibc that do will define the symbol
2064 // named "__parse_hwcap_and_convert_at_platform".
2065 if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess())
2066 OutStreamer->emitSymbolValue(
2067 GetExternalSymbolSymbol("__parse_hwcap_and_convert_at_platform"),
2068 MAI.getCodePointerSize());
2069 emitGNUAttributes(M);
2070
2071 if (!TOC.empty()) {
2072 const char *Name = isPPC64 ? ".toc" : ".got2";
2073 MCSectionELF *Section = OutContext.getELFSection(
2075 OutStreamer->switchSection(Section);
2076 if (!isPPC64)
2077 OutStreamer->emitValueToAlignment(Align(4));
2078
2079 for (const auto &TOCMapPair : TOC) {
2080 const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;
2081 MCSymbol *const TOCEntryLabel = TOCMapPair.second;
2082
2083 OutStreamer->emitLabel(TOCEntryLabel);
2084 if (isPPC64)
2085 TS->emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);
2086 else
2087 OutStreamer->emitSymbolValue(TOCEntryTarget, 4);
2088 }
2089 }
2090
2091 PPCAsmPrinter::emitEndOfAsmFile(M);
2092}
2093
2094/// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2.
2095void PPCLinuxAsmPrinter::emitFunctionBodyStart() {
2096 // In the ELFv2 ABI, in functions that use the TOC register, we need to
2097 // provide two entry points. The ABI guarantees that when calling the
2098 // local entry point, r2 is set up by the caller to contain the TOC base
2099 // for this function, and when calling the global entry point, r12 is set
2100 // up by the caller to hold the address of the global entry point. We
2101 // thus emit a prefix sequence along the following lines:
2102 //
2103 // func:
2104 // .Lfunc_gepNN:
2105 // # global entry point
2106 // addis r2,r12,(.TOC.-.Lfunc_gepNN)@ha
2107 // addi r2,r2,(.TOC.-.Lfunc_gepNN)@l
2108 // .Lfunc_lepNN:
2109 // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN
2110 // # local entry point, followed by function body
2111 //
2112 // For the Large code model, we create
2113 //
2114 // .Lfunc_tocNN:
2115 // .quad .TOC.-.Lfunc_gepNN # done by EmitFunctionEntryLabel
2116 // func:
2117 // .Lfunc_gepNN:
2118 // # global entry point
2119 // ld r2,.Lfunc_tocNN-.Lfunc_gepNN(r12)
2120 // add r2,r2,r12
2121 // .Lfunc_lepNN:
2122 // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN
2123 // # local entry point, followed by function body
2124 //
2125 // This ensures we have r2 set up correctly while executing the function
2126 // body, no matter which entry point is called.
2127 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
2128 const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||
2129 !MF->getRegInfo().use_empty(PPC::R2);
2130 const bool PCrelGEPRequired = Subtarget->isUsingPCRelativeCalls() &&
2131 UsesX2OrR2 && PPCFI->usesTOCBasePtr();
2132 const bool NonPCrelGEPRequired = !Subtarget->isUsingPCRelativeCalls() &&
2133 Subtarget->isELFv2ABI() && UsesX2OrR2;
2134
2135 // Only do all that if the function uses R2 as the TOC pointer
2136 // in the first place. We don't need the global entry point if the
2137 // function uses R2 as an allocatable register.
2138 if (NonPCrelGEPRequired || PCrelGEPRequired) {
2139 // Note: The logic here must be synchronized with the code in the
2140 // branch-selection pass which sets the offset of the first block in the
2141 // function. This matters because it affects the alignment.
2142 MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(*MF);
2143 OutStreamer->emitLabel(GlobalEntryLabel);
2144 const MCSymbolRefExpr *GlobalEntryLabelExp =
2145 MCSymbolRefExpr::create(GlobalEntryLabel, OutContext);
2146
2147 if (TM.getCodeModel() != CodeModel::Large) {
2148 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));
2149 const MCExpr *TOCDeltaExpr =
2150 MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),
2151 GlobalEntryLabelExp, OutContext);
2152
2153 const MCExpr *TOCDeltaHi =
2154 MCSpecifierExpr::create(TOCDeltaExpr, PPC::S_HA, OutContext);
2155 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
2156 .addReg(PPC::X2)
2157 .addReg(PPC::X12)
2158 .addExpr(TOCDeltaHi));
2159
2160 const MCExpr *TOCDeltaLo =
2161 MCSpecifierExpr::create(TOCDeltaExpr, PPC::S_LO, OutContext);
2162 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
2163 .addReg(PPC::X2)
2164 .addReg(PPC::X2)
2165 .addExpr(TOCDeltaLo));
2166 } else {
2167 MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(*MF);
2168 const MCExpr *TOCOffsetDeltaExpr =
2169 MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCOffset, OutContext),
2170 GlobalEntryLabelExp, OutContext);
2171
2172 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
2173 .addReg(PPC::X2)
2174 .addExpr(TOCOffsetDeltaExpr)
2175 .addReg(PPC::X12));
2176 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)
2177 .addReg(PPC::X2)
2178 .addReg(PPC::X2)
2179 .addReg(PPC::X12));
2180 }
2181
2182 MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(*MF);
2183 OutStreamer->emitLabel(LocalEntryLabel);
2184 const MCSymbolRefExpr *LocalEntryLabelExp =
2185 MCSymbolRefExpr::create(LocalEntryLabel, OutContext);
2186 const MCExpr *LocalOffsetExp =
2187 MCBinaryExpr::createSub(LocalEntryLabelExp,
2188 GlobalEntryLabelExp, OutContext);
2189
2190 PPCTargetStreamer *TS =
2191 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2192 TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),
2193 LocalOffsetExp);
2194 } else if (Subtarget->isUsingPCRelativeCalls()) {
2195 // When generating the entry point for a function we have a few scenarios
2196 // based on whether or not that function uses R2 and whether or not that
2197 // function makes calls (or is a leaf function).
2198 // 1) A leaf function that does not use R2 (or treats it as callee-saved
2199 // and preserves it). In this case st_other=0 and both
2200 // the local and global entry points for the function are the same.
2201 // No special entry point code is required.
2202 // 2) A function uses the TOC pointer R2. This function may or may not have
2203 // calls. In this case st_other=[2,6] and the global and local entry
2204 // points are different. Code to correctly setup the TOC pointer in R2
2205 // is put between the global and local entry points. This case is
2206 // covered by the if statatement above.
2207 // 3) A function does not use the TOC pointer R2 but does have calls.
2208 // In this case st_other=1 since we do not know whether or not any
2209 // of the callees clobber R2. This case is dealt with in this else if
2210 // block. Tail calls are considered calls and the st_other should also
2211 // be set to 1 in that case as well.
2212 // 4) The function does not use the TOC pointer but R2 is used inside
2213 // the function. In this case st_other=1 once again.
2214 // 5) This function uses inline asm. We mark R2 as reserved if the function
2215 // has inline asm as we have to assume that it may be used.
2216 if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||
2217 MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) {
2218 PPCTargetStreamer *TS =
2219 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2220 TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),
2221 MCConstantExpr::create(1, OutContext));
2222 }
2223 }
2224}
2225
2226/// EmitFunctionBodyEnd - Print the traceback table before the .size
2227/// directive.
2228///
2229void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
2230 // Only the 64-bit target requires a traceback table. For now,
2231 // we only emit the word of zeroes that GDB requires to find
2232 // the end of the function, and zeroes for the eight-byte
2233 // mandatory fields.
2234 // FIXME: We should fill in the eight-byte mandatory fields as described in
2235 // the PPC64 ELF ABI (this is a low-priority item because GDB does not
2236 // currently make use of these fields).
2237 if (Subtarget->isPPC64()) {
2238 OutStreamer->emitIntValue(0, 4/*size*/);
2239 OutStreamer->emitIntValue(0, 8/*size*/);
2240 }
2241}
2242
2243char PPCLinuxAsmPrinter::ID = 0;
2244
2245INITIALIZE_PASS(PPCLinuxAsmPrinter, "ppc-linux-asm-printer",
2246 "Linux PPC Assembly Printer", false, false)
2247
2248void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
2249 MCSymbol *GVSym) const {
2250 MCSymbolAttr LinkageAttr = MCSA_Invalid;
2251 switch (GV->getLinkage()) {
2252 case GlobalValue::ExternalLinkage:
2253 LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;
2254 break;
2255 case GlobalValue::LinkOnceAnyLinkage:
2256 case GlobalValue::LinkOnceODRLinkage:
2257 case GlobalValue::WeakAnyLinkage:
2258 case GlobalValue::WeakODRLinkage:
2259 case GlobalValue::ExternalWeakLinkage:
2260 LinkageAttr = MCSA_Weak;
2261 break;
2262 case GlobalValue::AvailableExternallyLinkage:
2263 LinkageAttr = MCSA_Extern;
2264 break;
2265 case GlobalValue::PrivateLinkage:
2266 return;
2267 case GlobalValue::InternalLinkage:
2268 assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&
2269 "InternalLinkage should not have other visibility setting.");
2270 LinkageAttr = MCSA_LGlobal;
2271 break;
2272 case GlobalValue::AppendingLinkage:
2273 llvm_unreachable("Should never emit this");
2274 case GlobalValue::CommonLinkage:
2275 llvm_unreachable("CommonLinkage of XCOFF should not come to this path");
2276 }
2277
2278 assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");
2279
2280 MCSymbolAttr VisibilityAttr = MCSA_Invalid;
2281 if (!TM.getIgnoreXCOFFVisibility()) {
2282 if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())
2283 report_fatal_error(
2284 "Cannot not be both dllexport and non-default visibility");
2285 switch (GV->getVisibility()) {
2286
2287 // TODO: "internal" Visibility needs to go here.
2288 case GlobalValue::DefaultVisibility:
2289 if (GV->hasDLLExportStorageClass())
2290 VisibilityAttr = MAI.getExportedVisibilityAttr();
2291 break;
2292 case GlobalValue::HiddenVisibility:
2293 VisibilityAttr = MAI.getHiddenVisibilityAttr();
2294 break;
2295 case GlobalValue::ProtectedVisibility:
2296 VisibilityAttr = MAI.getProtectedVisibilityAttr();
2297 break;
2298 }
2299 }
2300
2301 // Do not emit the _$TLSML symbol.
2302 if (GV->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&
2303 GV->hasName() && GV->getName() == "_$TLSML")
2304 return;
2305
2306 OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
2307 VisibilityAttr);
2308}
2309
2310void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
2311 // Setup CurrentFnDescSym and its containing csect.
2312 auto *FnDescSec = static_cast<MCSectionXCOFF *>(
2313 getObjFileLowering().getSectionForFunctionDescriptor(&MF.getFunction(),
2314 TM));
2315 FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4));
2316
2317 CurrentFnDescSym = FnDescSec->getQualNameSymbol();
2318
2320}
2321
2322uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {
2323 // Calculate the number of VRs be saved.
2324 // Vector registers 20 through 31 are marked as reserved and cannot be used
2325 // in the default ABI.
2326 const PPCSubtarget &Subtarget = MF->getSubtarget<PPCSubtarget>();
2327 if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&
2328 Subtarget.isAIXExtendedAltivecABI()) {
2329 const MachineRegisterInfo &MRI = MF->getRegInfo();
2330 for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg)
2332 // Number of VRs saved.
2333 return PPC::V31 - Reg + 1;
2334 }
2335 return 0;
2336}
2337
2338void PPCAIXAsmPrinter::emitFunctionBodyEnd() {
2339
2340 if (!TM.getXCOFFTracebackTable())
2341 return;
2342
2343 emitTracebackTable();
2344
2345 // If ShouldEmitEHBlock returns true, then the eh info table
2346 // will be emitted via `AIXException::endFunction`. Otherwise, we
2347 // need to emit a dumy eh info table when VRs are saved. We could not
2348 // consolidate these two places into one because there is no easy way
2349 // to access register information in `AIXException` class.
2351 (getNumberOfVRSaved() > 0)) {
2352 // Emit dummy EH Info Table.
2353 OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());
2354 MCSymbol *EHInfoLabel =
2356 OutStreamer->emitLabel(EHInfoLabel);
2357
2358 // Version number.
2359 OutStreamer->emitInt32(0);
2360
2361 const DataLayout &DL = MMI->getModule()->getDataLayout();
2362 const unsigned PointerSize = DL.getPointerSize();
2363 // Add necessary paddings in 64 bit mode.
2364 OutStreamer->emitValueToAlignment(Align(PointerSize));
2365
2366 OutStreamer->emitIntValue(0, PointerSize);
2367 OutStreamer->emitIntValue(0, PointerSize);
2368 OutStreamer->switchSection(MF->getSection());
2369 }
2370}
2371
2372void PPCAIXAsmPrinter::emitTracebackTable() {
2373
2374 // Create a symbol for the end of function.
2375 MCSymbol *FuncEnd = createTempSymbol(MF->getName());
2376 OutStreamer->emitLabel(FuncEnd);
2377
2378 OutStreamer->AddComment("Traceback table begin");
2379 // Begin with a fullword of zero.
2380 OutStreamer->emitIntValueInHexWithPadding(0, 4 /*size*/);
2381
2382 SmallString<128> CommentString;
2383 raw_svector_ostream CommentOS(CommentString);
2384
2385 auto EmitComment = [&]() {
2386 OutStreamer->AddComment(CommentOS.str());
2387 CommentString.clear();
2388 };
2389
2390 auto EmitCommentAndValue = [&](uint64_t Value, int Size) {
2391 EmitComment();
2392 OutStreamer->emitIntValueInHexWithPadding(Value, Size);
2393 };
2394
2395 unsigned int Version = 0;
2396 CommentOS << "Version = " << Version;
2397 EmitCommentAndValue(Version, 1);
2398
2399 // There is a lack of information in the IR to assist with determining the
2400 // source language. AIX exception handling mechanism would only search for
2401 // personality routine and LSDA area when such language supports exception
2402 // handling. So to be conservatively correct and allow runtime to do its job,
2403 // we need to set it to C++ for now.
2404 TracebackTable::LanguageID LanguageIdentifier =
2406
2407 CommentOS << "Language = "
2408 << getNameForTracebackTableLanguageId(LanguageIdentifier);
2409 EmitCommentAndValue(LanguageIdentifier, 1);
2410
2411 // This is only populated for the third and fourth bytes.
2412 uint32_t FirstHalfOfMandatoryField = 0;
2413
2414 // Emit the 3rd byte of the mandatory field.
2415
2416 // We always set traceback offset bit to true.
2417 FirstHalfOfMandatoryField |= TracebackTable::HasTraceBackTableOffsetMask;
2418
2419 const PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
2420 const MachineRegisterInfo &MRI = MF->getRegInfo();
2421
2422 // Check the function uses floating-point processor instructions or not
2423 for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {
2424 if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
2425 FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask;
2426 break;
2427 }
2428 }
2429
2430#define GENBOOLCOMMENT(Prefix, V, Field) \
2431 CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \
2432 << #Field
2433
2434#define GENVALUECOMMENT(PrefixAndName, V, Field) \
2435 CommentOS << (PrefixAndName) << " = " \
2436 << static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >> \
2437 (TracebackTable::Field##Shift))
2438
2439 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsGlobalLinkage);
2440 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);
2441 EmitComment();
2442
2443 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasTraceBackTableOffset);
2444 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsInternalProcedure);
2445 EmitComment();
2446
2447 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasControlledStorage);
2448 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsTOCless);
2449 EmitComment();
2450
2451 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsFloatingPointPresent);
2452 EmitComment();
2453 GENBOOLCOMMENT("", FirstHalfOfMandatoryField,
2454 IsFloatingPointOperationLogOrAbortEnabled);
2455 EmitComment();
2456
2457 OutStreamer->emitIntValueInHexWithPadding(
2458 (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2459
2460 // Set the 4th byte of the mandatory field.
2461 FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask;
2462
2463 const PPCRegisterInfo *RegInfo = Subtarget->getRegisterInfo();
2464 Register FrameReg = RegInfo->getFrameRegister(*MF);
2465 if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))
2466 FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask;
2467
2468 const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();
2469 if (!MustSaveCRs.empty())
2470 FirstHalfOfMandatoryField |= TracebackTable::IsCRSavedMask;
2471
2472 if (FI->mustSaveLR())
2473 FirstHalfOfMandatoryField |= TracebackTable::IsLRSavedMask;
2474
2475 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsInterruptHandler);
2476 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);
2477 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsAllocaUsed);
2478 EmitComment();
2479 GENVALUECOMMENT("OnConditionDirective", FirstHalfOfMandatoryField,
2480 OnConditionDirective);
2481 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsCRSaved);
2482 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsLRSaved);
2483 EmitComment();
2484 OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),
2485 1);
2486
2487 // Set the 5th byte of mandatory field.
2488 uint32_t SecondHalfOfMandatoryField = 0;
2489
2490 SecondHalfOfMandatoryField |= MF->getFrameInfo().getStackSize()
2492 : 0;
2493
2494 uint32_t FPRSaved = 0;
2495 for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) {
2496 if (MRI.isPhysRegModified(Reg)) {
2497 FPRSaved = PPC::F31 - Reg + 1;
2498 break;
2499 }
2500 }
2501 SecondHalfOfMandatoryField |= (FPRSaved << TracebackTable::FPRSavedShift) &
2503 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, IsBackChainStored);
2504 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, IsFixup);
2505 GENVALUECOMMENT(", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);
2506 EmitComment();
2507 OutStreamer->emitIntValueInHexWithPadding(
2508 (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);
2509
2510 // Set the 6th byte of mandatory field.
2511
2512 // Check whether has Vector Instruction,We only treat instructions uses vector
2513 // register as vector instructions.
2514 bool HasVectorInst = false;
2515 for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)
2516 if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
2517 // Has VMX instruction.
2518 HasVectorInst = true;
2519 break;
2520 }
2521
2522 if (FI->hasVectorParms() || HasVectorInst)
2523 SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask;
2524
2525 uint16_t NumOfVRSaved = getNumberOfVRSaved();
2526 bool ShouldEmitEHBlock =
2528
2529 if (ShouldEmitEHBlock)
2530 SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask;
2531
2532 uint32_t GPRSaved = 0;
2533
2534 // X13 is reserved under 64-bit environment.
2535 unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;
2536 unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;
2537
2538 for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) {
2539 if (MRI.isPhysRegModified(Reg)) {
2540 GPRSaved = GPREnd - Reg + 1;
2541 break;
2542 }
2543 }
2544
2545 SecondHalfOfMandatoryField |= (GPRSaved << TracebackTable::GPRSavedShift) &
2547
2548 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, HasExtensionTable);
2549 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasVectorInfo);
2550 GENVALUECOMMENT(", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);
2551 EmitComment();
2552 OutStreamer->emitIntValueInHexWithPadding(
2553 (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);
2554
2555 // Set the 7th byte of mandatory field.
2556 uint32_t NumberOfFixedParms = FI->getFixedParmsNum();
2557 SecondHalfOfMandatoryField |=
2558 (NumberOfFixedParms << TracebackTable::NumberOfFixedParmsShift) &
2560 GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,
2561 NumberOfFixedParms);
2562 EmitComment();
2563 OutStreamer->emitIntValueInHexWithPadding(
2564 (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2565
2566 // Set the 8th byte of mandatory field.
2567
2568 // Always set parameter on stack.
2569 SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask;
2570
2571 uint32_t NumberOfFPParms = FI->getFloatingPointParmsNum();
2572 SecondHalfOfMandatoryField |=
2575
2576 GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,
2577 NumberOfFloatingPointParms);
2578 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasParmsOnStack);
2579 EmitComment();
2580 OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,
2581 1);
2582
2583 // Generate the optional fields of traceback table.
2584
2585 // Parameter type.
2586 if (NumberOfFixedParms || NumberOfFPParms) {
2587 uint32_t ParmsTypeValue = FI->getParmsType();
2588
2589 Expected<SmallString<32>> ParmsType =
2590 FI->hasVectorParms()
2592 ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,
2593 FI->getVectorParmsNum())
2594 : XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms,
2595 NumberOfFPParms);
2596
2597 assert(ParmsType && toString(ParmsType.takeError()).c_str());
2598 if (ParmsType) {
2599 CommentOS << "Parameter type = " << ParmsType.get();
2600 EmitComment();
2601 }
2602 OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,
2603 sizeof(ParmsTypeValue));
2604 }
2605 // Traceback table offset.
2606 OutStreamer->AddComment("Function size");
2607 if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) {
2608 MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(
2609 &(MF->getFunction()), TM);
2610 OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);
2611 }
2612
2613 // Since we unset the Int_Handler.
2614 if (FirstHalfOfMandatoryField & TracebackTable::IsInterruptHandlerMask)
2615 report_fatal_error("Hand_Mask not implement yet");
2616
2617 if (FirstHalfOfMandatoryField & TracebackTable::HasControlledStorageMask)
2618 report_fatal_error("Ctl_Info not implement yet");
2619
2620 if (FirstHalfOfMandatoryField & TracebackTable::IsFunctionNamePresentMask) {
2621 StringRef Name = MF->getName().substr(0, INT16_MAX);
2622 int16_t NameLength = Name.size();
2623 CommentOS << "Function name len = "
2624 << static_cast<unsigned int>(NameLength);
2625 EmitCommentAndValue(NameLength, 2);
2626 OutStreamer->AddComment("Function Name");
2627 OutStreamer->emitBytes(Name);
2628 }
2629
2630 if (FirstHalfOfMandatoryField & TracebackTable::IsAllocaUsedMask) {
2631 uint8_t AllocReg = XCOFF::AllocRegNo;
2632 OutStreamer->AddComment("AllocaUsed");
2633 OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg));
2634 }
2635
2636 if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) {
2637 uint16_t VRData = 0;
2638 if (NumOfVRSaved) {
2639 // Number of VRs saved.
2640 VRData |= (NumOfVRSaved << TracebackTable::NumberOfVRSavedShift) &
2642 // This bit is supposed to set only when the special register
2643 // VRSAVE is saved on stack.
2644 // However, IBM XL compiler sets the bit when any vector registers
2645 // are saved on the stack. We will follow XL's behavior on AIX
2646 // so that we don't get surprise behavior change for C code.
2648 }
2649
2650 // Set has_varargs.
2651 if (FI->getVarArgsFrameIndex())
2653
2654 // Vector parameters number.
2655 unsigned VectorParmsNum = FI->getVectorParmsNum();
2656 VRData |= (VectorParmsNum << TracebackTable::NumberOfVectorParmsShift) &
2658
2659 if (HasVectorInst)
2661
2662 GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved);
2663 GENBOOLCOMMENT(", ", VRData, IsVRSavedOnStack);
2664 GENBOOLCOMMENT(", ", VRData, HasVarArgs);
2665 EmitComment();
2666 OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);
2667
2668 GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms);
2669 GENBOOLCOMMENT(", ", VRData, HasVMXInstruction);
2670 EmitComment();
2671 OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);
2672
2673 uint32_t VecParmTypeValue = FI->getVecExtParmsType();
2674
2675 Expected<SmallString<32>> VecParmsType =
2676 XCOFF::parseVectorParmsType(VecParmTypeValue, VectorParmsNum);
2677 assert(VecParmsType && toString(VecParmsType.takeError()).c_str());
2678 if (VecParmsType) {
2679 CommentOS << "Vector Parameter type = " << VecParmsType.get();
2680 EmitComment();
2681 }
2682 OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,
2683 sizeof(VecParmTypeValue));
2684 // Padding 2 bytes.
2685 CommentOS << "Padding";
2686 EmitCommentAndValue(0, 2);
2687 }
2688
2689 uint8_t ExtensionTableFlag = 0;
2690 if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) {
2691 if (ShouldEmitEHBlock)
2692 ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;
2695 ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;
2696
2697 CommentOS << "ExtensionTableFlag = "
2698 << getExtendedTBTableFlagString(ExtensionTableFlag);
2699 EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag));
2700 }
2701
2702 if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {
2703 auto &Ctx = OutStreamer->getContext();
2704 MCSymbol *EHInfoSym =
2706 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock);
2707 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
2708 getObjFileLowering().getTOCBaseSection())
2709 ->getQualNameSymbol();
2710 const MCExpr *Exp =
2712 MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);
2713
2714 const DataLayout &DL = getDataLayout();
2715 OutStreamer->emitValueToAlignment(Align(4));
2716 OutStreamer->AddComment("EHInfo Table");
2717 OutStreamer->emitValue(Exp, DL.getPointerSize());
2718 }
2719#undef GENBOOLCOMMENT
2720#undef GENVALUECOMMENT
2721}
2722
2724 return GV->hasAppendingLinkage() &&
2726 // TODO: Linker could still eliminate the GV if we just skip
2727 // handling llvm.used array. Skipping them for now until we or the
2728 // AIX OS team come up with a good solution.
2729 .Case("llvm.used", true)
2730 // It's correct to just skip llvm.compiler.used array here.
2731 .Case("llvm.compiler.used", true)
2732 .Default(false);
2733}
2734
2736 return StringSwitch<bool>(GV->getName())
2737 .Cases({"llvm.global_ctors", "llvm.global_dtors"}, true)
2738 .Default(false);
2739}
2740
2741uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {
2742 if (auto *GA = dyn_cast<GlobalAlias>(C))
2743 return getAliasOffset(GA->getAliasee());
2744 if (auto *CE = dyn_cast<ConstantExpr>(C)) {
2745 const MCExpr *LowC = lowerConstant(CE);
2746 const MCBinaryExpr *CBE = dyn_cast<MCBinaryExpr>(LowC);
2747 if (!CBE)
2748 return 0;
2749 if (CBE->getOpcode() != MCBinaryExpr::Add)
2750 report_fatal_error("Only adding an offset is supported now.");
2751 auto *RHS = dyn_cast<MCConstantExpr>(CBE->getRHS());
2752 if (!RHS)
2753 report_fatal_error("Unable to get the offset of alias.");
2754 return RHS->getValue();
2755 }
2756 return 0;
2757}
2758
2759static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV) {
2760 // TODO: These asserts should be updated as more support for the toc data
2761 // transformation is added (struct support, etc.).
2762 assert(
2763 PointerSize >= GV->getAlign().valueOrOne().value() &&
2764 "GlobalVariables with an alignment requirement stricter than TOC entry "
2765 "size not supported by the toc data transformation.");
2766
2767 Type *GVType = GV->getValueType();
2768 assert(GVType->isSized() && "A GlobalVariable's size must be known to be "
2769 "supported by the toc data transformation.");
2770 if (GV->getDataLayout().getTypeSizeInBits(GVType) >
2771 PointerSize * 8)
2773 "A GlobalVariable with size larger than a TOC entry is not currently "
2774 "supported by the toc data transformation.");
2775 if (GV->hasPrivateLinkage())
2776 report_fatal_error("A GlobalVariable with private linkage is not "
2777 "currently supported by the toc data transformation.");
2778}
2779
2780void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
2781 // Special LLVM global arrays have been handled at the initialization.
2783 return;
2784
2785 // Ignore non-emitted data.
2786 if (GV->getSection() == "llvm.metadata")
2787 return;
2788
2789 // If the Global Variable has the toc-data attribute, it needs to be emitted
2790 // when we emit the .toc section.
2791 if (GV->hasAttribute("toc-data")) {
2792 unsigned PointerSize = GV->getDataLayout().getPointerSize();
2793 tocDataChecks(PointerSize, GV);
2794 TOCDataGlobalVars.push_back(GV);
2795 return;
2796 }
2797
2798 emitGlobalVariableHelper(GV);
2799}
2800
2801void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
2802 assert(!GV->getName().starts_with("llvm.") &&
2803 "Unhandled intrinsic global variable.");
2804
2805 if (GV->hasComdat())
2806 report_fatal_error("COMDAT not yet supported by AIX.");
2807
2808 auto *GVSym = static_cast<MCSymbolXCOFF *>(getSymbol(GV));
2809
2810 if (GV->isDeclarationForLinker()) {
2811 emitLinkage(GV, GVSym);
2812 return;
2813 }
2814
2815 SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
2816 if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly() &&
2817 !GVKind.isThreadLocal()) // Checks for both ThreadData and ThreadBSS.
2818 report_fatal_error("Encountered a global variable kind that is "
2819 "not supported yet.");
2820
2821 // Print GV in verbose mode
2822 if (isVerbose()) {
2823 if (GV->hasInitializer()) {
2824 GV->printAsOperand(OutStreamer->getCommentOS(),
2825 /*PrintType=*/false, GV->getParent());
2826 OutStreamer->getCommentOS() << '\n';
2827 }
2828 }
2829
2830 auto *Csect = static_cast<MCSectionXCOFF *>(
2831 getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
2832
2833 // Switch to the containing csect.
2834 OutStreamer->switchSection(Csect);
2835
2836 if (GV->hasMetadata(LLVMContext::MD_implicit_ref)) {
2837 emitRefMetadata(GV);
2838 }
2839
2840 const DataLayout &DL = GV->getDataLayout();
2841
2842 // Handle common and zero-initialized local symbols.
2843 if (GV->hasCommonLinkage() || GVKind.isBSSLocal() ||
2844 GVKind.isThreadBSSLocal()) {
2845 Align Alignment = GV->getAlign().value_or(DL.getPreferredAlign(GV));
2847 GVSym->setStorageClass(
2849
2850 if (GVKind.isBSSLocal() && Csect->getMappingClass() == XCOFF::XMC_TD) {
2851 OutStreamer->emitZeros(Size);
2852 } else if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal()) {
2853 assert(Csect->getMappingClass() != XCOFF::XMC_TD &&
2854 "BSS local toc-data already handled and TLS variables "
2855 "incompatible with XMC_TD");
2856 OutStreamer->emitXCOFFLocalCommonSymbol(
2857 OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,
2858 GVSym, Alignment);
2859 } else {
2860 OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
2861 }
2862 return;
2863 }
2864
2865 MCSymbol *EmittedInitSym = GVSym;
2866
2867 // Emit linkage for the global variable and its aliases.
2868 emitLinkage(GV, EmittedInitSym);
2869 for (const GlobalAlias *GA : GOAliasMap[GV])
2870 emitLinkage(GA, getSymbol(GA));
2871
2872 emitAlignment(getGVAlignment(GV, DL), GV);
2873
2874 // When -fdata-sections is enabled, every GlobalVariable will
2875 // be put into its own csect; therefore, label is not necessary here.
2876 if (!TM.getDataSections() || GV->hasSection()) {
2877 if (Csect->getMappingClass() != XCOFF::XMC_TD)
2878 OutStreamer->emitLabel(EmittedInitSym);
2879 }
2880
2881 // No alias to emit.
2882 if (!GOAliasMap[GV].size()) {
2883 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());
2884 return;
2885 }
2886
2887 // Aliases with the same offset should be aligned. Record the list of aliases
2888 // associated with the offset.
2889 AliasMapTy AliasList;
2890 for (const GlobalAlias *GA : GOAliasMap[GV])
2891 AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);
2892
2893 // Emit alias label and element value for global variable.
2894 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),
2895 &AliasList);
2896}
2897
2898void PPCAIXAsmPrinter::emitFunctionDescriptor() {
2899 const DataLayout &DL = getDataLayout();
2900 const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;
2901
2902 MCSectionSubPair Current = OutStreamer->getCurrentSection();
2903 // Emit function descriptor.
2904 OutStreamer->switchSection(
2905 static_cast<MCSymbolXCOFF *>(CurrentFnDescSym)->getRepresentedCsect());
2906
2907 // Emit aliasing label for function descriptor csect.
2908 // An Ifunc doesn't have a corresponding machine function.
2909 if (MF)
2910 for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])
2911 OutStreamer->emitLabel(getSymbol(Alias));
2912
2913 // Emit function entry point address.
2914 OutStreamer->emitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),
2915 PointerSize);
2916 // Emit TOC base address.
2917 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
2918 getObjFileLowering().getTOCBaseSection())
2919 ->getQualNameSymbol();
2920 OutStreamer->emitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),
2921 PointerSize);
2922 // Emit a null environment pointer.
2923 OutStreamer->emitIntValue(0, PointerSize);
2924
2925 OutStreamer->switchSection(Current.first, Current.second);
2926}
2927
2928void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
2929 // For functions without user defined section, it's not necessary to emit the
2930 // label when we have individual function in its own csect.
2931 if (!TM.getFunctionSections() || (MF && MF->getFunction().hasSection()))
2932 PPCAsmPrinter::emitFunctionEntryLabel();
2933
2934 // an ifunc does not have an associated MachineFunction
2935 if (!MF)
2936 return;
2937
2938 const Function *F = &MF->getFunction();
2939 // Emit aliasing label for function entry point label.
2940 for (const GlobalAlias *Alias : GOAliasMap[F])
2941 OutStreamer->emitLabel(
2942 getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));
2943
2944 if (F->hasMetadata(LLVMContext::MD_implicit_ref)) {
2945 emitRefMetadata(F);
2946 }
2947}
2948
2949void PPCAIXAsmPrinter::emitPGORefs(Module &M) {
2950 if (!OutContext.hasXCOFFSection(
2951 "__llvm_prf_cnts",
2952 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
2953 return;
2954
2955 // When inside a csect `foo`, a .ref directive referring to a csect `bar`
2956 // translates into a relocation entry from `foo` to` bar`. The referring
2957 // csect, `foo`, is identified by its address. If multiple csects have the
2958 // same address (because one or more of them are zero-length), the referring
2959 // csect cannot be determined. Hence, we don't generate the .ref directives
2960 // if `__llvm_prf_cnts` is an empty section.
2961 bool HasNonZeroLengthPrfCntsSection = false;
2962 const DataLayout &DL = M.getDataLayout();
2963 for (GlobalVariable &GV : M.globals())
2964 if (GV.hasSection() && GV.getSection() == "__llvm_prf_cnts" &&
2965 GV.getGlobalSize(DL) > 0) {
2966 HasNonZeroLengthPrfCntsSection = true;
2967 break;
2968 }
2969
2970 if (HasNonZeroLengthPrfCntsSection) {
2971 MCSection *CntsSection = OutContext.getXCOFFSection(
2972 "__llvm_prf_cnts", SectionKind::getData(),
2973 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),
2974 /*MultiSymbolsAllowed*/ true);
2975
2976 OutStreamer->switchSection(CntsSection);
2977 if (OutContext.hasXCOFFSection(
2978 "__llvm_prf_data",
2979 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
2980 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_data[RW]");
2981 OutStreamer->emitXCOFFRefDirective(S);
2982 }
2983 if (OutContext.hasXCOFFSection(
2984 "__llvm_prf_names",
2985 XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD))) {
2986 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_names[RO]");
2987 OutStreamer->emitXCOFFRefDirective(S);
2988 }
2989 if (OutContext.hasXCOFFSection(
2990 "__llvm_prf_vnds",
2991 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
2992 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_vnds[RW]");
2993 OutStreamer->emitXCOFFRefDirective(S);
2994 }
2995 }
2996}
2997
2998void PPCAIXAsmPrinter::emitGCOVRefs() {
2999 if (!OutContext.hasXCOFFSection(
3000 "__llvm_gcov_ctr_section",
3001 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
3002 return;
3003
3004 MCSection *CtrSection = OutContext.getXCOFFSection(
3005 "__llvm_gcov_ctr_section", SectionKind::getData(),
3006 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),
3007 /*MultiSymbolsAllowed*/ true);
3008
3009 OutStreamer->switchSection(CtrSection);
3010 const XCOFF::StorageMappingClass MappingClass =
3011 TM.Options.XCOFFReadOnlyPointers ? XCOFF::XMC_RO : XCOFF::XMC_RW;
3012 if (OutContext.hasXCOFFSection(
3013 "__llvm_covinit",
3014 XCOFF::CsectProperties(MappingClass, XCOFF::XTY_SD))) {
3015 const char *SymbolStr = TM.Options.XCOFFReadOnlyPointers
3016 ? "__llvm_covinit[RO]"
3017 : "__llvm_covinit[RW]";
3018 MCSymbol *S = OutContext.getOrCreateSymbol(SymbolStr);
3019 OutStreamer->emitXCOFFRefDirective(S);
3020 }
3021}
3022
3023void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
3024 // If there are no functions and there are no toc-data definitions in this
3025 // module, we will never need to reference the TOC base.
3026 if (M.empty() && TOCDataGlobalVars.empty())
3027 return;
3028
3029 emitPGORefs(M);
3030 emitGCOVRefs();
3031
3032 // Switch to section to emit TOC base.
3033 OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
3034
3035 PPCTargetStreamer *TS =
3036 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
3037
3038 for (auto &I : TOC) {
3039 MCSectionXCOFF *TCEntry;
3040 // Setup the csect for the current TC entry. If the variant kind is
3041 // VK_AIX_TLSGDM the entry represents the region handle, we create a
3042 // new symbol to prefix the name with a dot.
3043 // If TLS model opt is turned on, create a new symbol to prefix the name
3044 // with a dot.
3045 if (I.first.second == PPC::S_AIX_TLSGDM ||
3046 (Subtarget->hasAIXShLibTLSModelOpt() &&
3047 I.first.second == PPC::S_AIX_TLSLD)) {
3048 SmallString<128> Name;
3049 StringRef Prefix = ".";
3050 Name += Prefix;
3051 Name += static_cast<const MCSymbolXCOFF *>(I.first.first)
3052 ->getSymbolTableName();
3053 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
3054 TCEntry = static_cast<MCSectionXCOFF *>(
3055 getObjFileLowering().getSectionForTOCEntry(S, TM));
3056 } else {
3057 TCEntry = static_cast<MCSectionXCOFF *>(
3058 getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
3059 }
3060 OutStreamer->switchSection(TCEntry);
3061
3062 OutStreamer->emitLabel(I.second);
3063 TS->emitTCEntry(*I.first.first, I.first.second);
3064 }
3065
3066 // Traverse the list of global variables twice, emitting all of the
3067 // non-common global variables before the common ones, as emitting a
3068 // .comm directive changes the scope from .toc to the common symbol.
3069 for (const auto *GV : TOCDataGlobalVars) {
3070 if (!GV->hasCommonLinkage())
3071 emitGlobalVariableHelper(GV);
3072 }
3073 for (const auto *GV : TOCDataGlobalVars) {
3074 if (GV->hasCommonLinkage())
3075 emitGlobalVariableHelper(GV);
3076 }
3077}
3078
3079bool PPCAIXAsmPrinter::doInitialization(Module &M) {
3080 const bool Result = PPCAsmPrinter::doInitialization(M);
3081
3082 // Emit the .machine directive on AIX.
3083 const Triple &Target = M.getTargetTriple();
3085 // Walk through the "target-cpu" attribute of functions and use the newest
3086 // level as the CPU of the module.
3087 for (auto &F : M) {
3088 XCOFF::CFileCpuId FunCpuId =
3089 XCOFF::getCpuID(TM.getSubtargetImpl(F)->getCPU());
3090 if (FunCpuId > TargetCpuId)
3091 TargetCpuId = FunCpuId;
3092 }
3093 // If there is no "target-cpu" attribute within the functions, take the
3094 // "-mcpu" value. If both are omitted, use getNormalizedPPCTargetCPU() to
3095 // determine the default CPU.
3096 if (!TargetCpuId) {
3097 StringRef TargetCPU = TM.getTargetCPU();
3098 TargetCpuId = XCOFF::getCpuID(
3099 TargetCPU.empty() ? PPC::getNormalizedPPCTargetCPU(Target) : TargetCPU);
3100 }
3101
3102 PPCTargetStreamer *TS =
3103 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
3104 TS->emitMachine(XCOFF::getTCPUString(TargetCpuId));
3105
3106 auto setCsectAlignment = [this](const GlobalObject *GO) {
3107 // Declarations have 0 alignment which is set by default.
3108 if (GO->isDeclarationForLinker())
3109 return;
3110
3111 SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);
3112 auto *Csect = static_cast<MCSectionXCOFF *>(
3113 getObjFileLowering().SectionForGlobal(GO, GOKind, TM));
3114
3115 Align GOAlign = getGVAlignment(GO, GO->getDataLayout());
3116 Csect->ensureMinAlignment(GOAlign);
3117 };
3118
3119 // For all TLS variables, calculate their corresponding addresses and store
3120 // them into TLSVarsToAddressMapping, which will be used to determine whether
3121 // or not local-exec TLS variables require special assembly printing.
3122 uint64_t TLSVarAddress = 0;
3123 auto DL = M.getDataLayout();
3124 for (const auto &G : M.globals()) {
3125 if (G.isThreadLocal() && !G.isDeclaration()) {
3126 TLSVarAddress = alignTo(TLSVarAddress, getGVAlignment(&G, DL));
3127 TLSVarsToAddressMapping[&G] = TLSVarAddress;
3128 TLSVarAddress += G.getGlobalSize(DL);
3129 }
3130 }
3131
3132 // We need to know, up front, the alignment of csects for the assembly path,
3133 // because once a .csect directive gets emitted, we could not change the
3134 // alignment value on it.
3135 for (const auto &G : M.globals()) {
3137 continue;
3138
3140 // Generate a format indicator and a unique module id to be a part of
3141 // the sinit and sterm function names.
3142 if (FormatIndicatorAndUniqueModId.empty()) {
3143 std::string UniqueModuleId = getUniqueModuleId(&M);
3144 if (UniqueModuleId != "")
3145 // TODO: Use source file full path to generate the unique module id
3146 // and add a format indicator as a part of function name in case we
3147 // will support more than one format.
3148 FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1);
3149 else {
3150 // Use threadId, Pid, and current time as the unique module id when we
3151 // cannot generate one based on a module's strong external symbols.
3152 auto CurTime =
3153 std::chrono::duration_cast<std::chrono::nanoseconds>(
3154 std::chrono::steady_clock::now().time_since_epoch())
3155 .count();
3156 FormatIndicatorAndUniqueModId =
3157 "clangPidTidTime_" + llvm::itostr(sys::Process::getProcessId()) +
3158 "_" + llvm::itostr(llvm::get_threadid()) + "_" +
3159 llvm::itostr(CurTime);
3160 }
3161 }
3162
3163 emitSpecialLLVMGlobal(&G);
3164 continue;
3165 }
3166
3167 setCsectAlignment(&G);
3168 std::optional<CodeModel::Model> OptionalCodeModel = G.getCodeModel();
3169 if (OptionalCodeModel)
3170 setOptionalCodeModel(static_cast<MCSymbolXCOFF *>(getSymbol(&G)),
3171 *OptionalCodeModel);
3172 }
3173
3174 for (const auto &F : M)
3175 setCsectAlignment(&F);
3176
3177 // Construct an aliasing list for each GlobalObject.
3178 for (const auto &Alias : M.aliases()) {
3179 const GlobalObject *Aliasee = Alias.getAliaseeObject();
3180 if (!Aliasee)
3182 "alias without a base object is not yet supported on AIX");
3183
3184 if (Aliasee->hasCommonLinkage()) {
3185 report_fatal_error("Aliases to common variables are not allowed on AIX:"
3186 "\n\tAlias attribute for " +
3187 Alias.getName() + " is invalid because " +
3188 Aliasee->getName() + " is common.",
3189 false);
3190 }
3191
3192 const GlobalVariable *GVar =
3193 dyn_cast_or_null<GlobalVariable>(Alias.getAliaseeObject());
3194 if (GVar) {
3195 std::optional<CodeModel::Model> OptionalCodeModel = GVar->getCodeModel();
3196 if (OptionalCodeModel)
3197 setOptionalCodeModel(static_cast<MCSymbolXCOFF *>(getSymbol(&Alias)),
3198 *OptionalCodeModel);
3199 }
3200
3201 GOAliasMap[Aliasee].push_back(&Alias);
3202 }
3203
3204 return Result;
3205}
3206
3207void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {
3208 switch (MI->getOpcode()) {
3209 default:
3210 break;
3211 case PPC::TW:
3212 case PPC::TWI:
3213 case PPC::TD:
3214 case PPC::TDI: {
3215 if (MI->getNumOperands() < 5)
3216 break;
3217 const MachineOperand &LangMO = MI->getOperand(3);
3218 const MachineOperand &ReasonMO = MI->getOperand(4);
3219 if (!LangMO.isImm() || !ReasonMO.isImm())
3220 break;
3221 MCSymbol *TempSym = OutContext.createNamedTempSymbol();
3222 OutStreamer->emitLabel(TempSym);
3223 OutStreamer->emitXCOFFExceptDirective(
3224 CurrentFnSym, TempSym, LangMO.getImm(), ReasonMO.getImm(),
3225 Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 8
3226 : MI->getMF()->getInstructionCount() * 4,
3227 hasDebugInfo());
3228 break;
3229 }
3230 case PPC::GETtlsMOD32AIX:
3231 case PPC::GETtlsMOD64AIX:
3232 case PPC::GETtlsTpointer32AIX:
3233 case PPC::GETtlsADDR64AIX:
3234 case PPC::GETtlsADDR32AIX: {
3235 // A reference to .__tls_get_mod/.__tls_get_addr/.__get_tpointer is unknown
3236 // to the assembler so we need to emit an external symbol reference.
3237 MCSymbol *TlsGetAddr =
3238 createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode());
3239 ExtSymSDNodeSymbols.insert(TlsGetAddr);
3240 break;
3241 }
3242 case PPC::BL8:
3243 case PPC::BL:
3244 case PPC::BL8_NOP:
3245 case PPC::BL_NOP:
3246 case PPC::BL_LWZinto_toc:
3247 case PPC::BL_LWZinto_toc_RM:
3248 case PPC::BL8_LDinto_toc:
3249 case PPC::BL8_LDinto_toc_RM: {
3250 const MachineOperand &MO = MI->getOperand(0);
3251 if (MO.isSymbol()) {
3252 auto *S = static_cast<MCSymbolXCOFF *>(
3253 OutContext.getOrCreateSymbol(MO.getSymbolName()));
3254 ExtSymSDNodeSymbols.insert(S);
3255 }
3256 } break;
3257 case PPC::BL_TLS:
3258 case PPC::BL8_TLS:
3259 case PPC::BL8_TLS_:
3260 case PPC::BL8_NOP_TLS:
3261 report_fatal_error("TLS call not yet implemented");
3262 case PPC::TAILB:
3263 case PPC::TAILB8:
3264 case PPC::TAILBA:
3265 case PPC::TAILBA8:
3266 case PPC::TAILBCTR:
3267 case PPC::TAILBCTR8:
3268 if (MI->getOperand(0).isSymbol())
3269 report_fatal_error("Tail call for extern symbol not yet supported.");
3270 break;
3271 case PPC::DST:
3272 case PPC::DST64:
3273 case PPC::DSTT:
3274 case PPC::DSTT64:
3275 case PPC::DSTST:
3276 case PPC::DSTST64:
3277 case PPC::DSTSTT:
3278 case PPC::DSTSTT64:
3279 EmitToStreamer(
3280 *OutStreamer,
3281 MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));
3282 return;
3283 }
3284 return PPCAsmPrinter::emitInstruction(MI);
3285}
3286
3287bool PPCAIXAsmPrinter::doFinalization(Module &M) {
3288 for (MCSymbol *Sym : ExtSymSDNodeSymbols)
3289 OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern);
3290 return PPCAsmPrinter::doFinalization(M);
3291}
3292
3293static unsigned mapToSinitPriority(int P) {
3294 if (P < 0 || P > 65535)
3295 report_fatal_error("invalid init priority");
3296
3297 if (P <= 20)
3298 return P;
3299
3300 if (P < 81)
3301 return 20 + (P - 20) * 16;
3302
3303 if (P <= 1124)
3304 return 1004 + (P - 81);
3305
3306 if (P < 64512)
3307 return 2047 + (P - 1124) * 33878;
3308
3309 return 2147482625u + (P - 64512);
3310}
3311
3312static std::string convertToSinitPriority(int Priority) {
3313 // This helper function converts clang init priority to values used in sinit
3314 // and sterm functions.
3315 //
3316 // The conversion strategies are:
3317 // We map the reserved clang/gnu priority range [0, 100] into the sinit/sterm
3318 // reserved priority range [0, 1023] by
3319 // - directly mapping the first 21 and the last 20 elements of the ranges
3320 // - linear interpolating the intermediate values with a step size of 16.
3321 //
3322 // We map the non reserved clang/gnu priority range of [101, 65535] into the
3323 // sinit/sterm priority range [1024, 2147483648] by:
3324 // - directly mapping the first and the last 1024 elements of the ranges
3325 // - linear interpolating the intermediate values with a step size of 33878.
3326 unsigned int P = mapToSinitPriority(Priority);
3327
3328 std::string PrioritySuffix;
3329 llvm::raw_string_ostream os(PrioritySuffix);
3330 os << llvm::format_hex_no_prefix(P, 8);
3331 return PrioritySuffix;
3332}
3333
3334void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL,
3335 const Constant *List, bool IsCtor) {
3336 SmallVector<Structor, 8> Structors;
3337 preprocessXXStructorList(DL, List, Structors);
3338 if (Structors.empty())
3339 return;
3340
3341 unsigned Index = 0;
3342 for (Structor &S : Structors) {
3343 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(S.Func))
3344 S.Func = CE->getOperand(0);
3345
3348 (IsCtor ? llvm::Twine("__sinit") : llvm::Twine("__sterm")) +
3349 llvm::Twine(convertToSinitPriority(S.Priority)) +
3350 llvm::Twine("_", FormatIndicatorAndUniqueModId) +
3351 llvm::Twine("_", llvm::utostr(Index++)),
3352 cast<Function>(S.Func));
3353 }
3354}
3355
3356void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV,
3357 unsigned Encoding) {
3358 if (GV) {
3359 TOCEntryType GlobalType = TOCType_GlobalInternal;
3364 GlobalType = TOCType_GlobalExternal;
3365 MCSymbol *TypeInfoSym = TM.getSymbol(GV);
3366 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType);
3367 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
3368 getObjFileLowering().getTOCBaseSection())
3369 ->getQualNameSymbol();
3370 auto &Ctx = OutStreamer->getContext();
3371 const MCExpr *Exp =
3373 MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);
3374 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));
3375 } else
3376 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));
3377}
3378
3379void PPCAIXAsmPrinter::emitRefMetadata(const GlobalObject *GO) {
3381 GO->getMetadata(LLVMContext::MD_implicit_ref, MDs);
3382 assert(MDs.size() && "Expected !implicit.ref metadata nodes");
3383
3384 for (const MDNode *MD : MDs) {
3385 const ValueAsMetadata *VAM = cast<ValueAsMetadata>(MD->getOperand(0).get());
3386 const GlobalValue *GV = cast<GlobalValue>(VAM->getValue());
3387 MCSymbol *Referenced =
3388 isa<Function>(GV)
3389 ? getObjFileLowering().getFunctionEntryPointSymbol(GV, TM)
3390 : TM.getSymbol(GV);
3391 OutStreamer->emitXCOFFRefDirective(Referenced);
3392 }
3393}
3394
3395// Return a pass that prints the PPC assembly code for a MachineFunction to the
3396// given output stream.
3397static AsmPrinter *
3399 std::unique_ptr<MCStreamer> &&Streamer) {
3400 if (tm.getTargetTriple().isOSAIX())
3401 return new PPCAIXAsmPrinter(tm, std::move(Streamer));
3402
3403 return new PPCLinuxAsmPrinter(tm, std::move(Streamer));
3404}
3405
3406void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {
3407 const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");
3408 if (!NMD || !NMD->getNumOperands())
3409 return;
3410
3411 std::string S;
3412 raw_string_ostream RSOS(S);
3413 for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
3414 const MDNode *N = NMD->getOperand(i);
3415 assert(N->getNumOperands() == 1 &&
3416 "llvm.commandline metadata entry can have only one operand");
3417 const MDString *MDS = cast<MDString>(N->getOperand(0));
3418 // Add "@(#)" to support retrieving the command line information with the
3419 // AIX "what" command
3420 RSOS << "@(#)opt " << MDS->getString() << "\n";
3421 RSOS.write('\0');
3422 }
3423 OutStreamer->emitXCOFFCInfoSym(".GCC.command.line", RSOS.str());
3424}
3425
3427 enum class IsLocal {
3428 Unknown, // Structure of the llvm::Value is not one of the recognizable
3429 // structures, and so it's unknown if the llvm::Value is the
3430 // address of a local function at runtime.
3431 True, // We can statically prove that all runtime values of the
3432 // llvm::Value is an address of a local function.
3433 False // We can statically prove that one of the runtime values of the
3434 // llvm::Value is the address of a non-local function; it could be
3435 // the case that at runtime the non-local function is never
3436 // selected but we don't care.
3437 };
3438 auto Combine = [](IsLocal LHS, IsLocal RHS) -> IsLocal {
3439 if (LHS == IsLocal::False || RHS == IsLocal::False)
3440 return IsLocal::False;
3441 if (LHS == IsLocal::True && RHS == IsLocal::True)
3442 return IsLocal::True;
3443 return IsLocal::Unknown;
3444 };
3445
3446 // Query if the given function is local to the load module.
3447 auto IsLocalFunc = [](const Function *F) -> IsLocal {
3448 bool Result = F->isDSOLocal();
3449 LLVM_DEBUG(dbgs() << F->getName() << " is "
3450 << (Result ? "dso_local\n" : "not dso_local\n"));
3451 return Result ? IsLocal::True : IsLocal::False;
3452 };
3453
3454 // Recursive walker that visits certain patterns that make up the given Value,
3455 // and returns
3456 // - false if at least one non-local function was seen,
3457 // - otherwise, return unknown if some unrecognizable pattern was seen,
3458 // - otherwise, return true (which means only recognizable patterns were seen
3459 // and all possible values are local functions).
3460 std::function<IsLocal(const Value *)> ValueIsALocalFunc =
3461 [&IsLocalFunc, &Combine, &ValueIsALocalFunc](const Value *V) -> IsLocal {
3462 if (auto *F = dyn_cast<Function>(V))
3463 return IsLocalFunc(F);
3464 if (!isa<Instruction>(V))
3465 return IsLocal::Unknown;
3466
3467 auto *I = cast<Instruction>(V);
3468 // return isP9 ? foo_p9 : foo_default;
3469 if (auto *SI = dyn_cast<SelectInst>(I))
3470 return Combine(ValueIsALocalFunc(SI->getTrueValue()),
3471 ValueIsALocalFunc(SI->getFalseValue()));
3472 else if (auto *PN = dyn_cast<PHINode>(I)) {
3473 IsLocal Res = IsLocal::True;
3474 for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
3475 Res = Combine(Res, ValueIsALocalFunc(PN->getIncomingValue(i)));
3476 if (Res == IsLocal::False)
3477 return Res;
3478 }
3479 return Res;
3480 }
3481 // clang-format off
3482 // @switch.table.resolve_foo = private unnamed_addr constant [3 x ptr] [ptr @foo_static, ptr @foo_hidden, ptr @foo_protected]
3483 // %switch.gep = getelementptr inbounds nuw ptr, ptr @switch.table, i64 %2
3484 // V = load ptr, ptr %switch.gep,
3485 // clang-format on
3486 else if (auto *Op = getPointerOperand(I)) {
3487 while (isa<GEPOperator>(Op))
3488 Op = cast<GEPOperator>(Op)->getPointerOperand();
3489
3490 if (!isa<GlobalVariable>(Op))
3491 return IsLocal::Unknown;
3492 auto *GV = dyn_cast<GlobalVariable>(Op);
3493 if (!GV->hasInitializer() || !isa<ConstantArray>(GV->getInitializer()))
3494 return IsLocal::Unknown;
3495 auto *Init = cast<ConstantArray>(GV->getInitializer());
3496 IsLocal Res = IsLocal::True;
3497 for (unsigned Idx = 0, End = Init->getNumOperands(); Idx != End; ++Idx) {
3498 Res = Combine(Res, ValueIsALocalFunc(Init->getOperand(Idx)));
3499 if (Res == IsLocal::False)
3500 return Res;
3501 }
3502 return Res;
3503 }
3504 return IsLocal::Unknown;
3505 };
3506
3507 auto *Resolver = GI.getResolverFunction();
3508 // If the resolver is preemptible then we cannot rely on its implementation.
3509 if (IsLocalFunc(Resolver) == IsLocal::False && IFuncLocalIfProven)
3510 return true;
3511
3512 // If one of the return values of the resolver function is not a
3513 // local function, then we have to conservatively do a TOC save/restore.
3514 IsLocal Res = IsLocal::True;
3515 for (auto &BB : *Resolver) {
3516 if (!isa<ReturnInst>(BB.getTerminator()))
3517 continue;
3518 auto *Ret = cast<ReturnInst>(BB.getTerminator());
3519 Value *RV = Ret->getReturnValue();
3520 assert(RV);
3521 Res = Combine(Res, ValueIsALocalFunc(RV));
3522 if (Res == IsLocal::False)
3523 break;
3524 }
3525 // no TOC save/restore needed if either all functions were local or we're
3526 // being optimistic and no preemptible functions were seen.
3527 if (Res == IsLocal::True || (Res == IsLocal::Unknown && !IFuncLocalIfProven))
3528 return false;
3529 return true;
3530}
3531/*
3532 * .csect .foo[PR],5
3533 * .globl foo[DS]
3534 * .globl .foo[PR]
3535 * .lglobl ifunc_sec.foo[RW]
3536 * .align 4
3537 * .csect foo[DS],2
3538 * .vbyte 4, .foo[PR]
3539 * .vbyte 4, TOC[TC0]
3540 * .vbyte 4, 0
3541 * .csect .foo[PR],5
3542 * .ref ifunc_sec.foo[RW]
3543 * lwz 12, L..foo_desc(2) # load foo's descriptor address
3544 * lwz 11, 8(12) # load the env pointer (for non-C/C++ functions)
3545 * lwz 12, 0(12) # load foo.addr
3546 * mtctr 12
3547 * bctr # branch to CR without setting LR so that callee
3548 * # returns to the caller of .foo
3549 * # -- End function
3550 */
3551void PPCAIXAsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
3552 // Set the Subtarget to that of the resolver.
3553 const TargetSubtargetInfo *STI =
3554 TM.getSubtargetImpl(*GI.getResolverFunction());
3555 bool IsPPC64 = static_cast<const PPCSubtarget *>(STI)->isPPC64();
3556
3557 // Create syms and sections that are part of the ifunc implementation:
3558 // - Function descriptor symbol foo[RW]
3559 // - Function entry symbol .foo[PR]
3560 MCSectionXCOFF *FnDescSec = static_cast<MCSectionXCOFF *>(
3561 getObjFileLowering().getSectionForFunctionDescriptor(&GI, TM));
3562 FnDescSec->setAlignment(Align(IsPPC64 ? 8 : 4));
3563
3564 CurrentFnDescSym = FnDescSec->getQualNameSymbol();
3565
3566 CurrentFnSym = getObjFileLowering().getFunctionEntryPointSymbol(&GI, TM);
3567
3568 // Start codegen:
3569 if (TM.getFunctionSections())
3570 OutStreamer->switchSection(
3571 static_cast<MCSymbolXCOFF *>(CurrentFnSym)->getRepresentedCsect());
3572 else
3573 OutStreamer->switchSection(getObjFileLowering().getTextSection());
3574
3575 if (GI.hasMetadata(LLVMContext::MD_implicit_ref))
3576 emitRefMetadata(&GI);
3577
3578 // generate linkage for foo and .foo
3579 emitLinkage(&GI, CurrentFnDescSym);
3580 emitLinkage(&GI, CurrentFnSym);
3581
3582 // .align 4
3584 emitAlignment(Alignment, nullptr);
3585
3586 // generate foo's function descriptor
3587 emitFunctionDescriptor();
3588
3589 emitFunctionEntryLabel();
3590
3591 // generate the code for .foo now:
3593 SmallString<128> Msg;
3594 Msg.append("unimplemented: TOC register save/restore needed for ifunc \"");
3595 getNameWithPrefix(Msg, &GI);
3596 Msg.append("\", because couldn't prove all candidates are static or "
3597 "hidden/protected visibility definitions");
3600 else
3601 dbgs() << Msg << "\n";
3602 }
3603
3604 auto FnDescTOCEntryType = getTOCEntryTypeForLinkage(GI.getLinkage());
3605 auto *FnDescTOCEntrySym =
3606 lookUpOrCreateTOCEntry(CurrentFnDescSym, FnDescTOCEntryType);
3607
3608 if (TM.getCodeModel() == CodeModel::Large) {
3609 // addis 12, L..foo_desc@u(2)
3610 // lwz 12, L..foo_desc@l(12)
3611 auto *Exp_U = symbolWithSpecifier(FnDescTOCEntrySym, PPC::S_U);
3612 OutStreamer->emitInstruction(MCInstBuilder(PPC::ADDIS)
3613 .addReg(PPC::X12)
3614 .addReg(PPC::X2)
3615 .addExpr(Exp_U),
3616 *Subtarget);
3617 auto *Exp_L = symbolWithSpecifier(FnDescTOCEntrySym, PPC::S_L);
3618 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::LD : PPC::LWZ)
3619 .addReg(PPC::X12)
3620 .addExpr(Exp_L)
3621 .addReg(PPC::X12),
3622 *Subtarget);
3623 } else {
3624 // lwz 12, L..foo_desc(2)
3625 auto *Exp = MCSymbolRefExpr::create(FnDescTOCEntrySym, OutContext);
3626 // Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
3627 // TODO: do we need to uncomment this?
3628 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::LD : PPC::LWZ)
3629 .addReg(PPC::X12)
3630 .addExpr(Exp)
3631 .addReg(PPC::X2),
3632 *Subtarget);
3633 }
3634 // lwz 11, 8(12)
3635 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::LD : PPC::LWZ)
3636 .addReg(PPC::X11)
3637 .addImm(IsPPC64 ? 16 : 8)
3638 .addReg(PPC::X12),
3639 *Subtarget);
3640 // lwz 12, 0(12)
3641 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::LD : PPC::LWZ)
3642 .addReg(PPC::X12)
3643 .addImm(0)
3644 .addReg(PPC::X12),
3645 *Subtarget);
3646 // mtctr 12
3647 OutStreamer->emitInstruction(
3648 MCInstBuilder(IsPPC64 ? PPC::MTCTR8 : PPC::MTCTR).addReg(PPC::X12),
3649 *Subtarget);
3650 // bctr
3651 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::BCTR8 : PPC::BCTR),
3652 *Subtarget);
3653}
3654
3655char PPCAIXAsmPrinter::ID = 0;
3656
3657INITIALIZE_PASS(PPCAIXAsmPrinter, "ppc-aix-asm-printer",
3658 "AIX PPC Assembly Printer", false, false)
3659
3660// Force static initialization.
3661extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
3662LLVMInitializePowerPCAsmPrinter() {
3671}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
uint64_t uint64_t
static AMDGPUMCExpr::Specifier getSpecifier(unsigned MOFlags)
AMDGPU Uniform Intrinsic Combine
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:211
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
DXIL Finalize Linkage
static bool hasDebugInfo(const MachineFunction *MF)
@ Default
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
static std::string getRegisterName(const TargetRegisterInfo *TRI, Register Reg)
Machine Check Debug Module
Register Reg
This file implements a map that provides insertion order iteration.
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type)
static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV)
static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV)
static cl::opt< bool > IFuncLocalIfProven("ppc-ifunc-local-if-proven", cl::init(false), cl::desc("During ifunc lowering, the compiler assumes the resolver returns " "dso-local functions and bails out if non-local functions are " "detected; this flag flips the assumption: resolver returns " "preemptible functions unless the compiler can prove all paths " "return local functions."), cl::Hidden)
#define GENBOOLCOMMENT(Prefix, V, Field)
static MCSymbol * getMCSymbolForTOCPseudoMO(const MachineOperand &MO, AsmPrinter &AP)
Map a machine operand for a TOC pseudo-machine instruction to its corresponding MCSymbol.
static void setOptionalCodeModel(MCSymbolXCOFF *XSym, CodeModel::Model CM)
static AsmPrinter * createPPCAsmPrinterPass(TargetMachine &tm, std::unique_ptr< MCStreamer > &&Streamer)
static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI)
static PPCAsmPrinter::TOCEntryType getTOCEntryTypeForMO(const MachineOperand &MO)
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static PPCAsmPrinter::TOCEntryType getTOCEntryTypeForLinkage(GlobalValue::LinkageTypes Linkage)
static std::string convertToSinitPriority(int Priority)
static MCSymbol * createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc)
This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX.
#define GENVALUECOMMENT(PrefixAndName, V, Field)
static cl::opt< bool > IFuncWarnInsteadOfError("ppc-test-ifunc-warn-noerror", cl::init(false), cl::ReallyHidden)
static cl::opt< bool > EnableSSPCanaryBitInTB("ppc-aix-ssp-tb-bit", cl::init(false), cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden)
static unsigned mapToSinitPriority(int P)
static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV)
PassBuilder PB(Mod->getContext(), Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
Provides a library for accessing information about this process and other processes on the operating ...
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
MachineRegisterInfo & MRI
const char * Msg
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file implements a set that has insertion order iteration characteristics.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
std::unique_ptr< MCStreamer > && Streamer
Value * RHS
Value * LHS
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:95
MCSymbol * getSymbol(const GlobalValue *GV) const
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
virtual void SetupMachineFunction(MachineFunction &MF)
This should be called when a new MachineFunction is being processed from runOnMachineFunction.
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
Definition AsmPrinter.h:647
MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const
Return the symbol for the specified jump table entry.
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:478
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
LLVM_ABI unsigned getPointerSize(unsigned AS=0) const
The pointer representation size in bytes, rounded up to a whole number of bytes.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
Definition DataLayout.h:791
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
reference get()
Returns a reference to the stored T value.
Definition Error.h:582
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
Definition Globals.cpp:692
LLVM_ABI const Function * getResolverFunction() const
Definition Globals.cpp:759
StringRef getSection() const
Get the custom section of this global if it has one.
bool hasMetadata() const
Return true if this GlobalObject has any metadata attached to it.
bool hasComdat() const
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
bool hasSection() const
Check if this global has a custom object file section.
LinkageTypes getLinkage() const
bool hasPrivateLinkage() const
ThreadLocalMode getThreadLocalMode() const
bool isDeclarationForLinker() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:205
bool hasCommonLinkage() const
bool hasAppendingLinkage() const
LinkageTypes
An enumeration for the kinds of linkage for global values.
Definition GlobalValue.h:52
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
@ AvailableExternallyLinkage
Available for inspection, not emission.
Definition GlobalValue.h:54
@ ExternalWeakLinkage
ExternalWeak linkage description.
Definition GlobalValue.h:62
Type * getValueType() const
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists.
bool hasInitializer() const
Definitions have initializers, declarations don't.
std::optional< CodeModel::Model > getCodeModel() const
Get the custom code model of this global if it has one.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:342
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition MCExpr.h:448
Opcode getOpcode() const
Get the kind of this binary expression.
Definition MCExpr.h:442
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
@ Add
Addition.
Definition MCExpr.h:301
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
MCSymbolXCOFF * getQualNameSymbol() const
void setAlignment(Align Value)
Definition MCSection.h:665
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
void setPerSymbolCodeModel(MCSymbolXCOFF::CodeModel Model)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
LLVM_ABI StringRef getString() const
Definition Metadata.cpp:615
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MCSection * getSection() const
Returns the Section this function belongs to.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
int64_t getOffset() const
Return the offset from the symbol in this operand.
LLVM_ABI bool isPhysRegModified(MCRegister PhysReg, bool SkipNoReturnDef=false) const
Return true if the specified register is modified in this function.
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
iterator find(const KeyT &Key)
Definition MapVector.h:156
iterator end()
Definition MapVector.h:69
LLVM_ABI MDNode * getOperand(unsigned i) const
LLVM_ABI unsigned getNumOperands() const
uint64_t getTOCSaveOffset() const
getTOCSaveOffset - Return the previous frame offset to save the TOC register – 64-bit SVR4 ABI only.
MCSymbol * getPICOffsetSymbol(MachineFunction &MF) const
const SmallVectorImpl< Register > & getMustSaveCRs() const
unsigned getFloatingPointParmsNum() const
MCSymbol * getGlobalEPSymbol(MachineFunction &MF) const
MCSymbol * getLocalEPSymbol(MachineFunction &MF) const
MCSymbol * getTOCOffsetSymbol(MachineFunction &MF) const
static const char * getRegisterName(MCRegister Reg)
static bool hasTLSFlag(unsigned TF)
Register getFrameRegister(const MachineFunction &MF) const override
bool is32BitELFABI() const
bool isAIXABI() const
const PPCFrameLowering * getFrameLowering() const override
bool isUsingPCRelativeCalls() const
bool isAIXExtendedAltivecABI() const
Returns true when the AIX extended Altivec ABI ("vec-extabi") is in effect, allowing use of the nonvo...
CodeModel::Model getCodeModel(const TargetMachine &TM, const GlobalValue *GV) const
Calculates the effective code model for argument GV.
bool isELFv2ABI() const
const PPCRegisterInfo * getRegisterInfo() const override
bool isGVIndirectSymbol(const GlobalValue *GV) const
True if the GV will be accessed via an indirect symbol.
static PPCABI computeABI(const Triple &TT, StringRef ABIName)
Compute the ABI variant for TT and ABIName (the "target-abi" module flag), falling back to the triple...
virtual void emitAbiVersion(int AbiVersion)
virtual void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset)
virtual void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind)
virtual void emitMachine(StringRef CPU)
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition Record.h:2295
bool isThreadBSSLocal() const
static SectionKind getText()
bool isBSSLocal() const
static SectionKind getData()
bool isThreadLocal() const
bool isReadOnly() const
bool isGlobalWriteableData() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
void push_back(const T &Elt)
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(std::initializer_list< StringLiteral > CaseStrings, T Value)
Align getMinFunctionAlignment() const
Return the minimum function alignment.
static bool ShouldSetSSPCanaryBitInTB(const MachineFunction *MF)
static MCSymbol * getEHInfoTableSymbol(const MachineFunction *MF)
static XCOFF::StorageClass getStorageClassForGlobal(const GlobalValue *GV)
static bool ShouldEmitEHBlock(const MachineFunction *MF)
Primary interface to the complete machine description for the target machine.
const Triple & getTargetTriple() const
CodeModel::Model getCodeModel() const
Returns the code model.
virtual const TargetLowering * getTargetLowering() const
bool isOSAIX() const
Tests whether the OS is AIX.
Definition Triple.h:856
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isSized() const
Return true if it makes sense to take the size of this type.
Definition Type.h:321
Value * getValue() const
Definition Metadata.h:510
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:986
LLVM_ABI void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
bool hasName() const
Definition Value.h:263
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
static LLVM_ABI Pid getProcessId()
Get the process's identifier.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ SHF_ALLOC
Definition ELF.h:1067
@ SHF_WRITE
Definition ELF.h:1064
@ SHT_PROGBITS
Definition ELF.h:965
Flag
These should be considered private to the implementation of the MCInstrDesc class.
@ MO_TLSLDM_FLAG
MO_TLSLDM_FLAG - on AIX the ML relocation type is only valid for a reference to a TOC symbol from the...
Definition PPC.h:157
@ MO_TPREL_PCREL_FLAG
MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TPREL_FLAG.
Definition PPC.h:208
@ MO_GOT_TPREL_PCREL_FLAG
MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
Definition PPC.h:183
@ MO_TLSGDM_FLAG
MO_TLSGDM_FLAG - If this bit is set the symbol reference is relative to the region handle of TLS Gene...
Definition PPC.h:165
@ MO_TLSLD_FLAG
MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to TLS Local Dynamic model.
Definition PPC.h:161
@ MO_TPREL_FLAG
MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to the thread pointer and the sy...
Definition PPC.h:151
@ MO_GOT_TLSLD_PCREL_FLAG
MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
Definition PPC.h:177
@ MO_TLSGD_FLAG
MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to TLS General Dynamic model for ...
Definition PPC.h:146
@ MO_GOT_TLSGD_PCREL_FLAG
MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
Definition PPC.h:171
LLVM_ABI StringRef getNormalizedPPCTargetCPU(const Triple &T, StringRef CPUName="")
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
const char * stripRegisterPrefix(const char *RegName)
stripRegisterPrefix - This method strips the character prefix from a register name so that only the n...
Predicate InvertPredicate(Predicate Opcode)
Invert the specified predicate. != -> ==, < -> >=.
static bool isVRRegister(MCRegister Reg)
static bool isVFRegister(MCRegister Reg)
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
LLVM_ABI SmallString< 32 > getExtendedTBTableFlagString(uint8_t Flag)
Definition XCOFF.cpp:221
LLVM_ABI XCOFF::CFileCpuId getCpuID(StringRef CPU)
Definition XCOFF.cpp:112
LLVM_ABI Expected< SmallString< 32 > > parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, unsigned FloatingParmsNum, unsigned VectorParmsNum)
Definition XCOFF.cpp:247
LLVM_ABI Expected< SmallString< 32 > > parseParmsType(uint32_t Value, unsigned FixedParmsNum, unsigned FloatingParmsNum)
Definition XCOFF.cpp:169
LLVM_ABI Expected< SmallString< 32 > > parseVectorParmsType(uint32_t Value, unsigned ParmsNum)
Definition XCOFF.cpp:299
@ TCPU_INVALID
Invalid id - assumes POWER for old objects.
Definition XCOFF.h:339
StorageMappingClass
Storage Mapping Class definitions.
Definition XCOFF.h:104
@ XMC_RW
Read Write Data.
Definition XCOFF.h:118
@ XMC_RO
Read Only Constant.
Definition XCOFF.h:107
@ XMC_TD
Scalar data item in the TOC.
Definition XCOFF.h:121
@ XMC_PR
Program Code.
Definition XCOFF.h:106
LLVM_ABI StringRef getTCPUString(XCOFF::CFileCpuId TCPU)
Definition XCOFF.cpp:141
LLVM_ABI StringRef getNameForTracebackTableLanguageId(TracebackTable::LanguageID LangId)
Definition XCOFF.cpp:89
constexpr uint8_t AllocRegNo
Definition XCOFF.h:45
@ XTY_SD
Csect definition for initialized storage.
Definition XCOFF.h:243
@ XTY_ER
External reference.
Definition XCOFF.h:242
initializer< Ty > init(const Ty &Val)
unsigned combineHashValue(unsigned a, unsigned b)
Simplistic combination of 32-bit hash values into 32-bit hash values.
This is an optimization pass for GlobalISel generic memory operations.
std::optional< LongDoubleFormat > parseLongDoubleFormat(StringRef Name)
Parses an IR floating-point type name into a LongDoubleFormat, returning std::nullopt if it does not ...
Definition CodeGen.h:144
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
Target & getThePPC64LETarget()
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
@ Unknown
Not known to have no common set bits.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto cast_or_null(const Y &Val)
Definition Casting.h:714
Target & getThePPC32Target()
std::string utostr(uint64_t X, bool isNeg=false)
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_ABI std::string getUniqueModuleId(Module *M)
Produce a unique identifier for this module by taking the MD5 sum of the names of the module's strong...
void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
bool LowerPPCMachineOperandToMCOperand(unsigned MIOpcode, const MachineOperand &MO, MCOperand &OutMO, AsmPrinter &AP)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
Definition Format.h:177
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
Target & getThePPC64Target()
LLVM_ABI uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
Definition Threading.cpp:33
DWARFExpression::Operation Op
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
Definition MathExtras.h:554
Target & getThePPC32LETarget()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
std::pair< MCSection *, uint32_t > MCSectionSubPair
Definition MCStreamer.h:68
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
@ PPC_ABI_ELFv2
Definition PPC.h:104
std::string itostr(int64_t X)
@ MCSA_Extern
.extern (XCOFF)
@ MCSA_Invalid
Not a valid directive.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:82
std::pair< const MCSymbol *, PPCMCExpr::Specifier > TOCKey
An information struct used to provide DenseMap with the various necessary components for a given valu...
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:135
static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn)
RegisterAsmPrinter - Register an AsmPrinter implementation for the given target.
static constexpr uint32_t FPRSavedMask
Definition XCOFF.h:437
static constexpr uint16_t NumberOfVRSavedMask
Definition XCOFF.h:467
static constexpr uint8_t NumberOfFloatingPointParmsShift
Definition XCOFF.h:453
static constexpr uint32_t NumberOfFixedParmsMask
Definition XCOFF.h:447
static constexpr uint16_t HasVMXInstructionMask
Definition XCOFF.h:473
static constexpr uint32_t IsLRSavedMask
Definition XCOFF.h:431
static constexpr uint16_t HasVarArgsMask
Definition XCOFF.h:469
static constexpr uint32_t IsAllocaUsedMask
Definition XCOFF.h:428
static constexpr uint16_t IsVRSavedOnStackMask
Definition XCOFF.h:468
static constexpr uint16_t NumberOfVectorParmsMask
Definition XCOFF.h:472
static constexpr uint32_t IsFloatingPointPresentMask
Definition XCOFF.h:421
static constexpr uint32_t FPRSavedShift
Definition XCOFF.h:438
static constexpr uint32_t NumberOfFloatingPointParmsMask
Definition XCOFF.h:451
static constexpr uint32_t HasControlledStorageMask
Definition XCOFF.h:419
static constexpr uint32_t HasExtensionTableMask
Definition XCOFF.h:441
static constexpr uint32_t HasTraceBackTableOffsetMask
Definition XCOFF.h:417
static constexpr uint32_t IsCRSavedMask
Definition XCOFF.h:430
static constexpr uint8_t NumberOfFixedParmsShift
Definition XCOFF.h:448
static constexpr uint32_t GPRSavedMask
Definition XCOFF.h:443
static constexpr uint8_t NumberOfVectorParmsShift
Definition XCOFF.h:474
static constexpr uint32_t HasParmsOnStackMask
Definition XCOFF.h:452
static constexpr uint32_t IsFunctionNamePresentMask
Definition XCOFF.h:427
static constexpr uint32_t IsBackChainStoredMask
Definition XCOFF.h:435
static constexpr uint32_t IsInterruptHandlerMask
Definition XCOFF.h:426
static constexpr uint32_t HasVectorInfoMask
Definition XCOFF.h:442
static constexpr uint8_t NumberOfVRSavedShift
Definition XCOFF.h:470
static constexpr uint32_t GPRSavedShift
Definition XCOFF.h:444