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