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