LLVM 23.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 float ABI into GNU attribute
1772 Metadata *MD = M.getModuleFlag("float-abi");
1773 MDString *FloatABI = dyn_cast_or_null<MDString>(MD);
1774 if (!FloatABI)
1775 return;
1776 StringRef flt = FloatABI->getString();
1777 // TODO: Support emitting soft-fp and hard double/single attributes.
1778 if (flt == "doubledouble")
1779 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1780 Val_GNU_Power_ABI_HardFloat_DP |
1781 Val_GNU_Power_ABI_LDBL_IBM128);
1782 else if (flt == "ieeequad")
1783 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1784 Val_GNU_Power_ABI_HardFloat_DP |
1785 Val_GNU_Power_ABI_LDBL_IEEE128);
1786 else if (flt == "ieeedouble")
1787 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1788 Val_GNU_Power_ABI_HardFloat_DP |
1789 Val_GNU_Power_ABI_LDBL_64);
1790}
1791
1792void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
1793 if (!Subtarget->isPPC64())
1794 return PPCAsmPrinter::emitInstruction(MI);
1795
1796 switch (MI->getOpcode()) {
1797 default:
1798 break;
1799 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1800 // .begin:
1801 // b .end # lis 0, FuncId[16..32]
1802 // nop # li 0, FuncId[0..15]
1803 // std 0, -8(1)
1804 // mflr 0
1805 // bl __xray_FunctionEntry
1806 // mtlr 0
1807 // .end:
1808 //
1809 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1810 // of instructions change.
1811 // XRAY is only supported on PPC Linux little endian.
1812 const Function &F = MF->getFunction();
1813 unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry");
1814
1815 if (!MAI.isLittleEndian() || Num)
1816 break;
1817 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1818 MCSymbol *EndOfSled = OutContext.createTempSymbol();
1819 OutStreamer->emitLabel(BeginOfSled);
1820 EmitToStreamer(*OutStreamer,
1821 MCInstBuilder(PPC::B).addExpr(
1822 MCSymbolRefExpr::create(EndOfSled, OutContext)));
1823 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1824 EmitToStreamer(
1825 *OutStreamer,
1826 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1827 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1828 EmitToStreamer(*OutStreamer,
1829 MCInstBuilder(PPC::BL8_NOP)
1830 .addExpr(MCSymbolRefExpr::create(
1831 OutContext.getOrCreateSymbol("__xray_FunctionEntry"),
1832 OutContext)));
1833 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1834 OutStreamer->emitLabel(EndOfSled);
1835 recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER, 2);
1836 break;
1837 }
1838 case TargetOpcode::PATCHABLE_RET: {
1839 unsigned RetOpcode = MI->getOperand(0).getImm();
1840 MCInst RetInst;
1841 RetInst.setOpcode(RetOpcode);
1842 for (const auto &MO : llvm::drop_begin(MI->operands())) {
1843 MCOperand MCOp;
1844 if (LowerPPCMachineOperandToMCOperand(MO, MCOp, *this))
1845 RetInst.addOperand(MCOp);
1846 }
1847
1848 bool IsConditional;
1849 if (RetOpcode == PPC::BCCLR) {
1850 IsConditional = true;
1851 } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
1852 RetOpcode == PPC::TCRETURNai8) {
1853 break;
1854 } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
1855 IsConditional = false;
1856 } else {
1857 EmitToStreamer(*OutStreamer, RetInst);
1858 return;
1859 }
1860
1861 MCSymbol *FallthroughLabel;
1862 if (IsConditional) {
1863 // Before:
1864 // bgtlr cr0
1865 //
1866 // After:
1867 // ble cr0, .end
1868 // .p2align 3
1869 // .begin:
1870 // blr # lis 0, FuncId[16..32]
1871 // nop # li 0, FuncId[0..15]
1872 // std 0, -8(1)
1873 // mflr 0
1874 // bl __xray_FunctionExit
1875 // mtlr 0
1876 // blr
1877 // .end:
1878 //
1879 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1880 // of instructions change.
1881 FallthroughLabel = OutContext.createTempSymbol();
1882 EmitToStreamer(
1883 *OutStreamer,
1884 MCInstBuilder(PPC::BCC)
1885 .addImm(PPC::InvertPredicate(
1886 static_cast<PPC::Predicate>(MI->getOperand(1).getImm())))
1887 .addReg(MI->getOperand(2).getReg())
1888 .addExpr(MCSymbolRefExpr::create(FallthroughLabel, OutContext)));
1889 RetInst = MCInst();
1890 RetInst.setOpcode(PPC::BLR8);
1891 }
1892 // .p2align 3
1893 // .begin:
1894 // b(lr)? # lis 0, FuncId[16..32]
1895 // nop # li 0, FuncId[0..15]
1896 // std 0, -8(1)
1897 // mflr 0
1898 // bl __xray_FunctionExit
1899 // mtlr 0
1900 // b(lr)?
1901 //
1902 // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number
1903 // of instructions change.
1904 OutStreamer->emitCodeAlignment(Align(8), &getSubtargetInfo());
1905 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1906 OutStreamer->emitLabel(BeginOfSled);
1907 EmitToStreamer(*OutStreamer, RetInst);
1908 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1909 EmitToStreamer(
1910 *OutStreamer,
1911 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1912 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1913 EmitToStreamer(*OutStreamer,
1914 MCInstBuilder(PPC::BL8_NOP)
1915 .addExpr(MCSymbolRefExpr::create(
1916 OutContext.getOrCreateSymbol("__xray_FunctionExit"),
1917 OutContext)));
1918 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1919 EmitToStreamer(*OutStreamer, RetInst);
1920 if (IsConditional)
1921 OutStreamer->emitLabel(FallthroughLabel);
1922 recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT, 2);
1923 return;
1924 }
1925 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1926 llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
1927 case TargetOpcode::PATCHABLE_TAIL_CALL:
1928 // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a
1929 // normal function exit from a tail exit.
1930 llvm_unreachable("Tail call is handled in the normal case. See comments "
1931 "around this assert.");
1932 }
1933 return PPCAsmPrinter::emitInstruction(MI);
1934}
1935
1936void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {
1937 if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {
1938 PPCTargetStreamer *TS =
1939 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
1940 TS->emitAbiVersion(2);
1941 }
1942
1943 if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||
1944 !isPositionIndependent())
1946
1947 if (M.getPICLevel() == PICLevel::SmallPIC)
1949
1950 OutStreamer->switchSection(OutContext.getELFSection(
1952
1953 MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC"));
1954 MCSymbol *CurrentPos = OutContext.createTempSymbol();
1955
1956 OutStreamer->emitLabel(CurrentPos);
1957
1958 // The GOT pointer points to the middle of the GOT, in order to reference the
1959 // entire 64kB range. 0x8000 is the midpoint.
1960 const MCExpr *tocExpr =
1961 MCBinaryExpr::createAdd(MCSymbolRefExpr::create(CurrentPos, OutContext),
1962 MCConstantExpr::create(0x8000, OutContext),
1963 OutContext);
1964
1965 OutStreamer->emitAssignment(TOCSym, tocExpr);
1966
1967 OutStreamer->switchSection(getObjFileLowering().getTextSection());
1968}
1969
1970void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {
1971 // linux/ppc32 - Normal entry label.
1972 if (!Subtarget->isPPC64() &&
1973 (!isPositionIndependent() ||
1974 MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC))
1976
1977 if (!Subtarget->isPPC64()) {
1978 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
1979 if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {
1980 MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(*MF);
1981 MCSymbol *PICBase = MF->getPICBaseSymbol();
1982 OutStreamer->emitLabel(RelocSymbol);
1983
1984 const MCExpr *OffsExpr =
1986 MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")),
1987 OutContext),
1988 MCSymbolRefExpr::create(PICBase, OutContext),
1989 OutContext);
1990 OutStreamer->emitValue(OffsExpr, 4);
1991 OutStreamer->emitLabel(CurrentFnSym);
1992 return;
1993 } else
1995 }
1996
1997 // ELFv2 ABI - Normal entry label.
1998 if (Subtarget->isELFv2ABI()) {
1999 // In the Large code model, we allow arbitrary displacements between
2000 // the text section and its associated TOC section. We place the
2001 // full 8-byte offset to the TOC in memory immediately preceding
2002 // the function global entry point.
2003 if (TM.getCodeModel() == CodeModel::Large
2004 && !MF->getRegInfo().use_empty(PPC::X2)) {
2005 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
2006
2007 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));
2008 MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(*MF);
2009 const MCExpr *TOCDeltaExpr =
2010 MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),
2011 MCSymbolRefExpr::create(GlobalEPSymbol,
2012 OutContext),
2013 OutContext);
2014
2015 OutStreamer->emitLabel(PPCFI->getTOCOffsetSymbol(*MF));
2016 OutStreamer->emitValue(TOCDeltaExpr, 8);
2017 }
2019 }
2020
2021 // Emit an official procedure descriptor.
2022 MCSectionSubPair Current = OutStreamer->getCurrentSection();
2023 MCSectionELF *Section = OutStreamer->getContext().getELFSection(
2025 OutStreamer->switchSection(Section);
2026 OutStreamer->emitLabel(CurrentFnSym);
2027 OutStreamer->emitValueToAlignment(Align(8));
2028 MCSymbol *Symbol1 = CurrentFnSymForSize;
2029 // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function
2030 // entry point.
2031 OutStreamer->emitValue(MCSymbolRefExpr::create(Symbol1, OutContext),
2032 8 /*size*/);
2033 MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC."));
2034 // Generates a R_PPC64_TOC relocation for TOC base insertion.
2035 OutStreamer->emitValue(
2036 MCSymbolRefExpr::create(Symbol2, PPC::S_TOCBASE, OutContext), 8 /*size*/);
2037 // Emit a null environment pointer.
2038 OutStreamer->emitIntValue(0, 8 /* size */);
2039 OutStreamer->switchSection(Current.first, Current.second);
2040}
2041
2042void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {
2043 const DataLayout &DL = getDataLayout();
2044
2045 bool isPPC64 = DL.getPointerSizeInBits() == 64;
2046
2047 PPCTargetStreamer *TS =
2048 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2049
2050 // If we are using any values provided by Glibc at fixed addresses,
2051 // we need to ensure that the Glibc used at link time actually provides
2052 // those values. All versions of Glibc that do will define the symbol
2053 // named "__parse_hwcap_and_convert_at_platform".
2054 if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess())
2055 OutStreamer->emitSymbolValue(
2056 GetExternalSymbolSymbol("__parse_hwcap_and_convert_at_platform"),
2057 MAI.getCodePointerSize());
2058 emitGNUAttributes(M);
2059
2060 if (!TOC.empty()) {
2061 const char *Name = isPPC64 ? ".toc" : ".got2";
2062 MCSectionELF *Section = OutContext.getELFSection(
2064 OutStreamer->switchSection(Section);
2065 if (!isPPC64)
2066 OutStreamer->emitValueToAlignment(Align(4));
2067
2068 for (const auto &TOCMapPair : TOC) {
2069 const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;
2070 MCSymbol *const TOCEntryLabel = TOCMapPair.second;
2071
2072 OutStreamer->emitLabel(TOCEntryLabel);
2073 if (isPPC64)
2074 TS->emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);
2075 else
2076 OutStreamer->emitSymbolValue(TOCEntryTarget, 4);
2077 }
2078 }
2079
2080 PPCAsmPrinter::emitEndOfAsmFile(M);
2081}
2082
2083/// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2.
2084void PPCLinuxAsmPrinter::emitFunctionBodyStart() {
2085 // In the ELFv2 ABI, in functions that use the TOC register, we need to
2086 // provide two entry points. The ABI guarantees that when calling the
2087 // local entry point, r2 is set up by the caller to contain the TOC base
2088 // for this function, and when calling the global entry point, r12 is set
2089 // up by the caller to hold the address of the global entry point. We
2090 // thus emit a prefix sequence along the following lines:
2091 //
2092 // func:
2093 // .Lfunc_gepNN:
2094 // # global entry point
2095 // addis r2,r12,(.TOC.-.Lfunc_gepNN)@ha
2096 // addi r2,r2,(.TOC.-.Lfunc_gepNN)@l
2097 // .Lfunc_lepNN:
2098 // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN
2099 // # local entry point, followed by function body
2100 //
2101 // For the Large code model, we create
2102 //
2103 // .Lfunc_tocNN:
2104 // .quad .TOC.-.Lfunc_gepNN # done by EmitFunctionEntryLabel
2105 // func:
2106 // .Lfunc_gepNN:
2107 // # global entry point
2108 // ld r2,.Lfunc_tocNN-.Lfunc_gepNN(r12)
2109 // add r2,r2,r12
2110 // .Lfunc_lepNN:
2111 // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN
2112 // # local entry point, followed by function body
2113 //
2114 // This ensures we have r2 set up correctly while executing the function
2115 // body, no matter which entry point is called.
2116 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
2117 const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||
2118 !MF->getRegInfo().use_empty(PPC::R2);
2119 const bool PCrelGEPRequired = Subtarget->isUsingPCRelativeCalls() &&
2120 UsesX2OrR2 && PPCFI->usesTOCBasePtr();
2121 const bool NonPCrelGEPRequired = !Subtarget->isUsingPCRelativeCalls() &&
2122 Subtarget->isELFv2ABI() && UsesX2OrR2;
2123
2124 // Only do all that if the function uses R2 as the TOC pointer
2125 // in the first place. We don't need the global entry point if the
2126 // function uses R2 as an allocatable register.
2127 if (NonPCrelGEPRequired || PCrelGEPRequired) {
2128 // Note: The logic here must be synchronized with the code in the
2129 // branch-selection pass which sets the offset of the first block in the
2130 // function. This matters because it affects the alignment.
2131 MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(*MF);
2132 OutStreamer->emitLabel(GlobalEntryLabel);
2133 const MCSymbolRefExpr *GlobalEntryLabelExp =
2134 MCSymbolRefExpr::create(GlobalEntryLabel, OutContext);
2135
2136 if (TM.getCodeModel() != CodeModel::Large) {
2137 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));
2138 const MCExpr *TOCDeltaExpr =
2139 MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext),
2140 GlobalEntryLabelExp, OutContext);
2141
2142 const MCExpr *TOCDeltaHi =
2143 MCSpecifierExpr::create(TOCDeltaExpr, PPC::S_HA, OutContext);
2144 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
2145 .addReg(PPC::X2)
2146 .addReg(PPC::X12)
2147 .addExpr(TOCDeltaHi));
2148
2149 const MCExpr *TOCDeltaLo =
2150 MCSpecifierExpr::create(TOCDeltaExpr, PPC::S_LO, OutContext);
2151 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
2152 .addReg(PPC::X2)
2153 .addReg(PPC::X2)
2154 .addExpr(TOCDeltaLo));
2155 } else {
2156 MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(*MF);
2157 const MCExpr *TOCOffsetDeltaExpr =
2158 MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCOffset, OutContext),
2159 GlobalEntryLabelExp, OutContext);
2160
2161 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
2162 .addReg(PPC::X2)
2163 .addExpr(TOCOffsetDeltaExpr)
2164 .addReg(PPC::X12));
2165 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)
2166 .addReg(PPC::X2)
2167 .addReg(PPC::X2)
2168 .addReg(PPC::X12));
2169 }
2170
2171 MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(*MF);
2172 OutStreamer->emitLabel(LocalEntryLabel);
2173 const MCSymbolRefExpr *LocalEntryLabelExp =
2174 MCSymbolRefExpr::create(LocalEntryLabel, OutContext);
2175 const MCExpr *LocalOffsetExp =
2176 MCBinaryExpr::createSub(LocalEntryLabelExp,
2177 GlobalEntryLabelExp, OutContext);
2178
2179 PPCTargetStreamer *TS =
2180 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2181 TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),
2182 LocalOffsetExp);
2183 } else if (Subtarget->isUsingPCRelativeCalls()) {
2184 // When generating the entry point for a function we have a few scenarios
2185 // based on whether or not that function uses R2 and whether or not that
2186 // function makes calls (or is a leaf function).
2187 // 1) A leaf function that does not use R2 (or treats it as callee-saved
2188 // and preserves it). In this case st_other=0 and both
2189 // the local and global entry points for the function are the same.
2190 // No special entry point code is required.
2191 // 2) A function uses the TOC pointer R2. This function may or may not have
2192 // calls. In this case st_other=[2,6] and the global and local entry
2193 // points are different. Code to correctly setup the TOC pointer in R2
2194 // is put between the global and local entry points. This case is
2195 // covered by the if statatement above.
2196 // 3) A function does not use the TOC pointer R2 but does have calls.
2197 // In this case st_other=1 since we do not know whether or not any
2198 // of the callees clobber R2. This case is dealt with in this else if
2199 // block. Tail calls are considered calls and the st_other should also
2200 // be set to 1 in that case as well.
2201 // 4) The function does not use the TOC pointer but R2 is used inside
2202 // the function. In this case st_other=1 once again.
2203 // 5) This function uses inline asm. We mark R2 as reserved if the function
2204 // has inline asm as we have to assume that it may be used.
2205 if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||
2206 MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) {
2207 PPCTargetStreamer *TS =
2208 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2209 TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),
2210 MCConstantExpr::create(1, OutContext));
2211 }
2212 }
2213}
2214
2215/// EmitFunctionBodyEnd - Print the traceback table before the .size
2216/// directive.
2217///
2218void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
2219 // Only the 64-bit target requires a traceback table. For now,
2220 // we only emit the word of zeroes that GDB requires to find
2221 // the end of the function, and zeroes for the eight-byte
2222 // mandatory fields.
2223 // FIXME: We should fill in the eight-byte mandatory fields as described in
2224 // the PPC64 ELF ABI (this is a low-priority item because GDB does not
2225 // currently make use of these fields).
2226 if (Subtarget->isPPC64()) {
2227 OutStreamer->emitIntValue(0, 4/*size*/);
2228 OutStreamer->emitIntValue(0, 8/*size*/);
2229 }
2230}
2231
2232char PPCLinuxAsmPrinter::ID = 0;
2233
2234INITIALIZE_PASS(PPCLinuxAsmPrinter, "ppc-linux-asm-printer",
2235 "Linux PPC Assembly Printer", false, false)
2236
2237void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
2238 MCSymbol *GVSym) const {
2239 MCSymbolAttr LinkageAttr = MCSA_Invalid;
2240 switch (GV->getLinkage()) {
2241 case GlobalValue::ExternalLinkage:
2242 LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;
2243 break;
2244 case GlobalValue::LinkOnceAnyLinkage:
2245 case GlobalValue::LinkOnceODRLinkage:
2246 case GlobalValue::WeakAnyLinkage:
2247 case GlobalValue::WeakODRLinkage:
2248 case GlobalValue::ExternalWeakLinkage:
2249 LinkageAttr = MCSA_Weak;
2250 break;
2251 case GlobalValue::AvailableExternallyLinkage:
2252 LinkageAttr = MCSA_Extern;
2253 break;
2254 case GlobalValue::PrivateLinkage:
2255 return;
2256 case GlobalValue::InternalLinkage:
2257 assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&
2258 "InternalLinkage should not have other visibility setting.");
2259 LinkageAttr = MCSA_LGlobal;
2260 break;
2261 case GlobalValue::AppendingLinkage:
2262 llvm_unreachable("Should never emit this");
2263 case GlobalValue::CommonLinkage:
2264 llvm_unreachable("CommonLinkage of XCOFF should not come to this path");
2265 }
2266
2267 assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");
2268
2269 MCSymbolAttr VisibilityAttr = MCSA_Invalid;
2270 if (!TM.getIgnoreXCOFFVisibility()) {
2271 if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())
2272 report_fatal_error(
2273 "Cannot not be both dllexport and non-default visibility");
2274 switch (GV->getVisibility()) {
2275
2276 // TODO: "internal" Visibility needs to go here.
2277 case GlobalValue::DefaultVisibility:
2278 if (GV->hasDLLExportStorageClass())
2279 VisibilityAttr = MAI.getExportedVisibilityAttr();
2280 break;
2281 case GlobalValue::HiddenVisibility:
2282 VisibilityAttr = MAI.getHiddenVisibilityAttr();
2283 break;
2284 case GlobalValue::ProtectedVisibility:
2285 VisibilityAttr = MAI.getProtectedVisibilityAttr();
2286 break;
2287 }
2288 }
2289
2290 // Do not emit the _$TLSML symbol.
2291 if (GV->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&
2292 GV->hasName() && GV->getName() == "_$TLSML")
2293 return;
2294
2295 OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
2296 VisibilityAttr);
2297}
2298
2299void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
2300 // Setup CurrentFnDescSym and its containing csect.
2301 auto *FnDescSec = static_cast<MCSectionXCOFF *>(
2302 getObjFileLowering().getSectionForFunctionDescriptor(&MF.getFunction(),
2303 TM));
2304 FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4));
2305
2306 CurrentFnDescSym = FnDescSec->getQualNameSymbol();
2307
2309}
2310
2311uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {
2312 // Calculate the number of VRs be saved.
2313 // Vector registers 20 through 31 are marked as reserved and cannot be used
2314 // in the default ABI.
2315 const PPCSubtarget &Subtarget = MF->getSubtarget<PPCSubtarget>();
2316 if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&
2317 TM.getAIXExtendedAltivecABI()) {
2318 const MachineRegisterInfo &MRI = MF->getRegInfo();
2319 for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg)
2320 if (MRI.isPhysRegModified(Reg))
2321 // Number of VRs saved.
2322 return PPC::V31 - Reg + 1;
2323 }
2324 return 0;
2325}
2326
2327void PPCAIXAsmPrinter::emitFunctionBodyEnd() {
2328
2329 if (!TM.getXCOFFTracebackTable())
2330 return;
2331
2332 emitTracebackTable();
2333
2334 // If ShouldEmitEHBlock returns true, then the eh info table
2335 // will be emitted via `AIXException::endFunction`. Otherwise, we
2336 // need to emit a dumy eh info table when VRs are saved. We could not
2337 // consolidate these two places into one because there is no easy way
2338 // to access register information in `AIXException` class.
2340 (getNumberOfVRSaved() > 0)) {
2341 // Emit dummy EH Info Table.
2342 OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());
2343 MCSymbol *EHInfoLabel =
2345 OutStreamer->emitLabel(EHInfoLabel);
2346
2347 // Version number.
2348 OutStreamer->emitInt32(0);
2349
2350 const DataLayout &DL = MMI->getModule()->getDataLayout();
2351 const unsigned PointerSize = DL.getPointerSize();
2352 // Add necessary paddings in 64 bit mode.
2353 OutStreamer->emitValueToAlignment(Align(PointerSize));
2354
2355 OutStreamer->emitIntValue(0, PointerSize);
2356 OutStreamer->emitIntValue(0, PointerSize);
2357 OutStreamer->switchSection(MF->getSection());
2358 }
2359}
2360
2361void PPCAIXAsmPrinter::emitTracebackTable() {
2362
2363 // Create a symbol for the end of function.
2364 MCSymbol *FuncEnd = createTempSymbol(MF->getName());
2365 OutStreamer->emitLabel(FuncEnd);
2366
2367 OutStreamer->AddComment("Traceback table begin");
2368 // Begin with a fullword of zero.
2369 OutStreamer->emitIntValueInHexWithPadding(0, 4 /*size*/);
2370
2371 SmallString<128> CommentString;
2372 raw_svector_ostream CommentOS(CommentString);
2373
2374 auto EmitComment = [&]() {
2375 OutStreamer->AddComment(CommentOS.str());
2376 CommentString.clear();
2377 };
2378
2379 auto EmitCommentAndValue = [&](uint64_t Value, int Size) {
2380 EmitComment();
2381 OutStreamer->emitIntValueInHexWithPadding(Value, Size);
2382 };
2383
2384 unsigned int Version = 0;
2385 CommentOS << "Version = " << Version;
2386 EmitCommentAndValue(Version, 1);
2387
2388 // There is a lack of information in the IR to assist with determining the
2389 // source language. AIX exception handling mechanism would only search for
2390 // personality routine and LSDA area when such language supports exception
2391 // handling. So to be conservatively correct and allow runtime to do its job,
2392 // we need to set it to C++ for now.
2393 TracebackTable::LanguageID LanguageIdentifier =
2395
2396 CommentOS << "Language = "
2397 << getNameForTracebackTableLanguageId(LanguageIdentifier);
2398 EmitCommentAndValue(LanguageIdentifier, 1);
2399
2400 // This is only populated for the third and fourth bytes.
2401 uint32_t FirstHalfOfMandatoryField = 0;
2402
2403 // Emit the 3rd byte of the mandatory field.
2404
2405 // We always set traceback offset bit to true.
2406 FirstHalfOfMandatoryField |= TracebackTable::HasTraceBackTableOffsetMask;
2407
2408 const PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
2409 const MachineRegisterInfo &MRI = MF->getRegInfo();
2410
2411 // Check the function uses floating-point processor instructions or not
2412 for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {
2413 if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
2414 FirstHalfOfMandatoryField |= TracebackTable::IsFloatingPointPresentMask;
2415 break;
2416 }
2417 }
2418
2419#define GENBOOLCOMMENT(Prefix, V, Field) \
2420 CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \
2421 << #Field
2422
2423#define GENVALUECOMMENT(PrefixAndName, V, Field) \
2424 CommentOS << (PrefixAndName) << " = " \
2425 << static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >> \
2426 (TracebackTable::Field##Shift))
2427
2428 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsGlobalLinkage);
2429 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);
2430 EmitComment();
2431
2432 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasTraceBackTableOffset);
2433 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsInternalProcedure);
2434 EmitComment();
2435
2436 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasControlledStorage);
2437 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsTOCless);
2438 EmitComment();
2439
2440 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsFloatingPointPresent);
2441 EmitComment();
2442 GENBOOLCOMMENT("", FirstHalfOfMandatoryField,
2443 IsFloatingPointOperationLogOrAbortEnabled);
2444 EmitComment();
2445
2446 OutStreamer->emitIntValueInHexWithPadding(
2447 (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2448
2449 // Set the 4th byte of the mandatory field.
2450 FirstHalfOfMandatoryField |= TracebackTable::IsFunctionNamePresentMask;
2451
2452 const PPCRegisterInfo *RegInfo = Subtarget->getRegisterInfo();
2453 Register FrameReg = RegInfo->getFrameRegister(*MF);
2454 if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))
2455 FirstHalfOfMandatoryField |= TracebackTable::IsAllocaUsedMask;
2456
2457 const SmallVectorImpl<Register> &MustSaveCRs = FI->getMustSaveCRs();
2458 if (!MustSaveCRs.empty())
2459 FirstHalfOfMandatoryField |= TracebackTable::IsCRSavedMask;
2460
2461 if (FI->mustSaveLR())
2462 FirstHalfOfMandatoryField |= TracebackTable::IsLRSavedMask;
2463
2464 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsInterruptHandler);
2465 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);
2466 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsAllocaUsed);
2467 EmitComment();
2468 GENVALUECOMMENT("OnConditionDirective", FirstHalfOfMandatoryField,
2469 OnConditionDirective);
2470 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsCRSaved);
2471 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsLRSaved);
2472 EmitComment();
2473 OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),
2474 1);
2475
2476 // Set the 5th byte of mandatory field.
2477 uint32_t SecondHalfOfMandatoryField = 0;
2478
2479 SecondHalfOfMandatoryField |= MF->getFrameInfo().getStackSize()
2481 : 0;
2482
2483 uint32_t FPRSaved = 0;
2484 for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) {
2485 if (MRI.isPhysRegModified(Reg)) {
2486 FPRSaved = PPC::F31 - Reg + 1;
2487 break;
2488 }
2489 }
2490 SecondHalfOfMandatoryField |= (FPRSaved << TracebackTable::FPRSavedShift) &
2492 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, IsBackChainStored);
2493 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, IsFixup);
2494 GENVALUECOMMENT(", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);
2495 EmitComment();
2496 OutStreamer->emitIntValueInHexWithPadding(
2497 (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);
2498
2499 // Set the 6th byte of mandatory field.
2500
2501 // Check whether has Vector Instruction,We only treat instructions uses vector
2502 // register as vector instructions.
2503 bool HasVectorInst = false;
2504 for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)
2505 if (MRI.isPhysRegUsed(Reg, /* SkipRegMaskTest */ true)) {
2506 // Has VMX instruction.
2507 HasVectorInst = true;
2508 break;
2509 }
2510
2511 if (FI->hasVectorParms() || HasVectorInst)
2512 SecondHalfOfMandatoryField |= TracebackTable::HasVectorInfoMask;
2513
2514 uint16_t NumOfVRSaved = getNumberOfVRSaved();
2515 bool ShouldEmitEHBlock =
2517
2518 if (ShouldEmitEHBlock)
2519 SecondHalfOfMandatoryField |= TracebackTable::HasExtensionTableMask;
2520
2521 uint32_t GPRSaved = 0;
2522
2523 // X13 is reserved under 64-bit environment.
2524 unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;
2525 unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;
2526
2527 for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) {
2528 if (MRI.isPhysRegModified(Reg)) {
2529 GPRSaved = GPREnd - Reg + 1;
2530 break;
2531 }
2532 }
2533
2534 SecondHalfOfMandatoryField |= (GPRSaved << TracebackTable::GPRSavedShift) &
2536
2537 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, HasExtensionTable);
2538 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasVectorInfo);
2539 GENVALUECOMMENT(", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);
2540 EmitComment();
2541 OutStreamer->emitIntValueInHexWithPadding(
2542 (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);
2543
2544 // Set the 7th byte of mandatory field.
2545 uint32_t NumberOfFixedParms = FI->getFixedParmsNum();
2546 SecondHalfOfMandatoryField |=
2547 (NumberOfFixedParms << TracebackTable::NumberOfFixedParmsShift) &
2549 GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,
2550 NumberOfFixedParms);
2551 EmitComment();
2552 OutStreamer->emitIntValueInHexWithPadding(
2553 (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2554
2555 // Set the 8th byte of mandatory field.
2556
2557 // Always set parameter on stack.
2558 SecondHalfOfMandatoryField |= TracebackTable::HasParmsOnStackMask;
2559
2560 uint32_t NumberOfFPParms = FI->getFloatingPointParmsNum();
2561 SecondHalfOfMandatoryField |=
2564
2565 GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,
2566 NumberOfFloatingPointParms);
2567 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasParmsOnStack);
2568 EmitComment();
2569 OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,
2570 1);
2571
2572 // Generate the optional fields of traceback table.
2573
2574 // Parameter type.
2575 if (NumberOfFixedParms || NumberOfFPParms) {
2576 uint32_t ParmsTypeValue = FI->getParmsType();
2577
2578 Expected<SmallString<32>> ParmsType =
2579 FI->hasVectorParms()
2581 ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,
2582 FI->getVectorParmsNum())
2583 : XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms,
2584 NumberOfFPParms);
2585
2586 assert(ParmsType && toString(ParmsType.takeError()).c_str());
2587 if (ParmsType) {
2588 CommentOS << "Parameter type = " << ParmsType.get();
2589 EmitComment();
2590 }
2591 OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,
2592 sizeof(ParmsTypeValue));
2593 }
2594 // Traceback table offset.
2595 OutStreamer->AddComment("Function size");
2596 if (FirstHalfOfMandatoryField & TracebackTable::HasTraceBackTableOffsetMask) {
2597 MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(
2598 &(MF->getFunction()), TM);
2599 OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);
2600 }
2601
2602 // Since we unset the Int_Handler.
2603 if (FirstHalfOfMandatoryField & TracebackTable::IsInterruptHandlerMask)
2604 report_fatal_error("Hand_Mask not implement yet");
2605
2606 if (FirstHalfOfMandatoryField & TracebackTable::HasControlledStorageMask)
2607 report_fatal_error("Ctl_Info not implement yet");
2608
2609 if (FirstHalfOfMandatoryField & TracebackTable::IsFunctionNamePresentMask) {
2610 StringRef Name = MF->getName().substr(0, INT16_MAX);
2611 int16_t NameLength = Name.size();
2612 CommentOS << "Function name len = "
2613 << static_cast<unsigned int>(NameLength);
2614 EmitCommentAndValue(NameLength, 2);
2615 OutStreamer->AddComment("Function Name");
2616 OutStreamer->emitBytes(Name);
2617 }
2618
2619 if (FirstHalfOfMandatoryField & TracebackTable::IsAllocaUsedMask) {
2620 uint8_t AllocReg = XCOFF::AllocRegNo;
2621 OutStreamer->AddComment("AllocaUsed");
2622 OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg));
2623 }
2624
2625 if (SecondHalfOfMandatoryField & TracebackTable::HasVectorInfoMask) {
2626 uint16_t VRData = 0;
2627 if (NumOfVRSaved) {
2628 // Number of VRs saved.
2629 VRData |= (NumOfVRSaved << TracebackTable::NumberOfVRSavedShift) &
2631 // This bit is supposed to set only when the special register
2632 // VRSAVE is saved on stack.
2633 // However, IBM XL compiler sets the bit when any vector registers
2634 // are saved on the stack. We will follow XL's behavior on AIX
2635 // so that we don't get surprise behavior change for C code.
2637 }
2638
2639 // Set has_varargs.
2640 if (FI->getVarArgsFrameIndex())
2642
2643 // Vector parameters number.
2644 unsigned VectorParmsNum = FI->getVectorParmsNum();
2645 VRData |= (VectorParmsNum << TracebackTable::NumberOfVectorParmsShift) &
2647
2648 if (HasVectorInst)
2650
2651 GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved);
2652 GENBOOLCOMMENT(", ", VRData, IsVRSavedOnStack);
2653 GENBOOLCOMMENT(", ", VRData, HasVarArgs);
2654 EmitComment();
2655 OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);
2656
2657 GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms);
2658 GENBOOLCOMMENT(", ", VRData, HasVMXInstruction);
2659 EmitComment();
2660 OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);
2661
2662 uint32_t VecParmTypeValue = FI->getVecExtParmsType();
2663
2664 Expected<SmallString<32>> VecParmsType =
2665 XCOFF::parseVectorParmsType(VecParmTypeValue, VectorParmsNum);
2666 assert(VecParmsType && toString(VecParmsType.takeError()).c_str());
2667 if (VecParmsType) {
2668 CommentOS << "Vector Parameter type = " << VecParmsType.get();
2669 EmitComment();
2670 }
2671 OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,
2672 sizeof(VecParmTypeValue));
2673 // Padding 2 bytes.
2674 CommentOS << "Padding";
2675 EmitCommentAndValue(0, 2);
2676 }
2677
2678 uint8_t ExtensionTableFlag = 0;
2679 if (SecondHalfOfMandatoryField & TracebackTable::HasExtensionTableMask) {
2680 if (ShouldEmitEHBlock)
2681 ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;
2684 ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;
2685
2686 CommentOS << "ExtensionTableFlag = "
2687 << getExtendedTBTableFlagString(ExtensionTableFlag);
2688 EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag));
2689 }
2690
2691 if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {
2692 auto &Ctx = OutStreamer->getContext();
2693 MCSymbol *EHInfoSym =
2695 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock);
2696 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
2697 getObjFileLowering().getTOCBaseSection())
2698 ->getQualNameSymbol();
2699 const MCExpr *Exp =
2701 MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);
2702
2703 const DataLayout &DL = getDataLayout();
2704 OutStreamer->emitValueToAlignment(Align(4));
2705 OutStreamer->AddComment("EHInfo Table");
2706 OutStreamer->emitValue(Exp, DL.getPointerSize());
2707 }
2708#undef GENBOOLCOMMENT
2709#undef GENVALUECOMMENT
2710}
2711
2713 return GV->hasAppendingLinkage() &&
2715 // TODO: Linker could still eliminate the GV if we just skip
2716 // handling llvm.used array. Skipping them for now until we or the
2717 // AIX OS team come up with a good solution.
2718 .Case("llvm.used", true)
2719 // It's correct to just skip llvm.compiler.used array here.
2720 .Case("llvm.compiler.used", true)
2721 .Default(false);
2722}
2723
2725 return StringSwitch<bool>(GV->getName())
2726 .Cases({"llvm.global_ctors", "llvm.global_dtors"}, true)
2727 .Default(false);
2728}
2729
2730uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {
2731 if (auto *GA = dyn_cast<GlobalAlias>(C))
2732 return getAliasOffset(GA->getAliasee());
2733 if (auto *CE = dyn_cast<ConstantExpr>(C)) {
2734 const MCExpr *LowC = lowerConstant(CE);
2735 const MCBinaryExpr *CBE = dyn_cast<MCBinaryExpr>(LowC);
2736 if (!CBE)
2737 return 0;
2738 if (CBE->getOpcode() != MCBinaryExpr::Add)
2739 report_fatal_error("Only adding an offset is supported now.");
2740 auto *RHS = dyn_cast<MCConstantExpr>(CBE->getRHS());
2741 if (!RHS)
2742 report_fatal_error("Unable to get the offset of alias.");
2743 return RHS->getValue();
2744 }
2745 return 0;
2746}
2747
2748static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV) {
2749 // TODO: These asserts should be updated as more support for the toc data
2750 // transformation is added (struct support, etc.).
2751 assert(
2752 PointerSize >= GV->getAlign().valueOrOne().value() &&
2753 "GlobalVariables with an alignment requirement stricter than TOC entry "
2754 "size not supported by the toc data transformation.");
2755
2756 Type *GVType = GV->getValueType();
2757 assert(GVType->isSized() && "A GlobalVariable's size must be known to be "
2758 "supported by the toc data transformation.");
2759 if (GV->getDataLayout().getTypeSizeInBits(GVType) >
2760 PointerSize * 8)
2762 "A GlobalVariable with size larger than a TOC entry is not currently "
2763 "supported by the toc data transformation.");
2764 if (GV->hasPrivateLinkage())
2765 report_fatal_error("A GlobalVariable with private linkage is not "
2766 "currently supported by the toc data transformation.");
2767}
2768
2769void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
2770 // Special LLVM global arrays have been handled at the initialization.
2772 return;
2773
2774 // Ignore non-emitted data.
2775 if (GV->getSection() == "llvm.metadata")
2776 return;
2777
2778 // If the Global Variable has the toc-data attribute, it needs to be emitted
2779 // when we emit the .toc section.
2780 if (GV->hasAttribute("toc-data")) {
2781 unsigned PointerSize = GV->getDataLayout().getPointerSize();
2782 tocDataChecks(PointerSize, GV);
2783 TOCDataGlobalVars.push_back(GV);
2784 return;
2785 }
2786
2787 emitGlobalVariableHelper(GV);
2788}
2789
2790void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
2791 assert(!GV->getName().starts_with("llvm.") &&
2792 "Unhandled intrinsic global variable.");
2793
2794 if (GV->hasComdat())
2795 report_fatal_error("COMDAT not yet supported by AIX.");
2796
2797 auto *GVSym = static_cast<MCSymbolXCOFF *>(getSymbol(GV));
2798
2799 if (GV->isDeclarationForLinker()) {
2800 emitLinkage(GV, GVSym);
2801 return;
2802 }
2803
2804 SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
2805 if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly() &&
2806 !GVKind.isThreadLocal()) // Checks for both ThreadData and ThreadBSS.
2807 report_fatal_error("Encountered a global variable kind that is "
2808 "not supported yet.");
2809
2810 // Print GV in verbose mode
2811 if (isVerbose()) {
2812 if (GV->hasInitializer()) {
2813 GV->printAsOperand(OutStreamer->getCommentOS(),
2814 /*PrintType=*/false, GV->getParent());
2815 OutStreamer->getCommentOS() << '\n';
2816 }
2817 }
2818
2819 auto *Csect = static_cast<MCSectionXCOFF *>(
2820 getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
2821
2822 // Switch to the containing csect.
2823 OutStreamer->switchSection(Csect);
2824
2825 if (GV->hasMetadata(LLVMContext::MD_implicit_ref)) {
2826 emitRefMetadata(GV);
2827 }
2828
2829 const DataLayout &DL = GV->getDataLayout();
2830
2831 // Handle common and zero-initialized local symbols.
2832 if (GV->hasCommonLinkage() || GVKind.isBSSLocal() ||
2833 GVKind.isThreadBSSLocal()) {
2834 Align Alignment = GV->getAlign().value_or(DL.getPreferredAlign(GV));
2835 uint64_t Size = GV->getGlobalSize(DL);
2836 GVSym->setStorageClass(
2838
2839 if (GVKind.isBSSLocal() && Csect->getMappingClass() == XCOFF::XMC_TD) {
2840 OutStreamer->emitZeros(Size);
2841 } else if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal()) {
2842 assert(Csect->getMappingClass() != XCOFF::XMC_TD &&
2843 "BSS local toc-data already handled and TLS variables "
2844 "incompatible with XMC_TD");
2845 OutStreamer->emitXCOFFLocalCommonSymbol(
2846 OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,
2847 GVSym, Alignment);
2848 } else {
2849 OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
2850 }
2851 return;
2852 }
2853
2854 MCSymbol *EmittedInitSym = GVSym;
2855
2856 // Emit linkage for the global variable and its aliases.
2857 emitLinkage(GV, EmittedInitSym);
2858 for (const GlobalAlias *GA : GOAliasMap[GV])
2859 emitLinkage(GA, getSymbol(GA));
2860
2861 emitAlignment(getGVAlignment(GV, DL), GV);
2862
2863 // When -fdata-sections is enabled, every GlobalVariable will
2864 // be put into its own csect; therefore, label is not necessary here.
2865 if (!TM.getDataSections() || GV->hasSection()) {
2866 if (Csect->getMappingClass() != XCOFF::XMC_TD)
2867 OutStreamer->emitLabel(EmittedInitSym);
2868 }
2869
2870 // No alias to emit.
2871 if (!GOAliasMap[GV].size()) {
2872 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());
2873 return;
2874 }
2875
2876 // Aliases with the same offset should be aligned. Record the list of aliases
2877 // associated with the offset.
2878 AliasMapTy AliasList;
2879 for (const GlobalAlias *GA : GOAliasMap[GV])
2880 AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);
2881
2882 // Emit alias label and element value for global variable.
2883 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),
2884 &AliasList);
2885}
2886
2887void PPCAIXAsmPrinter::emitFunctionDescriptor() {
2888 const DataLayout &DL = getDataLayout();
2889 const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;
2890
2891 MCSectionSubPair Current = OutStreamer->getCurrentSection();
2892 // Emit function descriptor.
2893 OutStreamer->switchSection(
2894 static_cast<MCSymbolXCOFF *>(CurrentFnDescSym)->getRepresentedCsect());
2895
2896 // Emit aliasing label for function descriptor csect.
2897 // An Ifunc doesn't have a corresponding machine function.
2898 if (MF)
2899 for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])
2900 OutStreamer->emitLabel(getSymbol(Alias));
2901
2902 // Emit function entry point address.
2903 OutStreamer->emitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),
2904 PointerSize);
2905 // Emit TOC base address.
2906 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
2907 getObjFileLowering().getTOCBaseSection())
2908 ->getQualNameSymbol();
2909 OutStreamer->emitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),
2910 PointerSize);
2911 // Emit a null environment pointer.
2912 OutStreamer->emitIntValue(0, PointerSize);
2913
2914 OutStreamer->switchSection(Current.first, Current.second);
2915}
2916
2917void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
2918 // For functions without user defined section, it's not necessary to emit the
2919 // label when we have individual function in its own csect.
2920 if (!TM.getFunctionSections() || (MF && MF->getFunction().hasSection()))
2921 PPCAsmPrinter::emitFunctionEntryLabel();
2922
2923 // an ifunc does not have an associated MachineFunction
2924 if (!MF)
2925 return;
2926
2927 const Function *F = &MF->getFunction();
2928 // Emit aliasing label for function entry point label.
2929 for (const GlobalAlias *Alias : GOAliasMap[F])
2930 OutStreamer->emitLabel(
2931 getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));
2932
2933 if (F->hasMetadata(LLVMContext::MD_implicit_ref)) {
2934 emitRefMetadata(F);
2935 }
2936}
2937
2938void PPCAIXAsmPrinter::emitPGORefs(Module &M) {
2939 if (!OutContext.hasXCOFFSection(
2940 "__llvm_prf_cnts",
2941 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
2942 return;
2943
2944 // When inside a csect `foo`, a .ref directive referring to a csect `bar`
2945 // translates into a relocation entry from `foo` to` bar`. The referring
2946 // csect, `foo`, is identified by its address. If multiple csects have the
2947 // same address (because one or more of them are zero-length), the referring
2948 // csect cannot be determined. Hence, we don't generate the .ref directives
2949 // if `__llvm_prf_cnts` is an empty section.
2950 bool HasNonZeroLengthPrfCntsSection = false;
2951 const DataLayout &DL = M.getDataLayout();
2952 for (GlobalVariable &GV : M.globals())
2953 if (GV.hasSection() && GV.getSection() == "__llvm_prf_cnts" &&
2954 GV.getGlobalSize(DL) > 0) {
2955 HasNonZeroLengthPrfCntsSection = true;
2956 break;
2957 }
2958
2959 if (HasNonZeroLengthPrfCntsSection) {
2960 MCSection *CntsSection = OutContext.getXCOFFSection(
2961 "__llvm_prf_cnts", SectionKind::getData(),
2962 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),
2963 /*MultiSymbolsAllowed*/ true);
2964
2965 OutStreamer->switchSection(CntsSection);
2966 if (OutContext.hasXCOFFSection(
2967 "__llvm_prf_data",
2968 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
2969 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_data[RW]");
2970 OutStreamer->emitXCOFFRefDirective(S);
2971 }
2972 if (OutContext.hasXCOFFSection(
2973 "__llvm_prf_names",
2974 XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD))) {
2975 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_names[RO]");
2976 OutStreamer->emitXCOFFRefDirective(S);
2977 }
2978 if (OutContext.hasXCOFFSection(
2979 "__llvm_prf_vnds",
2980 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
2981 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_vnds[RW]");
2982 OutStreamer->emitXCOFFRefDirective(S);
2983 }
2984 }
2985}
2986
2987void PPCAIXAsmPrinter::emitGCOVRefs() {
2988 if (!OutContext.hasXCOFFSection(
2989 "__llvm_gcov_ctr_section",
2990 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
2991 return;
2992
2993 MCSection *CtrSection = OutContext.getXCOFFSection(
2994 "__llvm_gcov_ctr_section", SectionKind::getData(),
2995 XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),
2996 /*MultiSymbolsAllowed*/ true);
2997
2998 OutStreamer->switchSection(CtrSection);
2999 const XCOFF::StorageMappingClass MappingClass =
3000 TM.Options.XCOFFReadOnlyPointers ? XCOFF::XMC_RO : XCOFF::XMC_RW;
3001 if (OutContext.hasXCOFFSection(
3002 "__llvm_covinit",
3003 XCOFF::CsectProperties(MappingClass, XCOFF::XTY_SD))) {
3004 const char *SymbolStr = TM.Options.XCOFFReadOnlyPointers
3005 ? "__llvm_covinit[RO]"
3006 : "__llvm_covinit[RW]";
3007 MCSymbol *S = OutContext.getOrCreateSymbol(SymbolStr);
3008 OutStreamer->emitXCOFFRefDirective(S);
3009 }
3010}
3011
3012void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
3013 // If there are no functions and there are no toc-data definitions in this
3014 // module, we will never need to reference the TOC base.
3015 if (M.empty() && TOCDataGlobalVars.empty())
3016 return;
3017
3018 emitPGORefs(M);
3019 emitGCOVRefs();
3020
3021 // Switch to section to emit TOC base.
3022 OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
3023
3024 PPCTargetStreamer *TS =
3025 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
3026
3027 for (auto &I : TOC) {
3028 MCSectionXCOFF *TCEntry;
3029 // Setup the csect for the current TC entry. If the variant kind is
3030 // VK_AIX_TLSGDM the entry represents the region handle, we create a
3031 // new symbol to prefix the name with a dot.
3032 // If TLS model opt is turned on, create a new symbol to prefix the name
3033 // with a dot.
3034 if (I.first.second == PPC::S_AIX_TLSGDM ||
3035 (Subtarget->hasAIXShLibTLSModelOpt() &&
3036 I.first.second == PPC::S_AIX_TLSLD)) {
3037 SmallString<128> Name;
3038 StringRef Prefix = ".";
3039 Name += Prefix;
3040 Name += static_cast<const MCSymbolXCOFF *>(I.first.first)
3041 ->getSymbolTableName();
3042 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
3043 TCEntry = static_cast<MCSectionXCOFF *>(
3044 getObjFileLowering().getSectionForTOCEntry(S, TM));
3045 } else {
3046 TCEntry = static_cast<MCSectionXCOFF *>(
3047 getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
3048 }
3049 OutStreamer->switchSection(TCEntry);
3050
3051 OutStreamer->emitLabel(I.second);
3052 TS->emitTCEntry(*I.first.first, I.first.second);
3053 }
3054
3055 // Traverse the list of global variables twice, emitting all of the
3056 // non-common global variables before the common ones, as emitting a
3057 // .comm directive changes the scope from .toc to the common symbol.
3058 for (const auto *GV : TOCDataGlobalVars) {
3059 if (!GV->hasCommonLinkage())
3060 emitGlobalVariableHelper(GV);
3061 }
3062 for (const auto *GV : TOCDataGlobalVars) {
3063 if (GV->hasCommonLinkage())
3064 emitGlobalVariableHelper(GV);
3065 }
3066}
3067
3068bool PPCAIXAsmPrinter::doInitialization(Module &M) {
3069 const bool Result = PPCAsmPrinter::doInitialization(M);
3070
3071 // Emit the .machine directive on AIX.
3072 const Triple &Target = TM.getTargetTriple();
3074 // Walk through the "target-cpu" attribute of functions and use the newest
3075 // level as the CPU of the module.
3076 for (auto &F : M) {
3077 XCOFF::CFileCpuId FunCpuId =
3078 XCOFF::getCpuID(TM.getSubtargetImpl(F)->getCPU());
3079 if (FunCpuId > TargetCpuId)
3080 TargetCpuId = FunCpuId;
3081 }
3082 // If there is no "target-cpu" attribute within the functions, take the
3083 // "-mcpu" value. If both are omitted, use getNormalizedPPCTargetCPU() to
3084 // determine the default CPU.
3085 if (!TargetCpuId) {
3086 StringRef TargetCPU = TM.getTargetCPU();
3087 TargetCpuId = XCOFF::getCpuID(
3088 TargetCPU.empty() ? PPC::getNormalizedPPCTargetCPU(Target) : TargetCPU);
3089 }
3090
3091 PPCTargetStreamer *TS =
3092 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
3093 TS->emitMachine(XCOFF::getTCPUString(TargetCpuId));
3094
3095 auto setCsectAlignment = [this](const GlobalObject *GO) {
3096 // Declarations have 0 alignment which is set by default.
3097 if (GO->isDeclarationForLinker())
3098 return;
3099
3100 SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);
3101 auto *Csect = static_cast<MCSectionXCOFF *>(
3102 getObjFileLowering().SectionForGlobal(GO, GOKind, TM));
3103
3104 Align GOAlign = getGVAlignment(GO, GO->getDataLayout());
3105 Csect->ensureMinAlignment(GOAlign);
3106 };
3107
3108 // For all TLS variables, calculate their corresponding addresses and store
3109 // them into TLSVarsToAddressMapping, which will be used to determine whether
3110 // or not local-exec TLS variables require special assembly printing.
3111 uint64_t TLSVarAddress = 0;
3112 auto DL = M.getDataLayout();
3113 for (const auto &G : M.globals()) {
3114 if (G.isThreadLocal() && !G.isDeclaration()) {
3115 TLSVarAddress = alignTo(TLSVarAddress, getGVAlignment(&G, DL));
3116 TLSVarsToAddressMapping[&G] = TLSVarAddress;
3117 TLSVarAddress += G.getGlobalSize(DL);
3118 }
3119 }
3120
3121 // We need to know, up front, the alignment of csects for the assembly path,
3122 // because once a .csect directive gets emitted, we could not change the
3123 // alignment value on it.
3124 for (const auto &G : M.globals()) {
3126 continue;
3127
3129 // Generate a format indicator and a unique module id to be a part of
3130 // the sinit and sterm function names.
3131 if (FormatIndicatorAndUniqueModId.empty()) {
3132 std::string UniqueModuleId = getUniqueModuleId(&M);
3133 if (UniqueModuleId != "")
3134 // TODO: Use source file full path to generate the unique module id
3135 // and add a format indicator as a part of function name in case we
3136 // will support more than one format.
3137 FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1);
3138 else {
3139 // Use threadId, Pid, and current time as the unique module id when we
3140 // cannot generate one based on a module's strong external symbols.
3141 auto CurTime =
3142 std::chrono::duration_cast<std::chrono::nanoseconds>(
3143 std::chrono::steady_clock::now().time_since_epoch())
3144 .count();
3145 FormatIndicatorAndUniqueModId =
3146 "clangPidTidTime_" + llvm::itostr(sys::Process::getProcessId()) +
3147 "_" + llvm::itostr(llvm::get_threadid()) + "_" +
3148 llvm::itostr(CurTime);
3149 }
3150 }
3151
3152 emitSpecialLLVMGlobal(&G);
3153 continue;
3154 }
3155
3156 setCsectAlignment(&G);
3157 std::optional<CodeModel::Model> OptionalCodeModel = G.getCodeModel();
3158 if (OptionalCodeModel)
3159 setOptionalCodeModel(static_cast<MCSymbolXCOFF *>(getSymbol(&G)),
3160 *OptionalCodeModel);
3161 }
3162
3163 for (const auto &F : M)
3164 setCsectAlignment(&F);
3165
3166 // Construct an aliasing list for each GlobalObject.
3167 for (const auto &Alias : M.aliases()) {
3168 const GlobalObject *Aliasee = Alias.getAliaseeObject();
3169 if (!Aliasee)
3171 "alias without a base object is not yet supported on AIX");
3172
3173 if (Aliasee->hasCommonLinkage()) {
3174 report_fatal_error("Aliases to common variables are not allowed on AIX:"
3175 "\n\tAlias attribute for " +
3176 Alias.getName() + " is invalid because " +
3177 Aliasee->getName() + " is common.",
3178 false);
3179 }
3180
3181 const GlobalVariable *GVar =
3182 dyn_cast_or_null<GlobalVariable>(Alias.getAliaseeObject());
3183 if (GVar) {
3184 std::optional<CodeModel::Model> OptionalCodeModel = GVar->getCodeModel();
3185 if (OptionalCodeModel)
3186 setOptionalCodeModel(static_cast<MCSymbolXCOFF *>(getSymbol(&Alias)),
3187 *OptionalCodeModel);
3188 }
3189
3190 GOAliasMap[Aliasee].push_back(&Alias);
3191 }
3192
3193 return Result;
3194}
3195
3196void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {
3197 switch (MI->getOpcode()) {
3198 default:
3199 break;
3200 case PPC::TW:
3201 case PPC::TWI:
3202 case PPC::TD:
3203 case PPC::TDI: {
3204 if (MI->getNumOperands() < 5)
3205 break;
3206 const MachineOperand &LangMO = MI->getOperand(3);
3207 const MachineOperand &ReasonMO = MI->getOperand(4);
3208 if (!LangMO.isImm() || !ReasonMO.isImm())
3209 break;
3210 MCSymbol *TempSym = OutContext.createNamedTempSymbol();
3211 OutStreamer->emitLabel(TempSym);
3212 OutStreamer->emitXCOFFExceptDirective(
3213 CurrentFnSym, TempSym, LangMO.getImm(), ReasonMO.getImm(),
3214 Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 8
3215 : MI->getMF()->getInstructionCount() * 4,
3216 hasDebugInfo());
3217 break;
3218 }
3219 case PPC::GETtlsMOD32AIX:
3220 case PPC::GETtlsMOD64AIX:
3221 case PPC::GETtlsTpointer32AIX:
3222 case PPC::GETtlsADDR64AIX:
3223 case PPC::GETtlsADDR32AIX: {
3224 // A reference to .__tls_get_mod/.__tls_get_addr/.__get_tpointer is unknown
3225 // to the assembler so we need to emit an external symbol reference.
3226 MCSymbol *TlsGetAddr =
3227 createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode());
3228 ExtSymSDNodeSymbols.insert(TlsGetAddr);
3229 break;
3230 }
3231 case PPC::BL8:
3232 case PPC::BL:
3233 case PPC::BL8_NOP:
3234 case PPC::BL_NOP:
3235 case PPC::BL_LWZinto_toc:
3236 case PPC::BL_LWZinto_toc_RM:
3237 case PPC::BL8_LDinto_toc:
3238 case PPC::BL8_LDinto_toc_RM: {
3239 const MachineOperand &MO = MI->getOperand(0);
3240 if (MO.isSymbol()) {
3241 auto *S = static_cast<MCSymbolXCOFF *>(
3242 OutContext.getOrCreateSymbol(MO.getSymbolName()));
3243 ExtSymSDNodeSymbols.insert(S);
3244 }
3245 } break;
3246 case PPC::BL_TLS:
3247 case PPC::BL8_TLS:
3248 case PPC::BL8_TLS_:
3249 case PPC::BL8_NOP_TLS:
3250 report_fatal_error("TLS call not yet implemented");
3251 case PPC::TAILB:
3252 case PPC::TAILB8:
3253 case PPC::TAILBA:
3254 case PPC::TAILBA8:
3255 case PPC::TAILBCTR:
3256 case PPC::TAILBCTR8:
3257 if (MI->getOperand(0).isSymbol())
3258 report_fatal_error("Tail call for extern symbol not yet supported.");
3259 break;
3260 case PPC::DST:
3261 case PPC::DST64:
3262 case PPC::DSTT:
3263 case PPC::DSTT64:
3264 case PPC::DSTST:
3265 case PPC::DSTST64:
3266 case PPC::DSTSTT:
3267 case PPC::DSTSTT64:
3268 EmitToStreamer(
3269 *OutStreamer,
3270 MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));
3271 return;
3272 }
3273 return PPCAsmPrinter::emitInstruction(MI);
3274}
3275
3276bool PPCAIXAsmPrinter::doFinalization(Module &M) {
3277 for (MCSymbol *Sym : ExtSymSDNodeSymbols)
3278 OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern);
3279 return PPCAsmPrinter::doFinalization(M);
3280}
3281
3282static unsigned mapToSinitPriority(int P) {
3283 if (P < 0 || P > 65535)
3284 report_fatal_error("invalid init priority");
3285
3286 if (P <= 20)
3287 return P;
3288
3289 if (P < 81)
3290 return 20 + (P - 20) * 16;
3291
3292 if (P <= 1124)
3293 return 1004 + (P - 81);
3294
3295 if (P < 64512)
3296 return 2047 + (P - 1124) * 33878;
3297
3298 return 2147482625u + (P - 64512);
3299}
3300
3301static std::string convertToSinitPriority(int Priority) {
3302 // This helper function converts clang init priority to values used in sinit
3303 // and sterm functions.
3304 //
3305 // The conversion strategies are:
3306 // We map the reserved clang/gnu priority range [0, 100] into the sinit/sterm
3307 // reserved priority range [0, 1023] by
3308 // - directly mapping the first 21 and the last 20 elements of the ranges
3309 // - linear interpolating the intermediate values with a step size of 16.
3310 //
3311 // We map the non reserved clang/gnu priority range of [101, 65535] into the
3312 // sinit/sterm priority range [1024, 2147483648] by:
3313 // - directly mapping the first and the last 1024 elements of the ranges
3314 // - linear interpolating the intermediate values with a step size of 33878.
3315 unsigned int P = mapToSinitPriority(Priority);
3316
3317 std::string PrioritySuffix;
3318 llvm::raw_string_ostream os(PrioritySuffix);
3319 os << llvm::format_hex_no_prefix(P, 8);
3320 return PrioritySuffix;
3321}
3322
3323void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL,
3324 const Constant *List, bool IsCtor) {
3325 SmallVector<Structor, 8> Structors;
3326 preprocessXXStructorList(DL, List, Structors);
3327 if (Structors.empty())
3328 return;
3329
3330 unsigned Index = 0;
3331 for (Structor &S : Structors) {
3332 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(S.Func))
3333 S.Func = CE->getOperand(0);
3334
3337 (IsCtor ? llvm::Twine("__sinit") : llvm::Twine("__sterm")) +
3338 llvm::Twine(convertToSinitPriority(S.Priority)) +
3339 llvm::Twine("_", FormatIndicatorAndUniqueModId) +
3340 llvm::Twine("_", llvm::utostr(Index++)),
3341 cast<Function>(S.Func));
3342 }
3343}
3344
3345void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV,
3346 unsigned Encoding) {
3347 if (GV) {
3348 TOCEntryType GlobalType = TOCType_GlobalInternal;
3353 GlobalType = TOCType_GlobalExternal;
3354 MCSymbol *TypeInfoSym = TM.getSymbol(GV);
3355 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType);
3356 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
3357 getObjFileLowering().getTOCBaseSection())
3358 ->getQualNameSymbol();
3359 auto &Ctx = OutStreamer->getContext();
3360 const MCExpr *Exp =
3362 MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx);
3363 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));
3364 } else
3365 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));
3366}
3367
3368void PPCAIXAsmPrinter::emitRefMetadata(const GlobalObject *GO) {
3370 GO->getMetadata(LLVMContext::MD_implicit_ref, MDs);
3371 assert(MDs.size() && "Expected !implicit.ref metadata nodes");
3372
3373 for (const MDNode *MD : MDs) {
3374 const ValueAsMetadata *VAM = cast<ValueAsMetadata>(MD->getOperand(0).get());
3375 const GlobalValue *GV = cast<GlobalValue>(VAM->getValue());
3376 MCSymbol *Referenced =
3377 isa<Function>(GV)
3378 ? getObjFileLowering().getFunctionEntryPointSymbol(GV, TM)
3379 : TM.getSymbol(GV);
3380 OutStreamer->emitXCOFFRefDirective(Referenced);
3381 }
3382}
3383
3384// Return a pass that prints the PPC assembly code for a MachineFunction to the
3385// given output stream.
3386static AsmPrinter *
3388 std::unique_ptr<MCStreamer> &&Streamer) {
3389 if (tm.getTargetTriple().isOSAIX())
3390 return new PPCAIXAsmPrinter(tm, std::move(Streamer));
3391
3392 return new PPCLinuxAsmPrinter(tm, std::move(Streamer));
3393}
3394
3395void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {
3396 const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");
3397 if (!NMD || !NMD->getNumOperands())
3398 return;
3399
3400 std::string S;
3401 raw_string_ostream RSOS(S);
3402 for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
3403 const MDNode *N = NMD->getOperand(i);
3404 assert(N->getNumOperands() == 1 &&
3405 "llvm.commandline metadata entry can have only one operand");
3406 const MDString *MDS = cast<MDString>(N->getOperand(0));
3407 // Add "@(#)" to support retrieving the command line information with the
3408 // AIX "what" command
3409 RSOS << "@(#)opt " << MDS->getString() << "\n";
3410 RSOS.write('\0');
3411 }
3412 OutStreamer->emitXCOFFCInfoSym(".GCC.command.line", RSOS.str());
3413}
3414
3416 enum class IsLocal {
3417 Unknown, // Structure of the llvm::Value is not one of the recognizable
3418 // structures, and so it's unknown if the llvm::Value is the
3419 // address of a local function at runtime.
3420 True, // We can statically prove that all runtime values of the
3421 // llvm::Value is an address of a local function.
3422 False // We can statically prove that one of the runtime values of the
3423 // llvm::Value is the address of a non-local function; it could be
3424 // the case that at runtime the non-local function is never
3425 // selected but we don't care.
3426 };
3427 auto Combine = [](IsLocal LHS, IsLocal RHS) -> IsLocal {
3428 if (LHS == IsLocal::False || RHS == IsLocal::False)
3429 return IsLocal::False;
3430 if (LHS == IsLocal::True && RHS == IsLocal::True)
3431 return IsLocal::True;
3432 return IsLocal::Unknown;
3433 };
3434
3435 // Query if the given function is local to the load module.
3436 auto IsLocalFunc = [](const Function *F) -> IsLocal {
3437 bool Result = F->isDSOLocal();
3438 LLVM_DEBUG(dbgs() << F->getName() << " is "
3439 << (Result ? "dso_local\n" : "not dso_local\n"));
3440 return Result ? IsLocal::True : IsLocal::False;
3441 };
3442
3443 // Recursive walker that visits certain patterns that make up the given Value,
3444 // and returns
3445 // - false if at least one non-local function was seen,
3446 // - otherwise, return unknown if some unrecognizable pattern was seen,
3447 // - otherwise, return true (which means only recognizable patterns were seen
3448 // and all possible values are local functions).
3449 std::function<IsLocal(const Value *)> ValueIsALocalFunc =
3450 [&IsLocalFunc, &Combine, &ValueIsALocalFunc](const Value *V) -> IsLocal {
3451 if (auto *F = dyn_cast<Function>(V))
3452 return IsLocalFunc(F);
3453 if (!isa<Instruction>(V))
3454 return IsLocal::Unknown;
3455
3456 auto *I = cast<Instruction>(V);
3457 // return isP9 ? foo_p9 : foo_default;
3458 if (auto *SI = dyn_cast<SelectInst>(I))
3459 return Combine(ValueIsALocalFunc(SI->getTrueValue()),
3460 ValueIsALocalFunc(SI->getFalseValue()));
3461 else if (auto *PN = dyn_cast<PHINode>(I)) {
3462 IsLocal Res = IsLocal::True;
3463 for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
3464 Res = Combine(Res, ValueIsALocalFunc(PN->getIncomingValue(i)));
3465 if (Res == IsLocal::False)
3466 return Res;
3467 }
3468 return Res;
3469 }
3470 // clang-format off
3471 // @switch.table.resolve_foo = private unnamed_addr constant [3 x ptr] [ptr @foo_static, ptr @foo_hidden, ptr @foo_protected]
3472 // %switch.gep = getelementptr inbounds nuw ptr, ptr @switch.table, i64 %2
3473 // V = load ptr, ptr %switch.gep,
3474 // clang-format on
3475 else if (auto *Op = getPointerOperand(I)) {
3476 while (isa<GEPOperator>(Op))
3477 Op = cast<GEPOperator>(Op)->getPointerOperand();
3478
3479 if (!isa<GlobalVariable>(Op))
3480 return IsLocal::Unknown;
3481 auto *GV = dyn_cast<GlobalVariable>(Op);
3482 if (!GV->hasInitializer() || !isa<ConstantArray>(GV->getInitializer()))
3483 return IsLocal::Unknown;
3484 auto *Init = cast<ConstantArray>(GV->getInitializer());
3485 IsLocal Res = IsLocal::True;
3486 for (unsigned Idx = 0, End = Init->getNumOperands(); Idx != End; ++Idx) {
3487 Res = Combine(Res, ValueIsALocalFunc(Init->getOperand(Idx)));
3488 if (Res == IsLocal::False)
3489 return Res;
3490 }
3491 return Res;
3492 }
3493 return IsLocal::Unknown;
3494 };
3495
3496 auto *Resolver = GI.getResolverFunction();
3497 // If the resolver is preemptible then we cannot rely on its implementation.
3498 if (IsLocalFunc(Resolver) == IsLocal::False && IFuncLocalIfProven)
3499 return true;
3500
3501 // If one of the return values of the resolver function is not a
3502 // local function, then we have to conservatively do a TOC save/restore.
3503 IsLocal Res = IsLocal::True;
3504 for (auto &BB : *Resolver) {
3505 if (!isa<ReturnInst>(BB.getTerminator()))
3506 continue;
3507 auto *Ret = cast<ReturnInst>(BB.getTerminator());
3508 Value *RV = Ret->getReturnValue();
3509 assert(RV);
3510 Res = Combine(Res, ValueIsALocalFunc(RV));
3511 if (Res == IsLocal::False)
3512 break;
3513 }
3514 // no TOC save/restore needed if either all functions were local or we're
3515 // being optimistic and no preemptible functions were seen.
3516 if (Res == IsLocal::True || (Res == IsLocal::Unknown && !IFuncLocalIfProven))
3517 return false;
3518 return true;
3519}
3520/*
3521 * .csect .foo[PR],5
3522 * .globl foo[DS]
3523 * .globl .foo[PR]
3524 * .lglobl ifunc_sec.foo[RW]
3525 * .align 4
3526 * .csect foo[DS],2
3527 * .vbyte 4, .foo[PR]
3528 * .vbyte 4, TOC[TC0]
3529 * .vbyte 4, 0
3530 * .csect .foo[PR],5
3531 * .ref ifunc_sec.foo[RW]
3532 * lwz 12, L..foo_desc(2) # load foo's descriptor address
3533 * lwz 11, 8(12) # load the env pointer (for non-C/C++ functions)
3534 * lwz 12, 0(12) # load foo.addr
3535 * mtctr 12
3536 * bctr # branch to CR without setting LR so that callee
3537 * # returns to the caller of .foo
3538 * # -- End function
3539 */
3540void PPCAIXAsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
3541 // Set the Subtarget to that of the resolver.
3542 const TargetSubtargetInfo *STI =
3543 TM.getSubtargetImpl(*GI.getResolverFunction());
3544 bool IsPPC64 = static_cast<const PPCSubtarget *>(STI)->isPPC64();
3545
3546 // Create syms and sections that are part of the ifunc implementation:
3547 // - Function descriptor symbol foo[RW]
3548 // - Function entry symbol .foo[PR]
3549 MCSectionXCOFF *FnDescSec = static_cast<MCSectionXCOFF *>(
3550 getObjFileLowering().getSectionForFunctionDescriptor(&GI, TM));
3551 FnDescSec->setAlignment(Align(IsPPC64 ? 8 : 4));
3552
3553 CurrentFnDescSym = FnDescSec->getQualNameSymbol();
3554
3555 CurrentFnSym = getObjFileLowering().getFunctionEntryPointSymbol(&GI, TM);
3556
3557 // Start codegen:
3558 if (TM.getFunctionSections())
3559 OutStreamer->switchSection(
3560 static_cast<MCSymbolXCOFF *>(CurrentFnSym)->getRepresentedCsect());
3561 else
3562 OutStreamer->switchSection(getObjFileLowering().getTextSection());
3563
3564 if (GI.hasMetadata(LLVMContext::MD_implicit_ref))
3565 emitRefMetadata(&GI);
3566
3567 // generate linkage for foo and .foo
3568 emitLinkage(&GI, CurrentFnDescSym);
3569 emitLinkage(&GI, CurrentFnSym);
3570
3571 // .align 4
3572 Align Alignment(STI->getTargetLowering()->getMinFunctionAlignment());
3573 emitAlignment(Alignment, nullptr);
3574
3575 // generate foo's function descriptor
3576 emitFunctionDescriptor();
3577
3578 emitFunctionEntryLabel();
3579
3580 // generate the code for .foo now:
3582 SmallString<128> Msg;
3583 Msg.append("unimplemented: TOC register save/restore needed for ifunc \"");
3584 getNameWithPrefix(Msg, &GI);
3585 Msg.append("\", because couldn't prove all candidates are static or "
3586 "hidden/protected visibility definitions");
3589 else
3590 dbgs() << Msg << "\n";
3591 }
3592
3593 auto FnDescTOCEntryType = getTOCEntryTypeForLinkage(GI.getLinkage());
3594 auto *FnDescTOCEntrySym =
3595 lookUpOrCreateTOCEntry(CurrentFnDescSym, FnDescTOCEntryType);
3596
3597 if (TM.getCodeModel() == CodeModel::Large) {
3598 // addis 12, L..foo_desc@u(2)
3599 // lwz 12, L..foo_desc@l(12)
3600 auto *Exp_U = symbolWithSpecifier(FnDescTOCEntrySym, PPC::S_U);
3601 OutStreamer->emitInstruction(MCInstBuilder(PPC::ADDIS)
3602 .addReg(PPC::X12)
3603 .addReg(PPC::X2)
3604 .addExpr(Exp_U),
3605 *Subtarget);
3606 auto *Exp_L = symbolWithSpecifier(FnDescTOCEntrySym, PPC::S_L);
3607 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::LD : PPC::LWZ)
3608 .addReg(PPC::X12)
3609 .addExpr(Exp_L)
3610 .addReg(PPC::X12),
3611 *Subtarget);
3612 } else {
3613 // lwz 12, L..foo_desc(2)
3614 auto *Exp = MCSymbolRefExpr::create(FnDescTOCEntrySym, OutContext);
3615 // Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
3616 // TODO: do we need to uncomment this?
3617 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::LD : PPC::LWZ)
3618 .addReg(PPC::X12)
3619 .addExpr(Exp)
3620 .addReg(PPC::X2),
3621 *Subtarget);
3622 }
3623 // lwz 11, 8(12)
3624 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::LD : PPC::LWZ)
3625 .addReg(PPC::X11)
3626 .addImm(IsPPC64 ? 16 : 8)
3627 .addReg(PPC::X12),
3628 *Subtarget);
3629 // lwz 12, 0(12)
3630 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::LD : PPC::LWZ)
3631 .addReg(PPC::X12)
3632 .addImm(0)
3633 .addReg(PPC::X12),
3634 *Subtarget);
3635 // mtctr 12
3636 OutStreamer->emitInstruction(
3637 MCInstBuilder(IsPPC64 ? PPC::MTCTR8 : PPC::MTCTR).addReg(PPC::X12),
3638 *Subtarget);
3639 // bctr
3640 OutStreamer->emitInstruction(MCInstBuilder(IsPPC64 ? PPC::BCTR8 : PPC::BCTR),
3641 *Subtarget);
3642}
3643
3644char PPCAIXAsmPrinter::ID = 0;
3645
3646INITIALIZE_PASS(PPCAIXAsmPrinter, "ppc-aix-asm-printer",
3647 "AIX PPC Assembly Printer", false, false)
3648
3649// Force static initialization.
3650extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
3651LLVMInitializePowerPCAsmPrinter() {
3660}
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
DXIL Finalize Linkage
dxil translate DXIL Translate Metadata
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)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:483
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:621
LLVM_ABI const Function * getResolverFunction() const
Definition Globals.cpp:688
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:141
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:569
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:343
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition MCExpr.h:449
Opcode getOpcode() const
Get the kind of this binary expression.
Definition MCExpr.h:443
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:428
@ Add
Addition.
Definition MCExpr.h:302
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:214
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:632
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:151
void append(StringRef RHS)
Append from a StringRef.
Definition SmallString.h:68
StringRef str() const
Explicit conversion to StringRef.
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:591
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:771
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:972
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:318
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ SHF_ALLOC
Definition ELF.h:1251
@ SHF_WRITE
Definition ELF.h:1248
@ SHT_PROGBITS
Definition ELF.h:1150
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:50
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.
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:558
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
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:1668
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)
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.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
FunctionAddr VTableAddr uintptr_t uintptr_t Version
Definition InstrProf.h:334
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:204
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
Target & getThePPC64Target()
LLVM_ABI uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
Definition Threading.cpp:33
DWARFExpression::Operation Op
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
Definition MathExtras.h:554
Target & getThePPC32LETarget()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1916
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:860
#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