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