LLVM: lib/Target/PowerPC/PPCAsmPrinter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
78#include
79#include
80#include
81#include
82
83using namespace llvm;
85
86#define DEBUG_TYPE "asmprinter"
87
88STATISTIC(NumTOCEntries, "Number of Total TOC Entries Emitted.");
89STATISTIC(NumTOCConstPool, "Number of Constant Pool TOC Entries.");
91 "Number of Internal Linkage Global TOC Entries.");
93 "Number of External Linkage Global TOC Entries.");
94STATISTIC(NumTOCJumpTable, "Number of Jump Table TOC Entries.");
95STATISTIC(NumTOCThreadLocal, "Number of Thread Local TOC Entries.");
96STATISTIC(NumTOCBlockAddress, "Number of Block Address TOC Entries.");
97STATISTIC(NumTOCEHBlock, "Number of EH Block TOC Entries.");
98
100 "aix-ssp-tb-bit", cl::init(false),
101 cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden);
102
103
104
105
106
107namespace llvm {
108template <>
109struct DenseMapInfo<std::pair<const MCSymbol *, PPCMCExpr::Specifier>> {
110 using TOCKey = std::pair<const MCSymbol *, PPCMCExpr::Specifier>;
111
122};
123}
124
125namespace {
126
127enum {
128
129 Tag_GNU_Power_ABI_FP = 4,
130 Tag_GNU_Power_ABI_Vector = 8,
131 Tag_GNU_Power_ABI_Struct_Return = 12,
132
133
134 Val_GNU_Power_ABI_NoFloat = 0b00,
135 Val_GNU_Power_ABI_HardFloat_DP = 0b01,
136 Val_GNU_Power_ABI_SoftFloat_DP = 0b10,
137 Val_GNU_Power_ABI_HardFloat_SP = 0b11,
138
139 Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,
140 Val_GNU_Power_ABI_LDBL_64 = 0b1000,
141 Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,
142};
143
144class PPCAsmPrinter : public AsmPrinter {
145protected:
146
147
148
149
150
151
152
153 MapVector<std::pair<const MCSymbol *, PPCMCExpr::Specifier>, MCSymbol *> TOC;
154 const PPCSubtarget *Subtarget = nullptr;
155
156
157
158
159 MapVector<const GlobalValue *, uint64_t> TLSVarsToAddressMapping;
160
161public:
162 explicit PPCAsmPrinter(TargetMachine &TM,
163 std::unique_ptr Streamer, char &ID)
164 : AsmPrinter(TM, std::move(Streamer), ID) {}
165
166 StringRef getPassName() const override { return "PowerPC Assembly Printer"; }
167
168 enum TOCEntryType {
169 TOCType_ConstantPool,
170 TOCType_GlobalExternal,
171 TOCType_GlobalInternal,
172 TOCType_JumpTable,
173 TOCType_ThreadLocal,
174 TOCType_BlockAddress,
175 TOCType_EHBlock
176 };
177
178 MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,
180
181 bool doInitialization(Module &M) override {
182 if (!TOC.empty())
183 TOC.clear();
185 }
186
187 const MCExpr *symbolWithSpecifier(const MCSymbol *S,
190
191
192
193
194 void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
195
196 void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
197 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
198 const char *ExtraCode, raw_ostream &O) override;
199 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
200 const char *ExtraCode, raw_ostream &O) override;
201
202 void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);
203 void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI);
205 void EmitAIXTlsCallHelper(const MachineInstr *MI);
206 const MCExpr *getAdjustedFasterLocalExpr(const MachineOperand &MO,
208 bool runOnMachineFunction(MachineFunction &MF) override {
209 Subtarget = &MF.getSubtarget();
211 emitXRayTable();
213 }
214};
215
216
217class PPCLinuxAsmPrinter : public PPCAsmPrinter {
218public:
219 static char ID;
220
221 explicit PPCLinuxAsmPrinter(TargetMachine &TM,
222 std::unique_ptr Streamer)
223 : PPCAsmPrinter(TM, std::move(Streamer), ID) {}
224
225 StringRef getPassName() const override {
226 return "Linux PPC Assembly Printer";
227 }
228
229 void emitGNUAttributes(Module &M);
230
231 void emitStartOfAsmFile(Module &M) override;
232 void emitEndOfAsmFile(Module &) override;
233
234 void emitFunctionEntryLabel() override;
235
236 void emitFunctionBodyStart() override;
237 void emitFunctionBodyEnd() override;
239};
240
241class PPCAIXAsmPrinter : public PPCAsmPrinter {
242private:
243
244
245 SmallSetVector<MCSymbol *, 8> ExtSymSDNodeSymbols;
246
247
248
249 std::string FormatIndicatorAndUniqueModId;
250
251
252
253 DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
254 GOAliasMap;
255
256 uint16_t getNumberOfVRSaved();
257 void emitTracebackTable();
258
260
261 void emitGlobalVariableHelper(const GlobalVariable *);
262
263
264 uint64_t getAliasOffset(const Constant *C);
265
266public:
267 static char ID;
268
269 PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer)
270 : PPCAsmPrinter(TM, std::move(Streamer), ID) {
271 if (MAI->isLittleEndian())
273 "cannot create AIX PPC Assembly Printer for a little-endian target");
274 }
275
276 StringRef getPassName() const override { return "AIX PPC Assembly Printer"; }
277
278 bool doInitialization(Module &M) override;
279
280 void emitXXStructorList(const DataLayout &DL, const Constant *List,
281 bool IsCtor) override;
282
283 void SetupMachineFunction(MachineFunction &MF) override;
284
285 void emitGlobalVariable(const GlobalVariable *GV) override;
286
287 void emitFunctionDescriptor() override;
288
289 void emitFunctionEntryLabel() override;
290
291 void emitFunctionBodyEnd() override;
292
293 void emitPGORefs(Module &M);
294
295 void emitGCOVRefs();
296
297 void emitEndOfAsmFile(Module &) override;
298
299 void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
300
302
303 bool doFinalization(Module &M) override;
304
305 void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override;
306
307 void emitModuleCommandLines(Module &M) override;
308};
309
310}
311
312void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
314
315 const GlobalValue *GV = MO.getGlobal();
316 getSymbol(GV)->print(O, MAI);
318}
319
320void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
321 raw_ostream &O) {
322 const DataLayout &DL = getDataLayout();
323 const MachineOperand &MO = MI->getOperand(OpNo);
324
327
329
330
331
333 return;
334 }
337 return;
338
341 return;
343 O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
345 return;
347 GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
348 return;
350 PrintSymbolOperand(MO, O);
351 return;
352 }
353
354 default:
355 O << "<unknown operand type: " << (unsigned)MO.getType() << ">";
356 return;
357 }
358}
359
360
361
362bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
363 const char *ExtraCode, raw_ostream &O) {
364
365 if (ExtraCode && ExtraCode[0]) {
366 if (ExtraCode[1] != 0) return true;
367
368 switch (ExtraCode[0]) {
369 default:
370
372 case 'L':
373
374 if (->getOperand(OpNo).isReg() ||
375 OpNo+1 == MI->getNumOperands() ||
376 ->getOperand(OpNo+1).isReg())
377 return true;
378 ++OpNo;
379 break;
380 case 'I':
381
382
383 if (MI->getOperand(OpNo).isImm())
384 O << "i";
385 return false;
386 case 'x':
387 if(->getOperand(OpNo).isReg())
388 return true;
389
390
393 Reg = PPC::VSX32 + (Reg - PPC::V0);
395 Reg = PPC::VSX32 + (Reg - PPC::VF0);
400 return false;
401 }
402 }
403
405 return false;
406}
407
408
409
410
411bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
412 const char *ExtraCode,
413 raw_ostream &O) {
414 if (ExtraCode && ExtraCode[0]) {
415 if (ExtraCode[1] != 0) return true;
416
417 switch (ExtraCode[0]) {
418 default: return true;
419 case 'L':
420 O << getDataLayout().getPointerSize() << "(";
422 O << ")";
423 return false;
424 case 'y':
425 O << "0, ";
427 return false;
428 case 'I':
429
430
431 if (MI->getOperand(OpNo).isImm())
432 O << "i";
433 return false;
434 case 'U':
435 case 'X':
436
437
438
439
440
441
442 assert(MI->getOperand(OpNo).isReg());
443 return false;
444 }
445 }
446
447 assert(MI->getOperand(OpNo).isReg());
448 O << "0(";
450 O << ")";
451 return false;
452}
453
455 ++NumTOCEntries;
456 switch (Type) {
457 case PPCAsmPrinter::TOCType_ConstantPool:
458 ++NumTOCConstPool;
459 break;
460 case PPCAsmPrinter::TOCType_GlobalInternal:
461 ++NumTOCGlobalInternal;
462 break;
463 case PPCAsmPrinter::TOCType_GlobalExternal:
464 ++NumTOCGlobalExternal;
465 break;
466 case PPCAsmPrinter::TOCType_JumpTable:
467 ++NumTOCJumpTable;
468 break;
469 case PPCAsmPrinter::TOCType_ThreadLocal:
470 ++NumTOCThreadLocal;
471 break;
472 case PPCAsmPrinter::TOCType_BlockAddress:
473 ++NumTOCBlockAddress;
474 break;
475 case PPCAsmPrinter::TOCType_EHBlock:
476 ++NumTOCEHBlock;
477 break;
478 }
479}
480
485
486
487
489 return ModuleModel;
490
492 assert(GV && "expected global for MO_GlobalAddress");
493
495}
496
498 switch (CM) {
501 return;
504 return;
505 default:
507 }
508}
509
510
511
512
513MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym,
514 TOCEntryType Type,
516
517 auto [It, Inserted] = TOC.try_emplace({Sym, Spec});
518 if (Inserted)
520
521 MCSymbol *&TOCEntry = It->second;
522 if (!TOCEntry)
523 TOCEntry = createTempSymbol("C");
524 return TOCEntry;
525}
526
527void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {
528 unsigned NumNOPBytes = MI.getOperand(1).getImm();
529
530 auto &Ctx = OutStreamer->getContext();
531 MCSymbol *MILabel = Ctx.createTempSymbol();
532 OutStreamer->emitLabel(MILabel);
533
535 assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
536
537
538 const MachineBasicBlock &MBB = *MI.getParent();
540 ++MII;
541 while (NumNOPBytes > 0) {
542 if (MII == MBB.end() || MII->isCall() ||
543 MII->getOpcode() == PPC::DBG_VALUE ||
544 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
545 MII->getOpcode() == TargetOpcode::STACKMAP)
546 break;
547 ++MII;
548 NumNOPBytes -= 4;
549 }
550
551
552 for (unsigned i = 0; i < NumNOPBytes; i += 4)
553 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
554}
555
556
557
558void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {
559 auto &Ctx = OutStreamer->getContext();
560 MCSymbol *MILabel = Ctx.createTempSymbol();
561 OutStreamer->emitLabel(MILabel);
562
564 PatchPointOpers Opers(&MI);
565
566 unsigned EncodedBytes = 0;
567 const MachineOperand &CalleeMO = Opers.getCallTarget();
568
569 if (CalleeMO.isImm()) {
570 int64_t CallTarget = CalleeMO.getImm();
571 if (CallTarget) {
572 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
573 "High 16 bits of call target should be zero.");
574 Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
575 EncodedBytes = 0;
576
577 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)
578 .addReg(ScratchReg)
579 .addImm((CallTarget >> 32) & 0xFFFF));
580 ++EncodedBytes;
581 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC)
582 .addReg(ScratchReg)
583 .addReg(ScratchReg)
584 .addImm(32).addImm(16));
585 ++EncodedBytes;
586 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8)
587 .addReg(ScratchReg)
588 .addReg(ScratchReg)
589 .addImm((CallTarget >> 16) & 0xFFFF));
590 ++EncodedBytes;
591 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8)
592 .addReg(ScratchReg)
593 .addReg(ScratchReg)
594 .addImm(CallTarget & 0xFFFF));
595
596
598 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD)
599 .addReg(PPC::X2)
600 .addImm(TOCSaveOffset)
601 .addReg(PPC::X1));
602 ++EncodedBytes;
603
604
605
607
608
609
610 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
611 .addReg(PPC::X2)
612 .addImm(8)
613 .addReg(ScratchReg));
614 ++EncodedBytes;
615 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
616 .addReg(ScratchReg)
617 .addImm(0)
618 .addReg(ScratchReg));
619 ++EncodedBytes;
620 }
621
622 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8)
623 .addReg(ScratchReg));
624 ++EncodedBytes;
625 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8));
626 ++EncodedBytes;
627
628
629 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
630 .addReg(PPC::X2)
631 .addImm(TOCSaveOffset)
632 .addReg(PPC::X1));
633 ++EncodedBytes;
634 }
635 } else if (CalleeMO.isGlobal()) {
636 const GlobalValue *GValue = CalleeMO.getGlobal();
637 MCSymbol *MOSymbol = getSymbol(GValue);
639
640 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP)
641 .addExpr(SymVar));
642 EncodedBytes += 2;
643 }
644
645
646 EncodedBytes *= 4;
647
648
649 unsigned NumBytes = Opers.getNumPatchBytes();
650 assert(NumBytes >= EncodedBytes &&
651 "Patchpoint can't request size less than the length of a call.");
652 assert((NumBytes - EncodedBytes) % 4 == 0 &&
653 "Invalid number of NOP bytes requested!");
654 for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
655 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
656}
657
658
659
660
663 switch (MIOpc) {
664 default:
665 SymName = ".__tls_get_addr";
666 break;
667 case PPC::GETtlsTpointer32AIX:
668 SymName = ".__get_tpointer";
669 break;
670 case PPC::GETtlsMOD32AIX:
671 case PPC::GETtlsMOD64AIX:
672 SymName = ".__tls_get_mod";
673 break;
674 }
675 return Ctx
678 ->getQualNameSymbol();
679}
680
681void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) {
683 "Only expecting to emit calls to get the thread pointer on AIX!");
684
687 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));
688}
689
690
691
692void PPCAsmPrinter::emitTlsCall(const MachineInstr *MI,
695 unsigned Opcode = PPC::BL8_NOP_TLS;
696
697 assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI");
701 Opcode = PPC::BL8_NOTOC_TLS;
702 }
703 const Module *M = MF->getFunction().getParent();
704
705 assert(MI->getOperand(0).isReg() &&
706 ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||
707 (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&
708 "GETtls[ld]ADDR[32] must define GPR3");
709 assert(MI->getOperand(1).isReg() &&
710 ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||
711 (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&
712 "GETtls[ld]ADDR[32] must read GPR3");
713
715
716
717
718
719 Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;
720 (void)VarOffsetReg;
721 assert((MI->getOpcode() == PPC::GETtlsMOD32AIX ||
722 MI->getOpcode() == PPC::GETtlsMOD64AIX ||
723 (MI->getOperand(2).isReg() &&
724 MI->getOperand(2).getReg() == VarOffsetReg)) &&
725 "GETtls[ld]ADDR[32] must read GPR4");
726 EmitAIXTlsCallHelper(MI);
727 return;
728 }
729
730 MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol("__tls_get_addr");
731
732 if (Subtarget->is32BitELFABI() && isPositionIndependent())
734
736
737
738 if (Kind == PPC::S_PLT && Subtarget->isSecurePlt() &&
742 const MachineOperand &MO = MI->getOperand(2);
743 const GlobalValue *GValue = MO.getGlobal();
744 MCSymbol *MOSymbol = getSymbol(GValue);
746 EmitToStreamer(*OutStreamer,
747 MCInstBuilder(Subtarget->isPPC64() ? Opcode
748 : (unsigned)PPC::BL_TLS)
749 .addExpr(TlsRef)
750 .addExpr(SymVar));
751}
752
753
754
770
771static PPCAsmPrinter::TOCEntryType
773
774
776 return PPCAsmPrinter::TOCType_ThreadLocal;
777
785 return PPCAsmPrinter::TOCType_GlobalExternal;
786
787 return PPCAsmPrinter::TOCType_GlobalInternal;
788 }
790 return PPCAsmPrinter::TOCType_ConstantPool;
792 return PPCAsmPrinter::TOCType_JumpTable;
794 return PPCAsmPrinter::TOCType_BlockAddress;
795 default:
796 llvm_unreachable("Unexpected operand type to get TOC type.");
797 }
798}
799
800const MCExpr *PPCAsmPrinter::symbolWithSpecifier(const MCSymbol *S,
803}
804
805
806
807
808void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
809 PPC_MC::verifyInstructionPredicates(MI->getOpcode(),
810 getSubtargetInfo().getFeatureBits());
811
812 MCInst TmpInst;
813 const bool IsPPC64 = Subtarget->isPPC64();
814 const bool IsAIX = Subtarget->isAIXABI();
815 const bool HasAIXSmallLocalTLS = Subtarget->hasAIXSmallLocalExecTLS() ||
816 Subtarget->hasAIXSmallLocalDynamicTLS();
817 const Module *M = MF->getFunction().getParent();
819
820#ifndef NDEBUG
821
822 if (->isInlineAsm()) {
823 for (const MachineOperand &MO: MI->operands()) {
824 if (MO.isReg()) {
826 if (Subtarget->hasSPE()) {
833 )
835 } else {
837 llvm_unreachable("SPE register found in FPU-targeted code!");
838 }
839 }
840 }
841 }
842#endif
843
844 auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,
845 ptrdiff_t OriginalOffset) {
846
847
848
849
850
851
852 ptrdiff_t Adjustment =
856 };
857
858 auto getTOCEntryLoadingExprForXCOFF =
859 [IsPPC64, getTOCRelocAdjustedExprForXCOFF,
860 this](const MCSymbol *MOSymbol, const MCExpr *Expr,
862 const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
863 const auto TOCEntryIter = TOC.find({MOSymbol, VK});
864 assert(TOCEntryIter != TOC.end() &&
865 "Could not find the TOC entry for this symbol.");
866 const ptrdiff_t EntryDistanceFromTOCBase =
867 (TOCEntryIter - TOC.begin()) * EntryByteSize;
868 constexpr int16_t PositiveTOCRange = INT16_MAX;
869
870 if (EntryDistanceFromTOCBase > PositiveTOCRange)
871 return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);
872
873 return Expr;
874 };
875 auto getSpecifier = [&](const MachineOperand &MO) {
876
877
878
883 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");
889
890
891 PPCFunctionInfo *FuncInfo = MF->getInfo();
895 dbgs() << "Current function uses IE access for default LD vars.\n");
897 }
898 llvm_unreachable("Only expecting local-exec or initial-exec accesses!");
899 }
900
901
902
907
908
909
915 };
916
917
918 switch (MI->getOpcode()) {
919 default: break;
920 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
922 "AIX does not support patchable function entry!");
923 const Function &F = MF->getFunction();
924 unsigned Num = 0;
925 (void)F.getFnAttribute("patchable-function-entry")
926 .getValueAsString()
927 .getAsInteger(10, Num);
928 if (!Num)
929 return;
930 emitNops(Num);
931 return;
932 }
933 case TargetOpcode::DBG_VALUE:
935 case TargetOpcode::STACKMAP:
936 return LowerSTACKMAP(SM, *MI);
937 case TargetOpcode::PATCHPOINT:
938 return LowerPATCHPOINT(SM, *MI);
939
940 case PPC::MoveGOTtoLR: {
941
942
943
944
945
946
948 OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
952
953
954 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));
955 return;
956 }
957 case PPC::MovePCtoLR:
958 case PPC::MovePCtoLR8: {
959
960
961
962
963 MCSymbol *PICBase = MF->getPICBaseSymbol();
964
965
966 EmitToStreamer(*OutStreamer,
967 MCInstBuilder(PPC::BCLalways)
968
969
971
972
973 OutStreamer->emitLabel(PICBase);
974 return;
975 }
976 case PPC::UpdateGBR: {
977
978
979
980
981
982
983
985 if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
987 MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
989 : ".LTOC");
990 const MCExpr *PB =
992
995
996 const MCExpr *DeltaHi =
998 EmitToStreamer(
999 *OutStreamer,
1000 MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));
1001
1002 const MCExpr *DeltaLo =
1004 EmitToStreamer(
1005 *OutStreamer,
1006 MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));
1007 return;
1008 } else {
1010 MF->getInfo()->getPICOffsetSymbol(*MF);
1013 const MCExpr *PB =
1015 OutContext);
1016 const MCOperand TR = TmpInst.getOperand(1);
1017 const MCOperand PICR = TmpInst.getOperand(0);
1018
1019
1024 EmitToStreamer(*OutStreamer, TmpInst);
1025
1030 EmitToStreamer(*OutStreamer, TmpInst);
1031 return;
1032 }
1033 }
1034 case PPC::LWZtoc: {
1035
1037
1038
1040
1041 const MachineOperand &MO = MI->getOperand(1);
1043 "Invalid operand for LWZtoc.");
1044
1045
1047
1048
1049
1051 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, PPC::S_GOT);
1053 EmitToStreamer(*OutStreamer, TmpInst);
1054 return;
1055 }
1056
1058
1059
1060
1061
1065
1066
1067
1068
1069 if (IsAIX) {
1072 "This pseudo should only be selected for 32-bit small code model.");
1073 Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
1075
1076
1077 if (isVerbose())
1078 OutStreamer->getCommentOS() << MO << '\n';
1079 EmitToStreamer(*OutStreamer, TmpInst);
1080 return;
1081 }
1082
1083
1084
1086 OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext);
1089 EmitToStreamer(*OutStreamer, TmpInst);
1090 return;
1091 }
1092 case PPC::ADDItoc:
1093 case PPC::ADDItoc8: {
1095 "PseudoOp only valid for small code model AIX");
1096
1097
1099
1100
1101 TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
1102
1103 const MachineOperand &MO = MI->getOperand(2);
1104 assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");
1105
1106
1108
1110
1112 EmitToStreamer(*OutStreamer, TmpInst);
1113 return;
1114 }
1115 case PPC::LDtocJTI:
1116 case PPC::LDtocCPT:
1117 case PPC::LDtocBA:
1118 case PPC::LDtoc: {
1119
1121
1122
1124
1125 const MachineOperand &MO = MI->getOperand(1);
1127 "Invalid operand!");
1128
1129
1131
1133
1134
1135
1136
1139
1141 const MCExpr *Exp = symbolWithSpecifier(TOCEntry, VKExpr);
1143 IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);
1144
1145
1146 if (isVerbose() && IsAIX)
1147 OutStreamer->getCommentOS() << MO << '\n';
1148 EmitToStreamer(*OutStreamer, TmpInst);
1149 return;
1150 }
1151 case PPC::ADDIStocHA: {
1152 const MachineOperand &MO = MI->getOperand(2);
1153
1155 "Invalid operand for ADDIStocHA.");
1156 assert((IsAIX && !IsPPC64 &&
1158 "This pseudo should only be selected for 32-bit large code model on"
1159 " AIX.");
1160
1161
1163
1164
1166
1167
1169
1171
1172
1173
1174
1175
1176
1177
1178 if ( {
1180 return false;
1181
1183 if (!GV)
1184 return false;
1186 }(MO)) {
1188 }
1189
1190 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, PPC::S_U);
1192 EmitToStreamer(*OutStreamer, TmpInst);
1193 return;
1194 }
1195 case PPC::LWZtocL: {
1196 const MachineOperand &MO = MI->getOperand(1);
1197
1199 "Invalid operand for LWZtocL.");
1200 assert(IsAIX && !IsPPC64 &&
1202 "This pseudo should only be selected for 32-bit large code model on"
1203 " AIX.");
1204
1205
1207
1208
1210
1211
1213
1215
1216
1217
1218
1219
1222 const MCExpr *Exp = symbolWithSpecifier(TOCEntry, PPC::S_L);
1224 EmitToStreamer(*OutStreamer, TmpInst);
1225 return;
1226 }
1227 case PPC::ADDIStocHA8: {
1228
1230
1231
1232
1233
1234
1236
1237 const MachineOperand &MO = MI->getOperand(2);
1239 "Invalid operand for ADDIStocHA8!");
1240
1242
1244
1245 const bool GlobalToc =
1247
1250
1254
1256
1257 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, VK);
1258
1262 OutContext),
1263 OutContext);
1264
1266 EmitToStreamer(*OutStreamer, TmpInst);
1267 return;
1268 }
1269 case PPC::LDtocL: {
1270
1272
1273
1274
1275
1276
1278
1279 const MachineOperand &MO = MI->getOperand(1);
1282 "Invalid operand for LDtocL!");
1283
1286 "LDtocL used on symbol that could be accessed directly is "
1287 "invalid. Must match ADDIStocHA8."));
1288
1290
1296
1298 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, VK);
1300 EmitToStreamer(*OutStreamer, TmpInst);
1301 return;
1302 }
1303 case PPC::ADDItocL:
1304 case PPC::ADDItocL8: {
1305
1307
1308 unsigned Op = MI->getOpcode();
1309
1310
1311
1312 TmpInst.setOpcode(Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8)
1313 : PPC::LA);
1314
1315 const MachineOperand &MO = MI->getOperand(2);
1316 assert((Op == PPC::ADDItocL8)
1318 : MO.isGlobal() && "Invalid operand for ADDItocL8.");
1320 "Interposable definitions must use indirect accesses.");
1321
1322
1324
1327
1329 EmitToStreamer(*OutStreamer, TmpInst);
1330 return;
1331 }
1332 case PPC::ADDISgotTprelHA: {
1333
1334
1335 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1336 const MachineOperand &MO = MI->getOperand(2);
1337 const GlobalValue *GValue = MO.getGlobal();
1338 MCSymbol *MOSymbol = getSymbol(GValue);
1339 const MCExpr *SymGotTprel =
1341 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1342 .addReg(MI->getOperand(0).getReg())
1343 .addReg(MI->getOperand(1).getReg())
1344 .addExpr(SymGotTprel));
1345 return;
1346 }
1347 case PPC::LDgotTprelL:
1348 case PPC::LDgotTprelL32: {
1349
1351
1352
1353 TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);
1354 const MachineOperand &MO = MI->getOperand(1);
1355 const GlobalValue *GValue = MO.getGlobal();
1356 MCSymbol *MOSymbol = getSymbol(GValue);
1357 const MCExpr *Exp = symbolWithSpecifier(
1360 EmitToStreamer(*OutStreamer, TmpInst);
1361 return;
1362 }
1363
1364 case PPC::PPC32PICGOT: {
1365 MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
1366 MCSymbol *GOTRef = OutContext.createTempSymbol();
1367 MCSymbol *NextInstr = OutContext.createTempSymbol();
1368
1369 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL)
1370
1371
1373 const MCExpr *OffsExpr =
1376 OutContext);
1377 OutStreamer->emitLabel(GOTRef);
1378 OutStreamer->emitValue(OffsExpr, 4);
1379 OutStreamer->emitLabel(NextInstr);
1380 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)
1381 .addReg(MI->getOperand(0).getReg()));
1382 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)
1383 .addReg(MI->getOperand(1).getReg())
1384 .addImm(0)
1385 .addReg(MI->getOperand(0).getReg()));
1386 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4)
1387 .addReg(MI->getOperand(0).getReg())
1388 .addReg(MI->getOperand(1).getReg())
1389 .addReg(MI->getOperand(0).getReg()));
1390 return;
1391 }
1392 case PPC::PPC32GOT: {
1394 OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
1395 const MCExpr *SymGotTlsL =
1397 const MCExpr *SymGotTlsHA =
1399 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI)
1400 .addReg(MI->getOperand(0).getReg())
1401 .addExpr(SymGotTlsL));
1402 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
1403 .addReg(MI->getOperand(0).getReg())
1404 .addReg(MI->getOperand(0).getReg())
1405 .addExpr(SymGotTlsHA));
1406 return;
1407 }
1408 case PPC::ADDIStlsgdHA: {
1409
1410
1411 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1412 const MachineOperand &MO = MI->getOperand(2);
1413 const GlobalValue *GValue = MO.getGlobal();
1414 MCSymbol *MOSymbol = getSymbol(GValue);
1415 const MCExpr *SymGotTlsGD =
1417 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1418 .addReg(MI->getOperand(0).getReg())
1419 .addReg(MI->getOperand(1).getReg())
1420 .addExpr(SymGotTlsGD));
1421 return;
1422 }
1423 case PPC::ADDItlsgdL:
1424
1425
1426 case PPC::ADDItlsgdL32: {
1427
1428
1429 const MachineOperand &MO = MI->getOperand(2);
1430 const GlobalValue *GValue = MO.getGlobal();
1431 MCSymbol *MOSymbol = getSymbol(GValue);
1432 const MCExpr *SymGotTlsGD = symbolWithSpecifier(
1434 EmitToStreamer(*OutStreamer,
1435 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1436 .addReg(MI->getOperand(0).getReg())
1437 .addReg(MI->getOperand(1).getReg())
1438 .addExpr(SymGotTlsGD));
1439 return;
1440 }
1441 case PPC::GETtlsMOD32AIX:
1442 case PPC::GETtlsMOD64AIX:
1443
1444
1445
1446 case PPC::GETtlsADDR:
1447
1448
1449 case PPC::GETtlsADDRPCREL:
1450 case PPC::GETtlsADDR32AIX:
1451 case PPC::GETtlsADDR64AIX:
1452
1453
1454
1455 case PPC::GETtlsADDR32: {
1456
1457
1459 return;
1460 }
1461 case PPC::GETtlsTpointer32AIX: {
1462
1463
1464 EmitAIXTlsCallHelper(MI);
1465 return;
1466 }
1467 case PPC::ADDIStlsldHA: {
1468
1469
1470 assert(IsPPC64 && "Not supported for 32-bit PowerPC");
1471 const MachineOperand &MO = MI->getOperand(2);
1472 const GlobalValue *GValue = MO.getGlobal();
1473 MCSymbol *MOSymbol = getSymbol(GValue);
1474 const MCExpr *SymGotTlsLD =
1476 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1477 .addReg(MI->getOperand(0).getReg())
1478 .addReg(MI->getOperand(1).getReg())
1479 .addExpr(SymGotTlsLD));
1480 return;
1481 }
1482 case PPC::ADDItlsldL:
1483
1484
1485 case PPC::ADDItlsldL32: {
1486
1487
1488 const MachineOperand &MO = MI->getOperand(2);
1489 const GlobalValue *GValue = MO.getGlobal();
1490 MCSymbol *MOSymbol = getSymbol(GValue);
1491 const MCExpr *SymGotTlsLD = symbolWithSpecifier(
1493 EmitToStreamer(*OutStreamer,
1494 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1495 .addReg(MI->getOperand(0).getReg())
1496 .addReg(MI->getOperand(1).getReg())
1497 .addExpr(SymGotTlsLD));
1498 return;
1499 }
1500 case PPC::GETtlsldADDR:
1501
1502
1503 case PPC::GETtlsldADDRPCREL:
1504 case PPC::GETtlsldADDR32: {
1505
1506
1508 return;
1509 }
1510 case PPC::ADDISdtprelHA:
1511
1512
1513 case PPC::ADDISdtprelHA32: {
1514
1515
1516 const MachineOperand &MO = MI->getOperand(2);
1517 const GlobalValue *GValue = MO.getGlobal();
1518 MCSymbol *MOSymbol = getSymbol(GValue);
1519 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL_HA);
1520 EmitToStreamer(
1521 *OutStreamer,
1522 MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)
1523 .addReg(MI->getOperand(0).getReg())
1524 .addReg(MI->getOperand(1).getReg())
1525 .addExpr(SymDtprel));
1526 return;
1527 }
1528 case PPC::PADDIdtprel: {
1529
1530
1531 const MachineOperand &MO = MI->getOperand(2);
1532 const GlobalValue *GValue = MO.getGlobal();
1533 MCSymbol *MOSymbol = getSymbol(GValue);
1534 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL);
1535 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8)
1536 .addReg(MI->getOperand(0).getReg())
1537 .addReg(MI->getOperand(1).getReg())
1538 .addExpr(SymDtprel));
1539 return;
1540 }
1541
1542 case PPC::ADDIdtprelL:
1543
1544
1545 case PPC::ADDIdtprelL32: {
1546
1547
1548 const MachineOperand &MO = MI->getOperand(2);
1549 const GlobalValue *GValue = MO.getGlobal();
1550 MCSymbol *MOSymbol = getSymbol(GValue);
1551 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL_LO);
1552 EmitToStreamer(*OutStreamer,
1553 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1554 .addReg(MI->getOperand(0).getReg())
1555 .addReg(MI->getOperand(1).getReg())
1556 .addExpr(SymDtprel));
1557 return;
1558 }
1559 case PPC::MFOCRF:
1560 case PPC::MFOCRF8:
1561 if (!Subtarget->hasMFOCRF()) {
1562
1563
1564 unsigned NewOpcode =
1565 MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;
1566 OutStreamer->AddComment(PPCInstPrinter::
1568 EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)
1569 .addReg(MI->getOperand(0).getReg()));
1570 return;
1571 }
1572 break;
1573 case PPC::MTOCRF:
1574 case PPC::MTOCRF8:
1575 if (!Subtarget->hasMFOCRF()) {
1576
1577
1578 unsigned NewOpcode =
1579 MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
1580 unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
1581 ->getEncodingValue(MI->getOperand(0).getReg());
1582 OutStreamer->AddComment(PPCInstPrinter::
1584 EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)
1585 .addImm(Mask)
1586 .addReg(MI->getOperand(1).getReg()));
1587 return;
1588 }
1589 break;
1590 case PPC::LD:
1591 case PPC::STD:
1592 case PPC::LWA_32:
1593 case PPC::LWA: {
1594
1595
1596 unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;
1597
1598
1599
1600 for (const MachineOperand &TempMO : MI->operands()) {
1603 TempMO.getOperandNo() == 1)
1604 OpNum = 1;
1605 }
1606 const MachineOperand &MO = MI->getOperand(OpNum);
1610 llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");
1611 }
1612
1613
1614
1615 [[fallthrough]];
1616 }
1617 case PPC::LBZ:
1618 case PPC::LBZ8:
1619 case PPC::LHA:
1620 case PPC::LHA8:
1621 case PPC::LHZ:
1622 case PPC::LHZ8:
1623 case PPC::LWZ:
1624 case PPC::LWZ8:
1625 case PPC::STB:
1626 case PPC::STB8:
1627 case PPC::STH:
1628 case PPC::STH8:
1629 case PPC::STW:
1630 case PPC::STW8:
1631 case PPC::LFS:
1632 case PPC::STFS:
1633 case PPC::LFD:
1634 case PPC::STFD:
1635 case PPC::ADDI8: {
1636
1637
1638
1639
1640 if (!HasAIXSmallLocalTLS)
1641 break;
1642 bool IsMIADDI8 = MI->getOpcode() == PPC::ADDI8;
1643 unsigned OpNum = IsMIADDI8 ? 2 : 1;
1644 const MachineOperand &MO = MI->getOperand(OpNum);
1650
1651 const MCExpr *Expr = getAdjustedFasterLocalExpr(MO, MO.getOffset());
1652 if (Expr)
1654
1655
1656 if (IsMIADDI8)
1658
1659 EmitToStreamer(*OutStreamer, TmpInst);
1660 return;
1661 }
1662
1663 break;
1664 }
1665 case PPC::PseudoEIEIO: {
1666 EmitToStreamer(
1667 *OutStreamer,
1668 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1669 EmitToStreamer(
1670 *OutStreamer,
1671 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1672 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));
1673 return;
1674 }
1675 }
1676
1678 EmitToStreamer(*OutStreamer, TmpInst);
1679}
1680
1681
1682
1683
1684
1685
1686
1687const MCExpr *
1688PPCAsmPrinter::getAdjustedFasterLocalExpr(const MachineOperand &MO,
1690
1691
1693 return nullptr;
1694
1695 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");
1696 const GlobalValue *GValue = MO.getGlobal();
1699 "Only local-[exec|dynamic] accesses are handled!");
1700
1702
1703
1704
1705 const auto TLSVarsMapEntryIter = TLSVarsToAddressMapping.find(GValue);
1706 if (TLSVarsMapEntryIter == TLSVarsToAddressMapping.end())
1707 assert(IsGlobalADeclaration &&
1708 "Only expecting to find extern TLS variables not present in the TLS "
1709 "variable-to-address map!");
1710
1711 unsigned TLSVarAddress =
1712 IsGlobalADeclaration ? 0 : TLSVarsMapEntryIter->second;
1713 ptrdiff_t FinalAddress = (TLSVarAddress + Offset);
1714
1715
1716
1717
1718
1720 getSymbol(GValue),
1722 OutContext);
1725 if (FinalAddress >= 32768) {
1726
1727
1728
1729
1730
1731
1732 ptrdiff_t Delta = ((FinalAddress + 32768) & ~0xFFFF);
1733
1734 [[maybe_unused]] ptrdiff_t InstDisp = TLSVarAddress + Offset - Delta;
1736 ((InstDisp < 32768) && (InstDisp >= -32768)) &&
1737 "Expecting the instruction displacement for local-[exec|dynamic] TLS "
1738 "variables to be between [-32768, 32768)!");
1741 }
1742
1743 return Expr;
1744}
1745
1746void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) {
1747
1748 Metadata *MD = M.getModuleFlag("float-abi");
1750 if (!FloatABI)
1751 return;
1752 StringRef flt = FloatABI->getString();
1753
1754 if (flt == "doubledouble")
1755 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1756 Val_GNU_Power_ABI_HardFloat_DP |
1757 Val_GNU_Power_ABI_LDBL_IBM128);
1758 else if (flt == "ieeequad")
1759 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1760 Val_GNU_Power_ABI_HardFloat_DP |
1761 Val_GNU_Power_ABI_LDBL_IEEE128);
1762 else if (flt == "ieeedouble")
1763 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1764 Val_GNU_Power_ABI_HardFloat_DP |
1765 Val_GNU_Power_ABI_LDBL_64);
1766}
1767
1768void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
1769 if (!Subtarget->isPPC64())
1770 return PPCAsmPrinter::emitInstruction(MI);
1771
1772 switch (MI->getOpcode()) {
1773 default:
1774 break;
1775 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788 const Function &F = MF->getFunction();
1789 unsigned Num = 0;
1790 (void)F.getFnAttribute("patchable-function-entry")
1791 .getValueAsString()
1792 .getAsInteger(10, Num);
1793
1794 if (!MAI->isLittleEndian() || Num)
1795 break;
1796 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1797 MCSymbol *EndOfSled = OutContext.createTempSymbol();
1798 OutStreamer->emitLabel(BeginOfSled);
1799 EmitToStreamer(*OutStreamer,
1800 MCInstBuilder(PPC::B).addExpr(
1802 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1803 EmitToStreamer(
1804 *OutStreamer,
1805 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1806 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1807 EmitToStreamer(*OutStreamer,
1808 MCInstBuilder(PPC::BL8_NOP)
1810 OutContext.getOrCreateSymbol("__xray_FunctionEntry"),
1811 OutContext)));
1812 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1813 OutStreamer->emitLabel(EndOfSled);
1814 recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER, 2);
1815 break;
1816 }
1817 case TargetOpcode::PATCHABLE_RET: {
1818 unsigned RetOpcode = MI->getOperand(0).getImm();
1819 MCInst RetInst;
1822 MCOperand MCOp;
1825 }
1826
1827 bool IsConditional;
1828 if (RetOpcode == PPC::BCCLR) {
1829 IsConditional = true;
1830 } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
1831 RetOpcode == PPC::TCRETURNai8) {
1832 break;
1833 } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
1834 IsConditional = false;
1835 } else {
1836 EmitToStreamer(*OutStreamer, RetInst);
1837 return;
1838 }
1839
1841 if (IsConditional) {
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860 FallthroughLabel = OutContext.createTempSymbol();
1861 EmitToStreamer(
1862 *OutStreamer,
1863 MCInstBuilder(PPC::BCC)
1866 .addReg(MI->getOperand(2).getReg())
1868 RetInst = MCInst();
1870 }
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883 OutStreamer->emitCodeAlignment(Align(8), &getSubtargetInfo());
1884 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1885 OutStreamer->emitLabel(BeginOfSled);
1886 EmitToStreamer(*OutStreamer, RetInst);
1887 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1888 EmitToStreamer(
1889 *OutStreamer,
1890 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1891 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1892 EmitToStreamer(*OutStreamer,
1893 MCInstBuilder(PPC::BL8_NOP)
1895 OutContext.getOrCreateSymbol("__xray_FunctionExit"),
1896 OutContext)));
1897 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1898 EmitToStreamer(*OutStreamer, RetInst);
1899 if (IsConditional)
1900 OutStreamer->emitLabel(FallthroughLabel);
1901 recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT, 2);
1902 return;
1903 }
1904 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1905 llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
1906 case TargetOpcode::PATCHABLE_TAIL_CALL:
1907
1908
1909 llvm_unreachable("Tail call is handled in the normal case. See comments "
1910 "around this assert.");
1911 }
1912 return PPCAsmPrinter::emitInstruction(MI);
1913}
1914
1915void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {
1916 if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {
1917 PPCTargetStreamer *TS =
1918 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
1920 }
1921
1922 if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||
1923 !isPositionIndependent())
1925
1928
1929 OutStreamer->switchSection(OutContext.getELFSection(
1931
1932 MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC"));
1933 MCSymbol *CurrentPos = OutContext.createTempSymbol();
1934
1935 OutStreamer->emitLabel(CurrentPos);
1936
1937
1938
1939 const MCExpr *tocExpr =
1942 OutContext);
1943
1944 OutStreamer->emitAssignment(TOCSym, tocExpr);
1945
1946 OutStreamer->switchSection(getObjFileLowering().getTextSection());
1947}
1948
1949void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {
1950
1951 if (!Subtarget->isPPC64() &&
1952 (!isPositionIndependent() ||
1953 MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC))
1955
1956 if (!Subtarget->isPPC64()) {
1957 const PPCFunctionInfo *PPCFI = MF->getInfo();
1958 if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {
1960 MCSymbol *PICBase = MF->getPICBaseSymbol();
1961 OutStreamer->emitLabel(RelocSymbol);
1962
1963 const MCExpr *OffsExpr =
1966 OutContext),
1968 OutContext);
1969 OutStreamer->emitValue(OffsExpr, 4);
1970 OutStreamer->emitLabel(CurrentFnSym);
1971 return;
1972 } else
1974 }
1975
1976
1978
1979
1980
1981
1983 && !MF->getRegInfo().use_empty(PPC::X2)) {
1984 const PPCFunctionInfo *PPCFI = MF->getInfo();
1985
1986 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));
1988 const MCExpr *TOCDeltaExpr =
1991 OutContext),
1992 OutContext);
1993
1995 OutStreamer->emitValue(TOCDeltaExpr, 8);
1996 }
1998 }
1999
2000
2001 MCSectionSubPair Current = OutStreamer->getCurrentSection();
2002 MCSectionELF *Section = OutStreamer->getContext().getELFSection(
2004 OutStreamer->switchSection(Section);
2005 OutStreamer->emitLabel(CurrentFnSym);
2006 OutStreamer->emitValueToAlignment(Align(8));
2007 MCSymbol *Symbol1 = CurrentFnSymForSize;
2008
2009
2011 8 );
2012 MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC."));
2013
2014 OutStreamer->emitValue(
2016
2017 OutStreamer->emitIntValue(0, 8 );
2018 OutStreamer->switchSection(Current.first, Current.second);
2019}
2020
2021void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {
2022 const DataLayout &DL = getDataLayout();
2023
2024 bool isPPC64 = DL.getPointerSizeInBits() == 64;
2025
2026 PPCTargetStreamer *TS =
2027 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2028
2029
2030
2031
2032
2033 if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess())
2034 OutStreamer->emitSymbolValue(
2035 GetExternalSymbolSymbol("__parse_hwcap_and_convert_at_platform"),
2036 MAI->getCodePointerSize());
2037 emitGNUAttributes(M);
2038
2039 if (.empty()) {
2040 const char *Name = isPPC64 ? ".toc" : ".got2";
2041 MCSectionELF *Section = OutContext.getELFSection(
2043 OutStreamer->switchSection(Section);
2044 if (!isPPC64)
2045 OutStreamer->emitValueToAlignment(Align(4));
2046
2047 for (const auto &TOCMapPair : TOC) {
2048 const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;
2049 MCSymbol *const TOCEntryLabel = TOCMapPair.second;
2050
2051 OutStreamer->emitLabel(TOCEntryLabel);
2052 if (isPPC64)
2053 TS->emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);
2054 else
2055 OutStreamer->emitSymbolValue(TOCEntryTarget, 4);
2056 }
2057 }
2058
2059 PPCAsmPrinter::emitEndOfAsmFile(M);
2060}
2061
2062
2063void PPCLinuxAsmPrinter::emitFunctionBodyStart() {
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095 const PPCFunctionInfo *PPCFI = MF->getInfo();
2096 const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||
2097 !MF->getRegInfo().use_empty(PPC::R2);
2101 Subtarget->isELFv2ABI() && UsesX2OrR2;
2102
2103
2104
2105
2106 if (NonPCrelGEPRequired || PCrelGEPRequired) {
2107
2108
2109
2111 OutStreamer->emitLabel(GlobalEntryLabel);
2112 const MCSymbolRefExpr *GlobalEntryLabelExp =
2114
2116 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));
2117 const MCExpr *TOCDeltaExpr =
2119 GlobalEntryLabelExp, OutContext);
2120
2121 const MCExpr *TOCDeltaHi =
2123 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
2124 .addReg(PPC::X2)
2125 .addReg(PPC::X12)
2126 .addExpr(TOCDeltaHi));
2127
2128 const MCExpr *TOCDeltaLo =
2130 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
2131 .addReg(PPC::X2)
2132 .addReg(PPC::X2)
2133 .addExpr(TOCDeltaLo));
2134 } else {
2136 const MCExpr *TOCOffsetDeltaExpr =
2138 GlobalEntryLabelExp, OutContext);
2139
2140 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
2141 .addReg(PPC::X2)
2142 .addExpr(TOCOffsetDeltaExpr)
2143 .addReg(PPC::X12));
2144 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)
2145 .addReg(PPC::X2)
2146 .addReg(PPC::X2)
2147 .addReg(PPC::X12));
2148 }
2149
2151 OutStreamer->emitLabel(LocalEntryLabel);
2152 const MCSymbolRefExpr *LocalEntryLabelExp =
2154 const MCExpr *LocalOffsetExp =
2156 GlobalEntryLabelExp, OutContext);
2157
2158 PPCTargetStreamer *TS =
2159 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2160 TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),
2161 LocalOffsetExp);
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184 if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||
2185 MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) {
2186 PPCTargetStreamer *TS =
2187 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2188 TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),
2190 }
2191 }
2192}
2193
2194
2195
2196
2197void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
2198
2199
2200
2201
2202
2203
2204
2205 if (Subtarget->isPPC64()) {
2206 OutStreamer->emitIntValue(0, 4);
2207 OutStreamer->emitIntValue(0, 8);
2208 }
2209}
2210
2211char PPCLinuxAsmPrinter::ID = 0;
2212
2214 "Linux PPC Assembly Printer", false, false)
2215
2219 switch (GV->getLinkage()) {
2220 case GlobalValue::ExternalLinkage:
2221 LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;
2222 break;
2223 case GlobalValue::LinkOnceAnyLinkage:
2224 case GlobalValue::LinkOnceODRLinkage:
2225 case GlobalValue::WeakAnyLinkage:
2226 case GlobalValue::WeakODRLinkage:
2227 case GlobalValue::ExternalWeakLinkage:
2228 LinkageAttr = MCSA_Weak;
2229 break;
2230 case GlobalValue::AvailableExternallyLinkage:
2231 LinkageAttr = MCSA_Extern;
2232 break;
2233 case GlobalValue::PrivateLinkage:
2234 return;
2235 case GlobalValue::InternalLinkage:
2236 assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&
2237 "InternalLinkage should not have other visibility setting.");
2238 LinkageAttr = MCSA_LGlobal;
2239 break;
2240 case GlobalValue::AppendingLinkage:
2241 llvm_unreachable("Should never emit this");
2242 case GlobalValue::CommonLinkage:
2243 llvm_unreachable("CommonLinkage of XCOFF should not come to this path");
2244 }
2245
2246 assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");
2247
2249 if (!TM.getIgnoreXCOFFVisibility()) {
2250 if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())
2251 report_fatal_error(
2252 "Cannot not be both dllexport and non-default visibility");
2253 switch (GV->getVisibility()) {
2254
2255
2256 case GlobalValue::DefaultVisibility:
2257 if (GV->hasDLLExportStorageClass())
2258 VisibilityAttr = MAI->getExportedVisibilityAttr();
2259 break;
2260 case GlobalValue::HiddenVisibility:
2261 VisibilityAttr = MAI->getHiddenVisibilityAttr();
2262 break;
2263 case GlobalValue::ProtectedVisibility:
2264 VisibilityAttr = MAI->getProtectedVisibilityAttr();
2265 break;
2266 }
2267 }
2268
2269
2270 if (GV->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&
2272 return;
2273
2274 OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
2275 VisibilityAttr);
2276}
2277
2278void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
2279
2280 auto *FnDescSec = static_cast<MCSectionXCOFF *>(
2281 getObjFileLowering().getSectionForFunctionDescriptor(&MF.getFunction(),
2282 TM));
2283 FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4));
2284
2285 CurrentFnDescSym = FnDescSec->getQualNameSymbol();
2286
2288}
2289
2290uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {
2291
2292
2293
2294 const PPCSubtarget &Subtarget = MF->getSubtarget();
2295 if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&
2296 TM.getAIXExtendedAltivecABI()) {
2297 const MachineRegisterInfo &MRI = MF->getRegInfo();
2298 for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg)
2299 if (MRI.isPhysRegModified(Reg))
2300
2301 return PPC::V31 - Reg + 1;
2302 }
2303 return 0;
2304}
2305
2306void PPCAIXAsmPrinter::emitFunctionBodyEnd() {
2307
2308 if (!TM.getXCOFFTracebackTable())
2309 return;
2310
2311 emitTracebackTable();
2312
2313
2314
2315
2316
2317
2319 (getNumberOfVRSaved() > 0)) {
2320
2321 OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());
2324 OutStreamer->emitLabel(EHInfoLabel);
2325
2326
2327 OutStreamer->emitInt32(0);
2328
2329 const DataLayout &DL = MMI->getModule()->getDataLayout();
2330 const unsigned PointerSize = DL.getPointerSize();
2331
2332 OutStreamer->emitValueToAlignment(Align(PointerSize));
2333
2334 OutStreamer->emitIntValue(0, PointerSize);
2335 OutStreamer->emitIntValue(0, PointerSize);
2336 OutStreamer->switchSection(MF->getSection());
2337 }
2338}
2339
2340void PPCAIXAsmPrinter::emitTracebackTable() {
2341
2342
2344 OutStreamer->emitLabel(FuncEnd);
2345
2346 OutStreamer->AddComment("Traceback table begin");
2347
2348 OutStreamer->emitIntValueInHexWithPadding(0, 4 );
2349
2350 SmallString<128> CommentString;
2351 raw_svector_ostream CommentOS(CommentString);
2352
2353 auto EmitComment = [&]() {
2354 OutStreamer->AddComment(CommentOS.str());
2355 CommentString.clear();
2356 };
2357
2358 auto EmitCommentAndValue = [&](uint64_t Value, int Size) {
2359 EmitComment();
2360 OutStreamer->emitIntValueInHexWithPadding(Value, Size);
2361 };
2362
2363 unsigned int Version = 0;
2364 CommentOS << "Version = " << Version;
2365 EmitCommentAndValue(Version, 1);
2366
2367
2368
2369
2370
2371
2374
2375 CommentOS << "Language = "
2377 EmitCommentAndValue(LanguageIdentifier, 1);
2378
2379
2380 uint32_t FirstHalfOfMandatoryField = 0;
2381
2382
2383
2384
2386
2387 const PPCFunctionInfo *FI = MF->getInfo();
2388 const MachineRegisterInfo &MRI = MF->getRegInfo();
2389
2390
2391 for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {
2392 if (MRI.isPhysRegUsed(Reg, true)) {
2394 break;
2395 }
2396 }
2397
2398#define GENBOOLCOMMENT(Prefix, V, Field) \
2399 CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \
2400 << #Field
2401
2402#define GENVALUECOMMENT(PrefixAndName, V, Field) \
2403 CommentOS << (PrefixAndName) << " = " \
2404 << static_cast(((V) & (TracebackTable::Field##Mask)) >> \
2405 (TracebackTable::Field##Shift))
2406
2407 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsGlobalLinkage);
2408 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);
2409 EmitComment();
2410
2411 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasTraceBackTableOffset);
2412 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsInternalProcedure);
2413 EmitComment();
2414
2415 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasControlledStorage);
2416 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsTOCless);
2417 EmitComment();
2418
2419 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsFloatingPointPresent);
2420 EmitComment();
2422 IsFloatingPointOperationLogOrAbortEnabled);
2423 EmitComment();
2424
2425 OutStreamer->emitIntValueInHexWithPadding(
2426 (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2427
2428
2430
2431 const PPCRegisterInfo *RegInfo = Subtarget->getRegisterInfo();
2433 if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))
2435
2436 const SmallVectorImpl &MustSaveCRs = FI->getMustSaveCRs();
2437 if (!MustSaveCRs.empty())
2439
2442
2443 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsInterruptHandler);
2444 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);
2445 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsAllocaUsed);
2446 EmitComment();
2447 GENVALUECOMMENT("OnConditionDirective", FirstHalfOfMandatoryField,
2448 OnConditionDirective);
2449 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsCRSaved);
2450 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsLRSaved);
2451 EmitComment();
2452 OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),
2453 1);
2454
2455
2456 uint32_t SecondHalfOfMandatoryField = 0;
2457
2460 : 0;
2461
2462 uint32_t FPRSaved = 0;
2463 for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) {
2464 if (MRI.isPhysRegModified(Reg)) {
2465 FPRSaved = PPC::F31 - Reg + 1;
2466 break;
2467 }
2468 }
2471 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, IsBackChainStored);
2472 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, IsFixup);
2473 GENVALUECOMMENT(", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);
2474 EmitComment();
2475 OutStreamer->emitIntValueInHexWithPadding(
2476 (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);
2477
2478
2479
2480
2481
2482 bool HasVectorInst = false;
2483 for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)
2484 if (MRI.isPhysRegUsed(Reg, true)) {
2485
2486 HasVectorInst = true;
2487 break;
2488 }
2489
2492
2493 uint16_t NumOfVRSaved = getNumberOfVRSaved();
2494 bool ShouldEmitEHBlock =
2496
2497 if (ShouldEmitEHBlock)
2499
2500 uint32_t GPRSaved = 0;
2501
2502
2503 unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;
2504 unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;
2505
2506 for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) {
2507 if (MRI.isPhysRegModified(Reg)) {
2508 GPRSaved = GPREnd - Reg + 1;
2509 break;
2510 }
2511 }
2512
2515
2516 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, HasExtensionTable);
2517 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasVectorInfo);
2518 GENVALUECOMMENT(", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);
2519 EmitComment();
2520 OutStreamer->emitIntValueInHexWithPadding(
2521 (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);
2522
2523
2525 SecondHalfOfMandatoryField |=
2528 GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,
2529 NumberOfFixedParms);
2530 EmitComment();
2531 OutStreamer->emitIntValueInHexWithPadding(
2532 (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2533
2534
2535
2536
2538
2540 SecondHalfOfMandatoryField |=
2543
2544 GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,
2545 NumberOfFloatingPointParms);
2546 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasParmsOnStack);
2547 EmitComment();
2548 OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,
2549 1);
2550
2551
2552
2553
2554 if (NumberOfFixedParms || NumberOfFPParms) {
2555 uint32_t ParmsTypeValue = FI->getParmsType();
2556
2557 Expected<SmallString<32>> ParmsType =
2560 ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,
2562 : XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms,
2563 NumberOfFPParms);
2564
2566 if (ParmsType) {
2567 CommentOS << "Parameter type = " << ParmsType.get();
2568 EmitComment();
2569 }
2570 OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,
2571 sizeof(ParmsTypeValue));
2572 }
2573
2574 OutStreamer->AddComment("Function size");
2576 MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(
2578 OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);
2579 }
2580
2581
2584
2587
2590 int16_t NameLength = Name.size();
2591 CommentOS << "Function name len = "
2592 << static_cast<unsigned int>(NameLength);
2593 EmitCommentAndValue(NameLength, 2);
2594 OutStreamer->AddComment("Function Name");
2595 OutStreamer->emitBytes(Name);
2596 }
2597
2600 OutStreamer->AddComment("AllocaUsed");
2601 OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg));
2602 }
2603
2605 uint16_t VRData = 0;
2606 if (NumOfVRSaved) {
2607
2610
2611
2612
2613
2614
2616 }
2617
2618
2621
2622
2626
2627 if (HasVectorInst)
2629
2630 GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved);
2633 EmitComment();
2634 OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);
2635
2636 GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms);
2638 EmitComment();
2639 OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);
2640
2642
2643 Expected<SmallString<32>> VecParmsType =
2646 if (VecParmsType) {
2647 CommentOS << "Vector Parameter type = " << VecParmsType.get();
2648 EmitComment();
2649 }
2650 OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,
2651 sizeof(VecParmTypeValue));
2652
2653 CommentOS << "Padding";
2654 EmitCommentAndValue(0, 2);
2655 }
2656
2657 uint8_t ExtensionTableFlag = 0;
2659 if (ShouldEmitEHBlock)
2660 ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;
2663 ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;
2664
2665 CommentOS << "ExtensionTableFlag = "
2667 EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag));
2668 }
2669
2670 if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {
2671 auto &Ctx = OutStreamer->getContext();
2674 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock);
2675 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
2676 getObjFileLowering().getTOCBaseSection())
2677 ->getQualNameSymbol();
2678 const MCExpr *Exp =
2681
2682 const DataLayout &DL = getDataLayout();
2683 OutStreamer->emitValueToAlignment(Align(4));
2684 OutStreamer->AddComment("EHInfo Table");
2685 OutStreamer->emitValue(Exp, DL.getPointerSize());
2686 }
2687#undef GENBOOLCOMMENT
2688#undef GENVALUECOMMENT
2689}
2690
2694
2695
2696
2697 .Case("llvm.used", true)
2698
2699 .Case("llvm.compiler.used", true)
2701}
2702
2705 .Cases({"llvm.global_ctors", "llvm.global_dtors"}, true)
2707}
2708
2709uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {
2711 return getAliasOffset(GA->getAliasee());
2715 if (!CBE)
2716 return 0;
2720 if ()
2722 return RHS->getValue();
2723 }
2724 return 0;
2725}
2726
2728
2729
2732 "GlobalVariables with an alignment requirement stricter than TOC entry "
2733 "size not supported by the toc data transformation.");
2734
2736 assert(GVType->isSized() && "A GlobalVariable's size must be known to be "
2737 "supported by the toc data transformation.");
2739 PointerSize * 8)
2741 "A GlobalVariable with size larger than a TOC entry is not currently "
2742 "supported by the toc data transformation.");
2745 "currently supported by the toc data transformation.");
2746}
2747
2748void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
2749
2751 return;
2752
2753
2754 if (GV->getSection() == "llvm.metadata")
2755 return;
2756
2757
2758
2762 TOCDataGlobalVars.push_back(GV);
2763 return;
2764 }
2765
2766 emitGlobalVariableHelper(GV);
2767}
2768
2769void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
2771 "Unhandled intrinsic global variable.");
2772
2775
2776 auto *GVSym = static_cast<MCSymbolXCOFF *>(getSymbol(GV));
2777
2779 emitLinkage(GV, GVSym);
2780 return;
2781 }
2782
2783 SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
2785 !GVKind.isThreadLocal())
2787 "not supported yet.");
2788
2789
2790 if (isVerbose()) {
2793 false, GV->getParent());
2794 OutStreamer->getCommentOS() << '\n';
2795 }
2796 }
2797
2798 auto *Csect = static_cast<MCSectionXCOFF *>(
2799 getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
2800
2801
2802 OutStreamer->switchSection(Csect);
2803
2805
2806
2809 Align Alignment = GV->getAlign().value_or(DL.getPreferredAlign(GV));
2811 GVSym->setStorageClass(
2813
2815 OutStreamer->emitZeros(Size);
2818 "BSS local toc-data already handled and TLS variables "
2819 "incompatible with XMC_TD");
2820 OutStreamer->emitXCOFFLocalCommonSymbol(
2821 OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,
2822 GVSym, Alignment);
2823 } else {
2824 OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
2825 }
2826 return;
2827 }
2828
2829 MCSymbol *EmittedInitSym = GVSym;
2830
2831
2832 emitLinkage(GV, EmittedInitSym);
2833 for (const GlobalAlias *GA : GOAliasMap[GV])
2834 emitLinkage(GA, getSymbol(GA));
2835
2836 emitAlignment(getGVAlignment(GV, DL), GV);
2837
2838
2839
2840 if (!TM.getDataSections() || GV->hasSection()) {
2842 OutStreamer->emitLabel(EmittedInitSym);
2843 }
2844
2845
2846 if (!GOAliasMap[GV].size()) {
2847 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());
2848 return;
2849 }
2850
2851
2852
2853 AliasMapTy AliasList;
2854 for (const GlobalAlias *GA : GOAliasMap[GV])
2855 AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);
2856
2857
2858 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),
2859 &AliasList);
2860}
2861
2862void PPCAIXAsmPrinter::emitFunctionDescriptor() {
2863 const DataLayout &DL = getDataLayout();
2864 const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;
2865
2866 MCSectionSubPair Current = OutStreamer->getCurrentSection();
2867
2868 OutStreamer->switchSection(
2869 static_cast<MCSymbolXCOFF *>(CurrentFnDescSym)->getRepresentedCsect());
2870
2871
2872 for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])
2873 OutStreamer->emitLabel(getSymbol(Alias));
2874
2875
2877 PointerSize);
2878
2879 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
2880 getObjFileLowering().getTOCBaseSection())
2881 ->getQualNameSymbol();
2883 PointerSize);
2884
2885 OutStreamer->emitIntValue(0, PointerSize);
2886
2887 OutStreamer->switchSection(Current.first, Current.second);
2888}
2889
2890void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
2891
2892
2894 PPCAsmPrinter::emitFunctionEntryLabel();
2895
2896
2897 for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])
2898 OutStreamer->emitLabel(
2899 getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));
2900}
2901
2902void PPCAIXAsmPrinter::emitPGORefs(Module &M) {
2903 if (!OutContext.hasXCOFFSection(
2904 "__llvm_prf_cnts",
2906 return;
2907
2908
2909
2910
2911
2912
2913
2914 bool HasNonZeroLengthPrfCntsSection = false;
2915 const DataLayout &DL = M.getDataLayout();
2916 for (GlobalVariable &GV : M.globals())
2917 if (GV.hasSection() && GV.getSection() == "__llvm_prf_cnts" &&
2918 DL.getTypeAllocSize(GV.getValueType()) > 0) {
2919 HasNonZeroLengthPrfCntsSection = true;
2920 break;
2921 }
2922
2923 if (HasNonZeroLengthPrfCntsSection) {
2924 MCSection *CntsSection = OutContext.getXCOFFSection(
2927 true);
2928
2929 OutStreamer->switchSection(CntsSection);
2930 if (OutContext.hasXCOFFSection(
2931 "__llvm_prf_data",
2933 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_data[RW]");
2934 OutStreamer->emitXCOFFRefDirective(S);
2935 }
2936 if (OutContext.hasXCOFFSection(
2937 "__llvm_prf_names",
2939 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_names[RO]");
2940 OutStreamer->emitXCOFFRefDirective(S);
2941 }
2942 if (OutContext.hasXCOFFSection(
2943 "__llvm_prf_vnds",
2945 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_vnds[RW]");
2946 OutStreamer->emitXCOFFRefDirective(S);
2947 }
2948 }
2949}
2950
2951void PPCAIXAsmPrinter::emitGCOVRefs() {
2952 if (!OutContext.hasXCOFFSection(
2953 "__llvm_gcov_ctr_section",
2955 return;
2956
2957 MCSection *CtrSection = OutContext.getXCOFFSection(
2960 true);
2961
2962 OutStreamer->switchSection(CtrSection);
2965 if (OutContext.hasXCOFFSection(
2966 "__llvm_covinit",
2967 XCOFF::CsectProperties(MappingClass, XCOFF::XTY_SD))) {
2968 const char *SymbolStr = TM.Options.XCOFFReadOnlyPointers
2969 ? "__llvm_covinit[RO]"
2970 : "__llvm_covinit[RW]";
2971 MCSymbol *S = OutContext.getOrCreateSymbol(SymbolStr);
2972 OutStreamer->emitXCOFFRefDirective(S);
2973 }
2974}
2975
2976void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
2977
2978
2979 if (M.empty() && TOCDataGlobalVars.empty())
2980 return;
2981
2982 emitPGORefs(M);
2983 emitGCOVRefs();
2984
2985
2986 OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
2987
2988 PPCTargetStreamer *TS =
2989 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
2990
2991 for (auto &I : TOC) {
2992 MCSectionXCOFF *TCEntry;
2993
2994
2995
2996
2997
2999 (Subtarget->hasAIXShLibTLSModelOpt() &&
3001 SmallString<128> Name;
3002 StringRef Prefix = ".";
3004 Name += static_cast<const MCSymbolXCOFF *>(I.first.first)
3005 ->getSymbolTableName();
3006 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
3007 TCEntry = static_cast<MCSectionXCOFF *>(
3008 getObjFileLowering().getSectionForTOCEntry(S, TM));
3009 } else {
3010 TCEntry = static_cast<MCSectionXCOFF *>(
3011 getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
3012 }
3013 OutStreamer->switchSection(TCEntry);
3014
3015 OutStreamer->emitLabel(I.second);
3016 TS->emitTCEntry(*I.first.first, I.first.second);
3017 }
3018
3019
3020
3021
3022 for (const auto *GV : TOCDataGlobalVars) {
3023 if (!GV->hasCommonLinkage())
3024 emitGlobalVariableHelper(GV);
3025 }
3026 for (const auto *GV : TOCDataGlobalVars) {
3027 if (GV->hasCommonLinkage())
3028 emitGlobalVariableHelper(GV);
3029 }
3030}
3031
3032bool PPCAIXAsmPrinter::doInitialization(Module &M) {
3033 const bool Result = PPCAsmPrinter::doInitialization(M);
3034
3035
3036 const Triple &Target = TM.getTargetTriple();
3038
3039
3040 for (auto &F : M) {
3043 if (FunCpuId > TargetCpuId)
3044 TargetCpuId = FunCpuId;
3045 }
3046
3047
3048
3049 if (!TargetCpuId) {
3050 StringRef TargetCPU = TM.getTargetCPU();
3053 }
3054
3055 PPCTargetStreamer *TS =
3056 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
3058
3059 auto setCsectAlignment = [this](const GlobalObject *GO) {
3060
3061 if (GO->isDeclarationForLinker())
3062 return;
3063
3064 SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);
3065 auto *Csect = static_cast<MCSectionXCOFF *>(
3066 getObjFileLowering().SectionForGlobal(GO, GOKind, TM));
3067
3068 Align GOAlign = getGVAlignment(GO, GO->getDataLayout());
3069 Csect->ensureMinAlignment(GOAlign);
3070 };
3071
3072
3073
3074
3075 uint64_t TLSVarAddress = 0;
3076 auto DL = M.getDataLayout();
3077 for (const auto &G : M.globals()) {
3078 if (G.isThreadLocal() && .isDeclaration()) {
3079 TLSVarAddress = alignTo(TLSVarAddress, getGVAlignment(&G, DL));
3080 TLSVarsToAddressMapping[&G] = TLSVarAddress;
3081 TLSVarAddress += DL.getTypeAllocSize(G.getValueType());
3082 }
3083 }
3084
3085
3086
3087
3088 for (const auto &G : M.globals()) {
3090 continue;
3091
3093
3094
3095 if (FormatIndicatorAndUniqueModId.empty()) {
3097 if (UniqueModuleId != "")
3098
3099
3100
3101 FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1);
3102 else {
3103
3104
3105 auto CurTime =
3106 std::chrono::duration_caststd::chrono::nanoseconds(
3107 std::chrono::steady_clock::now().time_since_epoch())
3108 .count();
3109 FormatIndicatorAndUniqueModId =
3113 }
3114 }
3115
3116 emitSpecialLLVMGlobal(&G);
3117 continue;
3118 }
3119
3120 setCsectAlignment(&G);
3121 std::optionalCodeModel::Model OptionalCodeModel = G.getCodeModel();
3122 if (OptionalCodeModel)
3124 *OptionalCodeModel);
3125 }
3126
3127 for (const auto &F : M)
3128 setCsectAlignment(&F);
3129
3130
3131 for (const auto &Alias : M.aliases()) {
3132 const GlobalObject *Aliasee = Alias.getAliaseeObject();
3133 if (!Aliasee)
3135 "alias without a base object is not yet supported on AIX");
3136
3138 report_fatal_error("Aliases to common variables are not allowed on AIX:"
3139 "\n\tAlias attribute for " +
3140 Alias.getName() + " is invalid because " +
3141 Aliasee->getName() + " is common.",
3142 false);
3143 }
3144
3145 const GlobalVariable *GVar =
3147 if (GVar) {
3148 std::optionalCodeModel::Model OptionalCodeModel = GVar->getCodeModel();
3149 if (OptionalCodeModel)
3151 *OptionalCodeModel);
3152 }
3153
3154 GOAliasMap[Aliasee].push_back(&Alias);
3155 }
3156
3158}
3159
3160void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {
3161 switch (MI->getOpcode()) {
3162 default:
3163 break;
3164 case PPC::TW:
3165 case PPC::TWI:
3166 case PPC::TD:
3167 case PPC::TDI: {
3168 if (MI->getNumOperands() < 5)
3169 break;
3170 const MachineOperand &LangMO = MI->getOperand(3);
3171 const MachineOperand &ReasonMO = MI->getOperand(4);
3172 if (!LangMO.isImm() || !ReasonMO.isImm())
3173 break;
3174 MCSymbol *TempSym = OutContext.createNamedTempSymbol();
3175 OutStreamer->emitLabel(TempSym);
3176 OutStreamer->emitXCOFFExceptDirective(
3177 CurrentFnSym, TempSym, LangMO.getImm(), ReasonMO.getImm(),
3178 Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 8
3179 : MI->getMF()->getInstructionCount() * 4,
3181 break;
3182 }
3183 case PPC::GETtlsMOD32AIX:
3184 case PPC::GETtlsMOD64AIX:
3185 case PPC::GETtlsTpointer32AIX:
3186 case PPC::GETtlsADDR64AIX:
3187 case PPC::GETtlsADDR32AIX: {
3188
3189
3192 ExtSymSDNodeSymbols.insert(TlsGetAddr);
3193 break;
3194 }
3195 case PPC::BL8:
3196 case PPC::BL:
3197 case PPC::BL8_NOP:
3198 case PPC::BL_NOP: {
3199 const MachineOperand &MO = MI->getOperand(0);
3201 auto *S = static_cast<MCSymbolXCOFF *>(
3202 OutContext.getOrCreateSymbol(MO.getSymbolName()));
3203 ExtSymSDNodeSymbols.insert(S);
3204 }
3205 } break;
3206 case PPC::BL_TLS:
3207 case PPC::BL8_TLS:
3208 case PPC::BL8_TLS_:
3209 case PPC::BL8_NOP_TLS:
3211 case PPC::TAILB:
3212 case PPC::TAILB8:
3213 case PPC::TAILBA:
3214 case PPC::TAILBA8:
3215 case PPC::TAILBCTR:
3216 case PPC::TAILBCTR8:
3217 if (MI->getOperand(0).isSymbol())
3218 report_fatal_error("Tail call for extern symbol not yet supported.");
3219 break;
3220 case PPC::DST:
3221 case PPC::DST64:
3222 case PPC::DSTT:
3223 case PPC::DSTT64:
3224 case PPC::DSTST:
3225 case PPC::DSTST64:
3226 case PPC::DSTSTT:
3227 case PPC::DSTSTT64:
3228 EmitToStreamer(
3229 *OutStreamer,
3230 MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));
3231 return;
3232 }
3233 return PPCAsmPrinter::emitInstruction(MI);
3234}
3235
3236bool PPCAIXAsmPrinter::doFinalization(Module &M) {
3237
3239
3240
3241
3242 auto *Sec = OutContext.getObjectFileInfo()->getTextSection();
3243 OutStreamer->switchSectionNoPrint(Sec);
3244 MCSymbol *Sym = Sec->getEndSymbol(OutContext);
3245 OutStreamer->emitLabel(Sym);
3246 }
3247
3248 for (MCSymbol *Sym : ExtSymSDNodeSymbols)
3249 OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern);
3250 return PPCAsmPrinter::doFinalization(M);
3251}
3252
3256
3257 if (P <= 20)
3258 return P;
3259
3260 if (P < 81)
3261 return 20 + (P - 20) * 16;
3262
3263 if (P <= 1124)
3264 return 1004 + (P - 81);
3265
3266 if (P < 64512)
3267 return 2047 + (P - 1124) * 33878;
3268
3269 return 2147482625u + (P - 64512);
3270}
3271
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3287
3288 std::string PrioritySuffix;
3291 return PrioritySuffix;
3292}
3293
3294void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL,
3295 const Constant *List, bool IsCtor) {
3297 preprocessXXStructorList(DL, List, Structors);
3298 if (Structors.empty())
3299 return;
3300
3301 unsigned Index = 0;
3302 for (Structor &S : Structors) {
3304 S.Func = CE->getOperand(0);
3305
3308 (IsCtor ? llvm::Twine("__sinit") : llvm::Twine("__sterm")) +
3310 llvm::Twine("_", FormatIndicatorAndUniqueModId) +
3313 }
3314}
3315
3316void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV,
3317 unsigned Encoding) {
3318 if (GV) {
3319 TOCEntryType GlobalType = TOCType_GlobalInternal;
3324 GlobalType = TOCType_GlobalExternal;
3325 MCSymbol *TypeInfoSym = TM.getSymbol(GV);
3326 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType);
3327 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(
3328 getObjFileLowering().getTOCBaseSection())
3329 ->getQualNameSymbol();
3330 auto &Ctx = OutStreamer->getContext();
3331 const MCExpr *Exp =
3334 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));
3335 } else
3336 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));
3337}
3338
3339
3340
3341static AsmPrinter *
3343 std::unique_ptr &&Streamer) {
3345 return new PPCAIXAsmPrinter(tm, std::move(Streamer));
3346
3347 return new PPCLinuxAsmPrinter(tm, std::move(Streamer));
3348}
3349
3350void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {
3351 const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");
3353 return;
3354
3355 std::string S;
3356 raw_string_ostream RSOS(S);
3357 for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
3359 assert(N->getNumOperands() == 1 &&
3360 "llvm.commandline metadata entry can have only one operand");
3362
3363
3364 RSOS << "@(#)opt " << MDS->getString() << "\n";
3365 RSOS.write('\0');
3366 }
3367 OutStreamer->emitXCOFFCInfoSym(".GCC.command.line", RSOS.str());
3368}
3369
3370char PPCAIXAsmPrinter::ID = 0;
3371
3373 "AIX PPC Assembly Printer", false, false)
3374
3375
3377LLVMInitializePowerPCAsmPrinter() {
3386}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static AMDGPUMCExpr::Specifier getSpecifier(unsigned MOFlags)
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_EXTERNAL_VISIBILITY
static bool hasDebugInfo(const MachineFunction *MF)
Module.h This file contains the declarations for the Module class.
static std::string getRegisterName(const TargetRegisterInfo *TRI, Register Reg)
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
Promote Memory to Register
static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type)
Definition PPCAsmPrinter.cpp:454
static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV)
Definition PPCAsmPrinter.cpp:2703
static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV)
Definition PPCAsmPrinter.cpp:2691
#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.
Definition PPCAsmPrinter.cpp:755
static void setOptionalCodeModel(MCSymbolXCOFF *XSym, CodeModel::Model CM)
Definition PPCAsmPrinter.cpp:497
static AsmPrinter * createPPCAsmPrinterPass(TargetMachine &tm, std::unique_ptr< MCStreamer > &&Streamer)
Definition PPCAsmPrinter.cpp:3342
static PPCAsmPrinter::TOCEntryType getTOCEntryTypeForMO(const MachineOperand &MO)
Definition PPCAsmPrinter.cpp:772
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
Definition PPCAsmPrinter.cpp:481
static std::string convertToSinitPriority(int Priority)
Definition PPCAsmPrinter.cpp:3272
static MCSymbol * createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc)
This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX.
Definition PPCAsmPrinter.cpp:661
#define GENVALUECOMMENT(PrefixAndName, V, Field)
static unsigned mapToSinitPriority(int P)
Definition PPCAsmPrinter.cpp:3253
static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV)
Definition PPCAsmPrinter.cpp:2727
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)
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)
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)
This class is intended to be used as a driving class for all asm writers.
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...
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.
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:
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
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...
StringRef getSection() const
Get the custom section of this global if it has one.
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.
bool hasCommonLinkage() const
bool hasAppendingLinkage() const
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ ExternalLinkage
Externally visible function.
@ AvailableExternallyLinkage
Available for inspection, not emission.
@ ExternalWeakLinkage
ExternalWeak linkage description.
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.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Opcode getOpcode() const
Get the kind of this binary expression.
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
const MCOperand & getOperand(unsigned i) const
static MCOperand createExpr(const MCExpr *Val)
MCRegister getReg() const
Returns the register number.
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
void setPerSymbolCodeModel(MCSymbolXCOFF::CodeModel Model)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
LLVM_ABI StringRef getString() const
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
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.
iterator find(const KeyT &Key)
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.
uint32_t getParmsType() const
MCSymbol * getPICOffsetSymbol(MachineFunction &MF) const
const SmallVectorImpl< Register > & getMustSaveCRs() const
unsigned getFloatingPointParmsNum() const
bool isAIXFuncUseTLSIEForLD() const
MCSymbol * getGlobalEPSymbol(MachineFunction &MF) const
MCSymbol * getLocalEPSymbol(MachineFunction &MF) const
unsigned getVectorParmsNum() const
int getVarArgsFrameIndex() const
bool usesTOCBasePtr() const
bool hasVectorParms() const
uint32_t getVecExtParmsType() const
MCSymbol * getTOCOffsetSymbol(MachineFunction &MF) const
unsigned getFixedParmsNum() const
static const char * getRegisterName(MCRegister Reg)
static bool hasTLSFlag(unsigned TF)
Register getFrameRegister(const MachineFunction &MF) const override
bool is32BitELFABI() 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.
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)
bool isThreadBSSLocal() const
static SectionKind getText()
static SectionKind getData()
bool isThreadLocal() const
bool isGlobalWriteableData() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
void push_back(const T &Elt)
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
StringRef - Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(std::initializer_list< StringLiteral > CaseStrings, T Value)
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.
bool isOSAIX() const
Tests whether the OS is AIX.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
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.
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.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
static LLVM_ABI Pid getProcessId()
Get the process's identifier.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
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...
@ MO_TPREL_PCREL_FLAG
MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TPREL_FLAG.
@ MO_GOT_TPREL_PCREL_FLAG
MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
@ MO_TLSGDM_FLAG
MO_TLSGDM_FLAG - If this bit is set the symbol reference is relative to the region handle of TLS Gene...
@ MO_TLSLD_FLAG
MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to TLS Local Dynamic model.
@ MO_TPREL_FLAG
MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to the thread pointer and the sy...
@ MO_GOT_TLSLD_PCREL_FLAG
MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
@ MO_TLSGD_FLAG
MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to TLS General Dynamic model for ...
@ MO_GOT_TLSGD_PCREL_FLAG
MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...
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)
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
LLVM_ABI SmallString< 32 > getExtendedTBTableFlagString(uint8_t Flag)
LLVM_ABI XCOFF::CFileCpuId getCpuID(StringRef CPU)
LLVM_ABI Expected< SmallString< 32 > > parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, unsigned FloatingParmsNum, unsigned VectorParmsNum)
LLVM_ABI Expected< SmallString< 32 > > parseParmsType(uint32_t Value, unsigned FixedParmsNum, unsigned FloatingParmsNum)
LLVM_ABI Expected< SmallString< 32 > > parseVectorParmsType(uint32_t Value, unsigned ParmsNum)
@ TCPU_INVALID
Invalid id - assumes POWER for old objects.
StorageMappingClass
Storage Mapping Class definitions.
@ XMC_RO
Read Only Constant.
@ XMC_TD
Scalar data item in the TOC.
LLVM_ABI StringRef getTCPUString(XCOFF::CFileCpuId TCPU)
LLVM_ABI StringRef getNameForTracebackTableLanguageId(TracebackTable::LanguageID LangId)
constexpr uint8_t AllocRegNo
@ XTY_SD
Csect definition for initialized storage.
@ XTY_ER
External reference.
initializer< Ty > init(const Ty &Val)
unsigned combineHashValue(unsigned a, unsigned b)
Simplistic combination of 32-bit hash values into 32-bit hash values.
constexpr uint64_t PointerSize
aarch64 pointer size.
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.
FunctionAddr VTableAddr Value
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
bool LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, MCOperand &OutMO, AsmPrinter &AP)
Target & getThePPC32Target()
std::string utostr(uint64_t X, bool isNeg=false)
auto dyn_cast_or_null(const Y &Val)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
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.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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.
Target & getThePPC64Target()
LLVM_ABI uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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.
Target & getThePPC32LETarget()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
std::pair< MCSection *, uint32_t > MCSectionSubPair
std::string itostr(int64_t X)
@ MCSA_Extern
.extern (XCOFF)
@ MCSA_Invalid
Not a valid directive.
Implement std::hash so that hash_code can be used in STL containers.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static bool isEqual(const TOCKey &A, const TOCKey &B)
Definition PPCAsmPrinter.cpp:121
std::pair< const MCSymbol *, PPCMCExpr::Specifier > TOCKey
Definition PPCAsmPrinter.cpp:110
static unsigned getHashValue(const TOCKey &PairVal)
Definition PPCAsmPrinter.cpp:116
static TOCKey getTombstoneKey()
Definition PPCAsmPrinter.cpp:113
static TOCKey getEmptyKey()
Definition PPCAsmPrinter.cpp:112
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.
static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn)
RegisterAsmPrinter - Register an AsmPrinter implementation for the given target.
static constexpr uint32_t FPRSavedMask
static constexpr uint16_t NumberOfVRSavedMask
static constexpr uint8_t NumberOfFloatingPointParmsShift
static constexpr uint32_t NumberOfFixedParmsMask
static constexpr uint16_t HasVMXInstructionMask
static constexpr uint32_t IsLRSavedMask
static constexpr uint16_t HasVarArgsMask
static constexpr uint32_t IsAllocaUsedMask
static constexpr uint16_t IsVRSavedOnStackMask
static constexpr uint16_t NumberOfVectorParmsMask
static constexpr uint32_t IsFloatingPointPresentMask
static constexpr uint32_t FPRSavedShift
static constexpr uint32_t NumberOfFloatingPointParmsMask
static constexpr uint32_t HasControlledStorageMask
static constexpr uint32_t HasExtensionTableMask
static constexpr uint32_t HasTraceBackTableOffsetMask
static constexpr uint32_t IsCRSavedMask
static constexpr uint8_t NumberOfFixedParmsShift
static constexpr uint32_t GPRSavedMask
static constexpr uint8_t NumberOfVectorParmsShift
static constexpr uint32_t HasParmsOnStackMask
static constexpr uint32_t IsFunctionNamePresentMask
static constexpr uint32_t IsBackChainStoredMask
static constexpr uint32_t IsInterruptHandlerMask
static constexpr uint32_t HasVectorInfoMask
static constexpr uint8_t NumberOfVRSavedShift
static constexpr uint32_t GPRSavedShift