86#define DEBUG_TYPE "asmprinter"
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.");
110 using TOCKey = std::pair<const MCSymbol *, PPCMCExpr::Specifier>;
129 Tag_GNU_Power_ABI_FP = 4,
130 Tag_GNU_Power_ABI_Vector = 8,
131 Tag_GNU_Power_ABI_Struct_Return = 12,
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,
139 Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,
140 Val_GNU_Power_ABI_LDBL_64 = 0b1000,
141 Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,
153 MapVector<std::pair<const MCSymbol *, PPCMCExpr::Specifier>,
MCSymbol *> TOC;
154 const PPCSubtarget *Subtarget =
nullptr;
159 MapVector<const GlobalValue *, uint64_t> TLSVarsToAddressMapping;
162 explicit PPCAsmPrinter(TargetMachine &TM,
163 std::unique_ptr<MCStreamer> Streamer,
char &
ID)
164 : AsmPrinter(TM, std::
move(Streamer),
ID) {}
166 StringRef getPassName()
const override {
return "PowerPC Assembly Printer"; }
169 TOCType_ConstantPool,
170 TOCType_GlobalExternal,
171 TOCType_GlobalInternal,
174 TOCType_BlockAddress,
178 MCSymbol *lookUpOrCreateTOCEntry(
const MCSymbol *Sym, TOCEntryType
Type,
181 bool doInitialization(
Module &M)
override {
187 const MCExpr *symbolWithSpecifier(
const MCSymbol *S,
194 void printOperand(
const MachineInstr *
MI,
unsigned OpNo, raw_ostream &O);
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;
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 {
217class PPCLinuxAsmPrinter :
public PPCAsmPrinter {
221 explicit PPCLinuxAsmPrinter(TargetMachine &TM,
222 std::unique_ptr<MCStreamer> Streamer)
223 : PPCAsmPrinter(TM, std::
move(Streamer), ID) {}
225 StringRef getPassName()
const override {
226 return "Linux PPC Assembly Printer";
229 void emitGNUAttributes(
Module &M);
231 void emitStartOfAsmFile(
Module &M)
override;
232 void emitEndOfAsmFile(
Module &)
override;
234 void emitFunctionEntryLabel()
override;
236 void emitFunctionBodyStart()
override;
237 void emitFunctionBodyEnd()
override;
241class PPCAIXAsmPrinter :
public PPCAsmPrinter {
245 SmallSetVector<MCSymbol *, 8> ExtSymSDNodeSymbols;
249 std::string FormatIndicatorAndUniqueModId;
253 DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
256 uint16_t getNumberOfVRSaved();
257 void emitTracebackTable();
261 void emitGlobalVariableHelper(
const GlobalVariable *);
264 uint64_t getAliasOffset(
const Constant *
C);
269 PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
270 : PPCAsmPrinter(TM, std::
move(Streamer), ID) {
271 if (MAI->isLittleEndian())
273 "cannot create AIX PPC Assembly Printer for a little-endian target");
276 StringRef getPassName()
const override {
return "AIX PPC Assembly Printer"; }
278 bool doInitialization(
Module &M)
override;
280 void emitXXStructorList(
const DataLayout &
DL,
const Constant *
List,
281 bool IsCtor)
override;
283 void SetupMachineFunction(MachineFunction &MF)
override;
285 void emitGlobalVariable(
const GlobalVariable *GV)
override;
287 void emitFunctionDescriptor()
override;
289 void emitFunctionEntryLabel()
override;
291 void emitFunctionBodyEnd()
override;
293 void emitPGORefs(
Module &M);
297 void emitEndOfAsmFile(
Module &)
override;
299 void emitLinkage(
const GlobalValue *GV, MCSymbol *GVSym)
const override;
303 bool doFinalization(
Module &M)
override;
305 void emitTTypeReference(
const GlobalValue *GV,
unsigned Encoding)
override;
307 void emitModuleCommandLines(
Module &M)
override;
309 void emitRefMetadata(
const GlobalObject *);
318 getSymbol(GV)->
print(O, MAI);
322void PPCAsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNo,
324 const DataLayout &
DL = getDataLayout();
325 const MachineOperand &MO =
MI->getOperand(OpNo);
345 O <<
DL.getPrivateGlobalPrefix() <<
"CPI" << getFunctionNumber() <<
'_'
352 PrintSymbolOperand(MO, O);
357 O <<
"<unknown operand type: " << (unsigned)MO.
getType() <<
">";
364bool PPCAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
365 const char *ExtraCode, raw_ostream &O) {
367 if (ExtraCode && ExtraCode[0]) {
368 if (ExtraCode[1] != 0)
return true;
370 switch (ExtraCode[0]) {
376 if (!
MI->getOperand(OpNo).isReg() ||
377 OpNo+1 ==
MI->getNumOperands() ||
378 !
MI->getOperand(OpNo+1).isReg())
385 if (
MI->getOperand(OpNo).isImm())
389 if(!
MI->getOperand(OpNo).isReg())
395 Reg = PPC::VSX32 + (
Reg - PPC::V0);
397 Reg = PPC::VSX32 + (
Reg - PPC::VF0);
413bool PPCAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNo,
414 const char *ExtraCode,
416 if (ExtraCode && ExtraCode[0]) {
417 if (ExtraCode[1] != 0)
return true;
419 switch (ExtraCode[0]) {
420 default:
return true;
422 O << getDataLayout().getPointerSize() <<
"(";
433 if (
MI->getOperand(OpNo).isImm())
444 assert(
MI->getOperand(OpNo).isReg());
449 assert(
MI->getOperand(OpNo).isReg());
459 case PPCAsmPrinter::TOCType_ConstantPool:
462 case PPCAsmPrinter::TOCType_GlobalInternal:
463 ++NumTOCGlobalInternal;
465 case PPCAsmPrinter::TOCType_GlobalExternal:
466 ++NumTOCGlobalExternal;
468 case PPCAsmPrinter::TOCType_JumpTable:
471 case PPCAsmPrinter::TOCType_ThreadLocal:
474 case PPCAsmPrinter::TOCType_BlockAddress:
475 ++NumTOCBlockAddress;
477 case PPCAsmPrinter::TOCType_EHBlock:
494 assert(GV &&
"expected global for MO_GlobalAddress");
515MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(
const MCSymbol *Sym,
519 auto [It,
Inserted] =
TOC.try_emplace({Sym, Spec});
525 TOCEntry = createTempSymbol(
"C");
529void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM,
const MachineInstr &
MI) {
530 unsigned NumNOPBytes =
MI.getOperand(1).getImm();
532 auto &Ctx = OutStreamer->getContext();
533 MCSymbol *MILabel = Ctx.createTempSymbol();
534 OutStreamer->emitLabel(MILabel);
537 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
540 const MachineBasicBlock &
MBB = *
MI.getParent();
543 while (NumNOPBytes > 0) {
544 if (MII ==
MBB.
end() || MII->isCall() ||
545 MII->getOpcode() == PPC::DBG_VALUE ||
546 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
547 MII->getOpcode() == TargetOpcode::STACKMAP)
554 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
555 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
560void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM,
const MachineInstr &
MI) {
561 auto &Ctx = OutStreamer->getContext();
562 MCSymbol *MILabel = Ctx.createTempSymbol();
563 OutStreamer->emitLabel(MILabel);
566 PatchPointOpers Opers(&
MI);
568 unsigned EncodedBytes = 0;
569 const MachineOperand &CalleeMO = Opers.getCallTarget();
571 if (CalleeMO.
isImm()) {
572 int64_t CallTarget = CalleeMO.
getImm();
574 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
575 "High 16 bits of call target should be zero.");
576 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
579 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)
581 .addImm((CallTarget >> 32) & 0xFFFF));
583 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC)
586 .addImm(32).addImm(16));
588 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8)
591 .addImm((CallTarget >> 16) & 0xFFFF));
593 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8)
596 .addImm(CallTarget & 0xFFFF));
600 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD)
602 .addImm(TOCSaveOffset)
612 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
615 .addReg(ScratchReg));
617 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
620 .addReg(ScratchReg));
624 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8)
625 .addReg(ScratchReg));
627 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8));
631 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
633 .addImm(TOCSaveOffset)
638 const GlobalValue *GValue = CalleeMO.
getGlobal();
639 MCSymbol *MOSymbol = getSymbol(GValue);
642 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP)
651 unsigned NumBytes = Opers.getNumPatchBytes();
652 assert(NumBytes >= EncodedBytes &&
653 "Patchpoint can't request size less than the length of a call.");
654 assert((NumBytes - EncodedBytes) % 4 == 0 &&
655 "Invalid number of NOP bytes requested!");
656 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
657 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
667 SymName =
".__tls_get_addr";
669 case PPC::GETtlsTpointer32AIX:
670 SymName =
".__get_tpointer";
672 case PPC::GETtlsMOD32AIX:
673 case PPC::GETtlsMOD64AIX:
674 SymName =
".__tls_get_mod";
680 ->getQualNameSymbol();
683void PPCAsmPrinter::EmitAIXTlsCallHelper(
const MachineInstr *
MI) {
685 "Only expecting to emit calls to get the thread pointer on AIX!");
689 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));
694void PPCAsmPrinter::emitTlsCall(
const MachineInstr *
MI,
697 unsigned Opcode = PPC::BL8_NOP_TLS;
699 assert(
MI->getNumOperands() >= 3 &&
"Expecting at least 3 operands from MI");
703 Opcode = PPC::BL8_NOTOC_TLS;
705 const Module *
M = MF->getFunction().getParent();
708 ((Subtarget->isPPC64() &&
MI->getOperand(0).getReg() == PPC::X3) ||
709 (!Subtarget->isPPC64() &&
MI->getOperand(0).getReg() == PPC::R3)) &&
710 "GETtls[ld]ADDR[32] must define GPR3");
712 ((Subtarget->isPPC64() &&
MI->getOperand(1).getReg() == PPC::X3) ||
713 (!Subtarget->isPPC64() &&
MI->getOperand(1).getReg() == PPC::R3)) &&
714 "GETtls[ld]ADDR[32] must read GPR3");
721 Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;
723 assert((
MI->getOpcode() == PPC::GETtlsMOD32AIX ||
724 MI->getOpcode() == PPC::GETtlsMOD64AIX ||
725 (
MI->getOperand(2).isReg() &&
726 MI->getOperand(2).getReg() == VarOffsetReg)) &&
727 "GETtls[ld]ADDR[32] must read GPR4");
728 EmitAIXTlsCallHelper(
MI);
732 MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol(
"__tls_get_addr");
740 if (Kind ==
PPC::S_PLT && Subtarget->isSecurePlt() &&
744 const MachineOperand &MO =
MI->getOperand(2);
745 const GlobalValue *GValue = MO.
getGlobal();
746 MCSymbol *MOSymbol = getSymbol(GValue);
748 EmitToStreamer(*OutStreamer,
749 MCInstBuilder(Subtarget->isPPC64() ? Opcode
750 : (
unsigned)PPC::BL_TLS)
773static PPCAsmPrinter::TOCEntryType
778 return PPCAsmPrinter::TOCType_ThreadLocal;
787 return PPCAsmPrinter::TOCType_GlobalExternal;
789 return PPCAsmPrinter::TOCType_GlobalInternal;
792 return PPCAsmPrinter::TOCType_ConstantPool;
794 return PPCAsmPrinter::TOCType_JumpTable;
796 return PPCAsmPrinter::TOCType_BlockAddress;
802const MCExpr *PPCAsmPrinter::symbolWithSpecifier(
const MCSymbol *S,
810void PPCAsmPrinter::emitInstruction(
const MachineInstr *
MI) {
811 PPC_MC::verifyInstructionPredicates(
MI->getOpcode(),
812 getSubtargetInfo().getFeatureBits());
815 const bool IsPPC64 = Subtarget->isPPC64();
816 const bool IsAIX = Subtarget->
isAIXABI();
817 const bool HasAIXSmallLocalTLS = Subtarget->hasAIXSmallLocalExecTLS() ||
818 Subtarget->hasAIXSmallLocalDynamicTLS();
819 const Module *
M = MF->getFunction().getParent();
824 if (!
MI->isInlineAsm()) {
825 for (
const MachineOperand &MO:
MI->operands()) {
828 if (Subtarget->hasSPE()) {
846 auto getTOCRelocAdjustedExprForXCOFF = [
this](
const MCExpr *Expr,
847 ptrdiff_t OriginalOffset) {
854 ptrdiff_t Adjustment =
860 auto getTOCEntryLoadingExprForXCOFF =
861 [IsPPC64, getTOCRelocAdjustedExprForXCOFF,
862 this](
const MCSymbol *MOSymbol,
const MCExpr *Expr,
864 const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
865 const auto TOCEntryIter =
TOC.find({MOSymbol, VK});
867 "Could not find the TOC entry for this symbol.");
868 const ptrdiff_t EntryDistanceFromTOCBase =
869 (TOCEntryIter -
TOC.begin()) * EntryByteSize;
870 constexpr int16_t PositiveTOCRange = INT16_MAX;
872 if (EntryDistanceFromTOCBase > PositiveTOCRange)
873 return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);
885 assert(MO.
isGlobal() &&
"Only expecting a global MachineOperand here!\n");
893 PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
897 dbgs() <<
"Current function uses IE access for default LD vars.\n");
920 switch (
MI->getOpcode()) {
922 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
924 "AIX does not support patchable function entry!");
927 (void)
F.getFnAttribute(
"patchable-function-entry")
929 .getAsInteger(10, Num);
935 case TargetOpcode::DBG_VALUE:
937 case TargetOpcode::STACKMAP:
938 return LowerSTACKMAP(SM, *
MI);
939 case TargetOpcode::PATCHPOINT:
940 return LowerPATCHPOINT(SM, *
MI);
942 case PPC::MoveGOTtoLR: {
950 OutContext.getOrCreateSymbol(StringRef(
"_GLOBAL_OFFSET_TABLE_"));
956 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));
959 case PPC::MovePCtoLR:
960 case PPC::MovePCtoLR8: {
965 MCSymbol *PICBase = MF->getPICBaseSymbol();
968 EmitToStreamer(*OutStreamer,
969 MCInstBuilder(PPC::BCLalways)
975 OutStreamer->emitLabel(PICBase);
978 case PPC::UpdateGBR: {
987 if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
989 MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
998 const MCExpr *DeltaHi =
1002 MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));
1004 const MCExpr *DeltaLo =
1008 MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));
1012 MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(*MF);
1019 const MCOperand PICR = TmpInst.
getOperand(0);
1026 EmitToStreamer(*OutStreamer, TmpInst);
1032 EmitToStreamer(*OutStreamer, TmpInst);
1043 const MachineOperand &MO =
MI->getOperand(1);
1045 "Invalid operand for LWZtoc.");
1053 const MCExpr *
Exp = symbolWithSpecifier(MOSymbol,
PPC::S_GOT);
1055 EmitToStreamer(*OutStreamer, TmpInst);
1074 "This pseudo should only be selected for 32-bit small code model.");
1075 Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
1080 OutStreamer->getCommentOS() << MO <<
'\n';
1081 EmitToStreamer(*OutStreamer, TmpInst);
1088 OutContext.getOrCreateSymbol(Twine(
".LTOC")), OutContext);
1091 EmitToStreamer(*OutStreamer, TmpInst);
1095 case PPC::ADDItoc8: {
1097 "PseudoOp only valid for small code model AIX");
1103 TmpInst.
setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
1105 const MachineOperand &MO =
MI->getOperand(2);
1114 EmitToStreamer(*OutStreamer, TmpInst);
1127 const MachineOperand &MO =
MI->getOperand(1);
1129 "Invalid operand!");
1143 const MCExpr *
Exp = symbolWithSpecifier(TOCEntry, VKExpr);
1145 IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);
1148 if (isVerbose() && IsAIX)
1149 OutStreamer->getCommentOS() << MO <<
'\n';
1150 EmitToStreamer(*OutStreamer, TmpInst);
1153 case PPC::ADDIStocHA: {
1154 const MachineOperand &MO =
MI->getOperand(2);
1157 "Invalid operand for ADDIStocHA.");
1158 assert((IsAIX && !IsPPC64 &&
1160 "This pseudo should only be selected for 32-bit large code model on"
1180 if ( {
1192 const MCExpr *
Exp = symbolWithSpecifier(MOSymbol,
PPC::S_U);
1194 EmitToStreamer(*OutStreamer, TmpInst);
1197 case PPC::LWZtocL: {
1198 const MachineOperand &MO =
MI->getOperand(1);
1201 "Invalid operand for LWZtocL.");
1202 assert(IsAIX && !IsPPC64 &&
1204 "This pseudo should only be selected for 32-bit large code model on"
1224 const MCExpr *
Exp = symbolWithSpecifier(TOCEntry,
PPC::S_L);
1226 EmitToStreamer(*OutStreamer, TmpInst);
1229 case PPC::ADDIStocHA8: {
1239 const MachineOperand &MO =
MI->getOperand(2);
1241 "Invalid operand for ADDIStocHA8!");
1247 const bool GlobalToc =
1259 const MCExpr *
Exp = symbolWithSpecifier(MOSymbol, VK);
1268 EmitToStreamer(*OutStreamer, TmpInst);
1281 const MachineOperand &MO =
MI->getOperand(1);
1284 "Invalid operand for LDtocL!");
1288 "LDtocL used on symbol that could be accessed directly is "
1289 "invalid. Must match ADDIStocHA8."));
1300 const MCExpr *
Exp = symbolWithSpecifier(MOSymbol, VK);
1302 EmitToStreamer(*OutStreamer, TmpInst);
1306 case PPC::ADDItocL8: {
1310 unsigned Op =
MI->getOpcode();
1314 TmpInst.
setOpcode(
Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8)
1317 const MachineOperand &MO =
MI->getOperand(2);
1320 : MO.
isGlobal() &&
"Invalid operand for ADDItocL8.");
1322 "Interposable definitions must use indirect accesses.");
1331 EmitToStreamer(*OutStreamer, TmpInst);
1334 case PPC::ADDISgotTprelHA: {
1337 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1338 const MachineOperand &MO =
MI->getOperand(2);
1339 const GlobalValue *GValue = MO.
getGlobal();
1340 MCSymbol *MOSymbol = getSymbol(GValue);
1341 const MCExpr *SymGotTprel =
1343 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1344 .addReg(
MI->getOperand(0).getReg())
1345 .addReg(
MI->getOperand(1).getReg())
1346 .addExpr(SymGotTprel));
1349 case PPC::LDgotTprelL:
1350 case PPC::LDgotTprelL32: {
1355 TmpInst.
setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);
1356 const MachineOperand &MO =
MI->getOperand(1);
1357 const GlobalValue *GValue = MO.
getGlobal();
1358 MCSymbol *MOSymbol = getSymbol(GValue);
1359 const MCExpr *
Exp = symbolWithSpecifier(
1362 EmitToStreamer(*OutStreamer, TmpInst);
1366 case PPC::PPC32PICGOT: {
1367 MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(StringRef(
"_GLOBAL_OFFSET_TABLE_"));
1368 MCSymbol *GOTRef = OutContext.createTempSymbol();
1369 MCSymbol *NextInstr = OutContext.createTempSymbol();
1371 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL)
1375 const MCExpr *OffsExpr =
1379 OutStreamer->emitLabel(GOTRef);
1380 OutStreamer->emitValue(OffsExpr, 4);
1381 OutStreamer->emitLabel(NextInstr);
1382 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)
1383 .addReg(
MI->getOperand(0).getReg()));
1384 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)
1385 .addReg(
MI->getOperand(1).getReg())
1387 .addReg(
MI->getOperand(0).getReg()));
1388 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4)
1389 .addReg(
MI->getOperand(0).getReg())
1390 .addReg(
MI->getOperand(1).getReg())
1391 .addReg(
MI->getOperand(0).getReg()));
1394 case PPC::PPC32GOT: {
1396 OutContext.getOrCreateSymbol(StringRef(
"_GLOBAL_OFFSET_TABLE_"));
1397 const MCExpr *SymGotTlsL =
1399 const MCExpr *SymGotTlsHA =
1401 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI)
1402 .addReg(
MI->getOperand(0).getReg())
1403 .addExpr(SymGotTlsL));
1404 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
1405 .addReg(
MI->getOperand(0).getReg())
1406 .addReg(
MI->getOperand(0).getReg())
1407 .addExpr(SymGotTlsHA));
1410 case PPC::ADDIStlsgdHA: {
1413 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1414 const MachineOperand &MO =
MI->getOperand(2);
1415 const GlobalValue *GValue = MO.
getGlobal();
1416 MCSymbol *MOSymbol = getSymbol(GValue);
1417 const MCExpr *SymGotTlsGD =
1419 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1420 .addReg(
MI->getOperand(0).getReg())
1421 .addReg(
MI->getOperand(1).getReg())
1422 .addExpr(SymGotTlsGD));
1425 case PPC::ADDItlsgdL:
1428 case PPC::ADDItlsgdL32: {
1431 const MachineOperand &MO =
MI->getOperand(2);
1432 const GlobalValue *GValue = MO.
getGlobal();
1433 MCSymbol *MOSymbol = getSymbol(GValue);
1434 const MCExpr *SymGotTlsGD = symbolWithSpecifier(
1436 EmitToStreamer(*OutStreamer,
1437 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1438 .addReg(
MI->getOperand(0).getReg())
1439 .addReg(
MI->getOperand(1).getReg())
1440 .addExpr(SymGotTlsGD));
1443 case PPC::GETtlsMOD32AIX:
1444 case PPC::GETtlsMOD64AIX:
1448 case PPC::GETtlsADDR:
1451 case PPC::GETtlsADDRPCREL:
1452 case PPC::GETtlsADDR32AIX:
1453 case PPC::GETtlsADDR64AIX:
1457 case PPC::GETtlsADDR32: {
1463 case PPC::GETtlsTpointer32AIX: {
1466 EmitAIXTlsCallHelper(
MI);
1469 case PPC::ADDIStlsldHA: {
1472 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1473 const MachineOperand &MO =
MI->getOperand(2);
1474 const GlobalValue *GValue = MO.
getGlobal();
1475 MCSymbol *MOSymbol = getSymbol(GValue);
1476 const MCExpr *SymGotTlsLD =
1478 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
1479 .addReg(
MI->getOperand(0).getReg())
1480 .addReg(
MI->getOperand(1).getReg())
1481 .addExpr(SymGotTlsLD));
1484 case PPC::ADDItlsldL:
1487 case PPC::ADDItlsldL32: {
1490 const MachineOperand &MO =
MI->getOperand(2);
1491 const GlobalValue *GValue = MO.
getGlobal();
1492 MCSymbol *MOSymbol = getSymbol(GValue);
1493 const MCExpr *SymGotTlsLD = symbolWithSpecifier(
1495 EmitToStreamer(*OutStreamer,
1496 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1497 .addReg(
MI->getOperand(0).getReg())
1498 .addReg(
MI->getOperand(1).getReg())
1499 .addExpr(SymGotTlsLD));
1502 case PPC::GETtlsldADDR:
1505 case PPC::GETtlsldADDRPCREL:
1506 case PPC::GETtlsldADDR32: {
1512 case PPC::ADDISdtprelHA:
1515 case PPC::ADDISdtprelHA32: {
1518 const MachineOperand &MO =
MI->getOperand(2);
1519 const GlobalValue *GValue = MO.
getGlobal();
1520 MCSymbol *MOSymbol = getSymbol(GValue);
1524 MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)
1525 .addReg(
MI->getOperand(0).getReg())
1526 .addReg(
MI->getOperand(1).getReg())
1527 .addExpr(SymDtprel));
1530 case PPC::PADDIdtprel: {
1533 const MachineOperand &MO =
MI->getOperand(2);
1534 const GlobalValue *GValue = MO.
getGlobal();
1535 MCSymbol *MOSymbol = getSymbol(GValue);
1536 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol,
PPC::S_DTPREL);
1537 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8)
1538 .addReg(
MI->getOperand(0).getReg())
1539 .addReg(
MI->getOperand(1).getReg())
1540 .addExpr(SymDtprel));
1544 case PPC::ADDIdtprelL:
1547 case PPC::ADDIdtprelL32: {
1550 const MachineOperand &MO =
MI->getOperand(2);
1551 const GlobalValue *GValue = MO.
getGlobal();
1552 MCSymbol *MOSymbol = getSymbol(GValue);
1554 EmitToStreamer(*OutStreamer,
1555 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
1556 .addReg(
MI->getOperand(0).getReg())
1557 .addReg(
MI->getOperand(1).getReg())
1558 .addExpr(SymDtprel));
1563 if (!Subtarget->hasMFOCRF()) {
1566 unsigned NewOpcode =
1567 MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;
1568 OutStreamer->AddComment(PPCInstPrinter::
1570 EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)
1571 .addReg(
MI->getOperand(0).getReg()));
1577 if (!Subtarget->hasMFOCRF()) {
1580 unsigned NewOpcode =
1581 MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
1582 unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
1583 ->getEncodingValue(
MI->getOperand(0).getReg());
1584 OutStreamer->AddComment(PPCInstPrinter::
1586 EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)
1588 .addReg(
MI->getOperand(1).getReg()));
1598 unsigned OpNum = (
MI->getOpcode() == PPC::STD) ? 2 : 1;
1602 for (
const MachineOperand &TempMO :
MI->operands()) {
1605 TempMO.getOperandNo() == 1)
1608 const MachineOperand &MO =
MI->getOperand(OpNum);
1642 if (!HasAIXSmallLocalTLS)
1644 bool IsMIADDI8 =
MI->getOpcode() == PPC::ADDI8;
1645 unsigned OpNum = IsMIADDI8 ? 2 : 1;
1646 const MachineOperand &MO =
MI->getOperand(OpNum);
1653 const MCExpr *Expr = getAdjustedFasterLocalExpr(MO, MO.
getOffset());
1661 EmitToStreamer(*OutStreamer, TmpInst);
1667 case PPC::PseudoEIEIO: {
1670 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1673 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1674 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));
1680 EmitToStreamer(*OutStreamer, TmpInst);
1690PPCAsmPrinter::getAdjustedFasterLocalExpr(
const MachineOperand &MO,
1697 assert(MO.
isGlobal() &&
"Only expecting a global MachineOperand here!");
1698 const GlobalValue *GValue = MO.
getGlobal();
1701 "Only local-[exec|dynamic] accesses are handled!");
1707 const auto TLSVarsMapEntryIter = TLSVarsToAddressMapping.
find(GValue);
1708 if (TLSVarsMapEntryIter == TLSVarsToAddressMapping.
end())
1709 assert(IsGlobalADeclaration &&
1710 "Only expecting to find extern TLS variables not present in the TLS "
1711 "variable-to-address map!");
1713 unsigned TLSVarAddress =
1714 IsGlobalADeclaration ? 0 : TLSVarsMapEntryIter->second;
1715 ptrdiff_t FinalAddress = (TLSVarAddress +
Offset);
1727 if (FinalAddress >= 32768) {
1734 ptrdiff_t Delta = ((FinalAddress + 32768) & ~0xFFFF);
1736 [[maybe_unused]] ptrdiff_t InstDisp = TLSVarAddress +
Offset - Delta;
1738 ((InstDisp < 32768) && (InstDisp >= -32768)) &&
1739 "Expecting the instruction displacement for local-[exec|dynamic] TLS "
1740 "variables to be between [-32768, 32768)!");
1748void PPCLinuxAsmPrinter::emitGNUAttributes(
Module &M) {
1750 Metadata *MD =
M.getModuleFlag(
"float-abi");
1756 if (flt ==
"doubledouble")
1757 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1758 Val_GNU_Power_ABI_HardFloat_DP |
1759 Val_GNU_Power_ABI_LDBL_IBM128);
1760 else if (flt ==
"ieeequad")
1761 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1762 Val_GNU_Power_ABI_HardFloat_DP |
1763 Val_GNU_Power_ABI_LDBL_IEEE128);
1764 else if (flt ==
"ieeedouble")
1765 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1766 Val_GNU_Power_ABI_HardFloat_DP |
1767 Val_GNU_Power_ABI_LDBL_64);
1770void PPCLinuxAsmPrinter::emitInstruction(
const MachineInstr *
MI) {
1771 if (!Subtarget->isPPC64())
1772 return PPCAsmPrinter::emitInstruction(
MI);
1774 switch (
MI->getOpcode()) {
1777 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1792 (void)
F.getFnAttribute(
"patchable-function-entry")
1794 .getAsInteger(10, Num);
1796 if (!MAI->isLittleEndian() || Num)
1798 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1799 MCSymbol *EndOfSled = OutContext.createTempSymbol();
1800 OutStreamer->emitLabel(BeginOfSled);
1801 EmitToStreamer(*OutStreamer,
1802 MCInstBuilder(PPC::B).addExpr(
1804 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1807 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1808 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1809 EmitToStreamer(*OutStreamer,
1810 MCInstBuilder(PPC::BL8_NOP)
1812 OutContext.getOrCreateSymbol(
"__xray_FunctionEntry"),
1814 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1815 OutStreamer->emitLabel(EndOfSled);
1816 recordSled(BeginOfSled, *
MI, SledKind::FUNCTION_ENTER, 2);
1819 case TargetOpcode::PATCHABLE_RET: {
1820 unsigned RetOpcode =
MI->getOperand(0).getImm();
1830 if (RetOpcode == PPC::BCCLR) {
1831 IsConditional =
true;
1832 }
else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
1833 RetOpcode == PPC::TCRETURNai8) {
1835 }
else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
1836 IsConditional =
false;
1838 EmitToStreamer(*OutStreamer, RetInst);
1843 if (IsConditional) {
1862 FallthroughLabel = OutContext.createTempSymbol();
1865 MCInstBuilder(PPC::BCC)
1868 .addReg(
MI->getOperand(2).getReg())
1885 OutStreamer->emitCodeAlignment(
Align(8), &getSubtargetInfo());
1886 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1887 OutStreamer->emitLabel(BeginOfSled);
1888 EmitToStreamer(*OutStreamer, RetInst);
1889 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
1892 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1893 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1894 EmitToStreamer(*OutStreamer,
1895 MCInstBuilder(PPC::BL8_NOP)
1897 OutContext.getOrCreateSymbol(
"__xray_FunctionExit"),
1899 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1900 EmitToStreamer(*OutStreamer, RetInst);
1902 OutStreamer->emitLabel(FallthroughLabel);
1903 recordSled(BeginOfSled, *
MI, SledKind::FUNCTION_EXIT, 2);
1906 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1908 case TargetOpcode::PATCHABLE_TAIL_CALL:
1912 "around this assert.");
1914 return PPCAsmPrinter::emitInstruction(
MI);
1917void PPCLinuxAsmPrinter::emitStartOfAsmFile(
Module &M) {
1918 if (
static_cast<const PPCTargetMachine &
>(TM).isELFv2ABI()) {
1919 PPCTargetStreamer *TS =
1920 static_cast<PPCTargetStreamer *
>(OutStreamer->getTargetStreamer());
1924 if (
static_cast<const PPCTargetMachine &
>(TM).isPPC64() ||
1925 !isPositionIndependent())
1931 OutStreamer->switchSection(OutContext.getELFSection(
1934 MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(
".LTOC"));
1935 MCSymbol *CurrentPos = OutContext.createTempSymbol();
1937 OutStreamer->emitLabel(CurrentPos);
1941 const MCExpr *tocExpr =
1946 OutStreamer->emitAssignment(TOCSym, tocExpr);
1948 OutStreamer->switchSection(getObjFileLowering().getTextSection());
1951void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {
1953 if (!Subtarget->isPPC64() &&
1954 (!isPositionIndependent() ||
1958 if (!Subtarget->isPPC64()) {
1959 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
1960 if (PPCFI->
usesPICBase() && !Subtarget->isSecurePlt()) {
1962 MCSymbol *PICBase = MF->getPICBaseSymbol();
1963 OutStreamer->emitLabel(RelocSymbol);
1965 const MCExpr *OffsExpr =
1971 OutStreamer->emitValue(OffsExpr, 4);
1972 OutStreamer->emitLabel(CurrentFnSym);
1985 && !MF->getRegInfo().use_empty(PPC::X2)) {
1986 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
1988 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(
".TOC."));
1990 const MCExpr *TOCDeltaExpr =
1997 OutStreamer->emitValue(TOCDeltaExpr, 8);
2004 MCSectionELF *
Section = OutStreamer->getContext().getELFSection(
2006 OutStreamer->switchSection(Section);
2007 OutStreamer->emitLabel(CurrentFnSym);
2008 OutStreamer->emitValueToAlignment(
Align(8));
2009 MCSymbol *Symbol1 = CurrentFnSymForSize;
2014 MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(
".TOC."));
2016 OutStreamer->emitValue(
2019 OutStreamer->emitIntValue(0, 8 );
2020 OutStreamer->switchSection(Current.first, Current.second);
2023void PPCLinuxAsmPrinter::emitEndOfAsmFile(
Module &M) {
2024 const DataLayout &
DL = getDataLayout();
2026 bool isPPC64 =
DL.getPointerSizeInBits() == 64;
2028 PPCTargetStreamer *TS =
2029 static_cast<PPCTargetStreamer *
>(OutStreamer->getTargetStreamer());
2035 if (
static_cast<const PPCTargetMachine &
>(TM).hasGlibcHWCAPAccess())
2036 OutStreamer->emitSymbolValue(
2037 GetExternalSymbolSymbol(
"__parse_hwcap_and_convert_at_platform"),
2038 MAI->getCodePointerSize());
2039 emitGNUAttributes(M);
2042 const char *
Name = isPPC64 ?
".toc" :
".got2";
2043 MCSectionELF *
Section = OutContext.getELFSection(
2045 OutStreamer->switchSection(Section);
2047 OutStreamer->emitValueToAlignment(
Align(4));
2049 for (
const auto &TOCMapPair : TOC) {
2050 const MCSymbol *
const TOCEntryTarget = TOCMapPair.first.first;
2051 MCSymbol *
const TOCEntryLabel = TOCMapPair.second;
2053 OutStreamer->emitLabel(TOCEntryLabel);
2055 TS->
emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);
2057 OutStreamer->emitSymbolValue(TOCEntryTarget, 4);
2061 PPCAsmPrinter::emitEndOfAsmFile(M);
2065void PPCLinuxAsmPrinter::emitFunctionBodyStart() {
2097 const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
2098 const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||
2099 !MF->getRegInfo().use_empty(PPC::R2);
2108 if (NonPCrelGEPRequired || PCrelGEPRequired) {
2113 OutStreamer->emitLabel(GlobalEntryLabel);
2114 const MCSymbolRefExpr *GlobalEntryLabelExp =
2118 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(
".TOC."));
2119 const MCExpr *TOCDeltaExpr =
2121 GlobalEntryLabelExp, OutContext);
2123 const MCExpr *TOCDeltaHi =
2125 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
2128 .addExpr(TOCDeltaHi));
2130 const MCExpr *TOCDeltaLo =
2132 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
2135 .addExpr(TOCDeltaLo));
2138 const MCExpr *TOCOffsetDeltaExpr =
2140 GlobalEntryLabelExp, OutContext);
2142 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)
2144 .addExpr(TOCOffsetDeltaExpr)
2146 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)
2153 OutStreamer->emitLabel(LocalEntryLabel);
2154 const MCSymbolRefExpr *LocalEntryLabelExp =
2156 const MCExpr *LocalOffsetExp =
2158 GlobalEntryLabelExp, OutContext);
2160 PPCTargetStreamer *TS =
2161 static_cast<PPCTargetStreamer *
>(OutStreamer->getTargetStreamer());
2186 if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||
2187 MF->hasInlineAsm() || (!PPCFI->
usesTOCBasePtr() && UsesX2OrR2)) {
2188 PPCTargetStreamer *TS =
2189 static_cast<PPCTargetStreamer *
>(OutStreamer->getTargetStreamer());
2199void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
2207 if (Subtarget->isPPC64()) {
2208 OutStreamer->emitIntValue(0, 4);
2209 OutStreamer->emitIntValue(0, 8);
2213char PPCLinuxAsmPrinter::ID = 0;
2216 "Linux PPC Assembly Printer",
false,
false)
2221 switch (GV->getLinkage()) {
2222 case GlobalValue::ExternalLinkage:
2223 LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;
2225 case GlobalValue::LinkOnceAnyLinkage:
2226 case GlobalValue::LinkOnceODRLinkage:
2227 case GlobalValue::WeakAnyLinkage:
2228 case GlobalValue::WeakODRLinkage:
2229 case GlobalValue::ExternalWeakLinkage:
2230 LinkageAttr = MCSA_Weak;
2232 case GlobalValue::AvailableExternallyLinkage:
2233 LinkageAttr = MCSA_Extern;
2235 case GlobalValue::PrivateLinkage:
2237 case GlobalValue::InternalLinkage:
2238 assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&
2239 "InternalLinkage should not have other visibility setting.");
2240 LinkageAttr = MCSA_LGlobal;
2242 case GlobalValue::AppendingLinkage:
2243 llvm_unreachable(
"Should never emit this");
2244 case GlobalValue::CommonLinkage:
2245 llvm_unreachable(
"CommonLinkage of XCOFF should not come to this path");
2251 if (!TM.getIgnoreXCOFFVisibility()) {
2252 if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())
2254 "Cannot not be both dllexport and non-default visibility");
2255 switch (GV->getVisibility()) {
2258 case GlobalValue::DefaultVisibility:
2259 if (GV->hasDLLExportStorageClass())
2260 VisibilityAttr = MAI->getExportedVisibilityAttr();
2262 case GlobalValue::HiddenVisibility:
2263 VisibilityAttr = MAI->getHiddenVisibilityAttr();
2265 case GlobalValue::ProtectedVisibility:
2266 VisibilityAttr = MAI->getProtectedVisibilityAttr();
2276 OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
2280void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
2282 auto *FnDescSec =
static_cast<MCSectionXCOFF *
>(
2283 getObjFileLowering().getSectionForFunctionDescriptor(&MF.
getFunction(),
2285 FnDescSec->setAlignment(
Align(Subtarget->isPPC64() ? 8 : 4));
2287 CurrentFnDescSym = FnDescSec->getQualNameSymbol();
2292uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {
2296 const PPCSubtarget &Subtarget = MF->
getSubtarget<PPCSubtarget>();
2297 if (Subtarget.
isAIXABI() && Subtarget.hasAltivec() &&
2298 TM.getAIXExtendedAltivecABI()) {
2300 for (
unsigned Reg = PPC::V20;
Reg <= PPC::V31; ++
Reg)
2301 if (
MRI.isPhysRegModified(
Reg))
2303 return PPC::V31 -
Reg + 1;
2308void PPCAIXAsmPrinter::emitFunctionBodyEnd() {
2310 if (!TM.getXCOFFTracebackTable())
2313 emitTracebackTable();
2321 (getNumberOfVRSaved() > 0)) {
2323 OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());
2326 OutStreamer->emitLabel(EHInfoLabel);
2329 OutStreamer->emitInt32(0);
2331 const DataLayout &
DL = MMI->getModule()->getDataLayout();
2334 OutStreamer->emitValueToAlignment(
Align(PointerSize));
2336 OutStreamer->emitIntValue(0, PointerSize);
2337 OutStreamer->emitIntValue(0, PointerSize);
2338 OutStreamer->switchSection(MF->
getSection());
2342void PPCAIXAsmPrinter::emitTracebackTable() {
2346 OutStreamer->emitLabel(FuncEnd);
2348 OutStreamer->AddComment(
"Traceback table begin");
2350 OutStreamer->emitIntValueInHexWithPadding(0, 4 );
2352 SmallString<128> CommentString;
2353 raw_svector_ostream CommentOS(CommentString);
2355 auto EmitComment = [&]() {
2356 OutStreamer->AddComment(CommentOS.str());
2357 CommentString.
clear();
2360 auto EmitCommentAndValue = [&](uint64_t
Value,
int Size) {
2362 OutStreamer->emitIntValueInHexWithPadding(
Value,
Size);
2366 CommentOS <<
"Version = " <<
Version;
2367 EmitCommentAndValue(
Version, 1);
2377 CommentOS <<
"Language = "
2379 EmitCommentAndValue(LanguageIdentifier, 1);
2382 uint32_t FirstHalfOfMandatoryField = 0;
2389 const PPCFunctionInfo *FI = MF->
getInfo<PPCFunctionInfo>();
2393 for (
unsigned Reg = PPC::F0;
Reg <= PPC::F31; ++
Reg) {
2394 if (
MRI.isPhysRegUsed(
Reg,
true)) {
2400#define GENBOOLCOMMENT(Prefix, V, Field) \
2401 CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \
2404#define GENVALUECOMMENT(PrefixAndName, V, Field) \
2405 CommentOS << (PrefixAndName) << " = " \
2406 << static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >> \
2407 (TracebackTable::Field##Shift))
2410 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);
2413 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, HasTraceBackTableOffset);
2414 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsInternalProcedure);
2417 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, HasControlledStorage);
2421 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, IsFloatingPointPresent);
2424 IsFloatingPointOperationLogOrAbortEnabled);
2427 OutStreamer->emitIntValueInHexWithPadding(
2428 (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2435 if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))
2438 const SmallVectorImpl<Register> &MustSaveCRs = FI->
getMustSaveCRs();
2439 if (!MustSaveCRs.
empty())
2445 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, IsInterruptHandler);
2446 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);
2450 OnConditionDirective);
2454 OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),
2458 uint32_t SecondHalfOfMandatoryField = 0;
2464 uint32_t FPRSaved = 0;
2465 for (
unsigned Reg = PPC::F14;
Reg <= PPC::F31; ++
Reg) {
2466 if (
MRI.isPhysRegModified(
Reg)) {
2467 FPRSaved = PPC::F31 -
Reg + 1;
2473 GENBOOLCOMMENT(
"", SecondHalfOfMandatoryField, IsBackChainStored);
2475 GENVALUECOMMENT(
", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);
2477 OutStreamer->emitIntValueInHexWithPadding(
2478 (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);
2484 bool HasVectorInst =
false;
2485 for (
unsigned Reg = PPC::V0;
Reg <= PPC::V31; ++
Reg)
2486 if (
MRI.isPhysRegUsed(
Reg,
true)) {
2488 HasVectorInst =
true;
2495 uint16_t NumOfVRSaved = getNumberOfVRSaved();
2496 bool ShouldEmitEHBlock =
2499 if (ShouldEmitEHBlock)
2502 uint32_t GPRSaved = 0;
2505 unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;
2506 unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;
2508 for (
unsigned Reg = GPRBegin;
Reg <= GPREnd; ++
Reg) {
2509 if (
MRI.isPhysRegModified(
Reg)) {
2510 GPRSaved = GPREnd -
Reg + 1;
2518 GENBOOLCOMMENT(
"", SecondHalfOfMandatoryField, HasExtensionTable);
2520 GENVALUECOMMENT(
", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);
2522 OutStreamer->emitIntValueInHexWithPadding(
2523 (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);
2527 SecondHalfOfMandatoryField |=
2531 NumberOfFixedParms);
2533 OutStreamer->emitIntValueInHexWithPadding(
2534 (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2542 SecondHalfOfMandatoryField |=
2547 NumberOfFloatingPointParms);
2548 GENBOOLCOMMENT(
", ", SecondHalfOfMandatoryField, HasParmsOnStack);
2550 OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,
2556 if (NumberOfFixedParms || NumberOfFPParms) {
2559 Expected<SmallString<32>> ParmsType =
2562 ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,
2569 CommentOS <<
"Parameter type = " << ParmsType.
get();
2572 OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,
2573 sizeof(ParmsTypeValue));
2576 OutStreamer->AddComment(
"Function size");
2578 MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(
2580 OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);
2592 int16_t NameLength =
Name.size();
2593 CommentOS <<
"Function name len = "
2594 <<
static_cast<unsigned int>(NameLength);
2595 EmitCommentAndValue(NameLength, 2);
2596 OutStreamer->AddComment(
"Function Name");
2597 OutStreamer->emitBytes(Name);
2602 OutStreamer->AddComment(
"AllocaUsed");
2603 OutStreamer->emitIntValueInHex(AllocReg,
sizeof(AllocReg));
2607 uint16_t VRData = 0;
2636 OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);
2641 OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);
2645 Expected<SmallString<32>> VecParmsType =
2649 CommentOS <<
"Vector Parameter type = " << VecParmsType.
get();
2652 OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,
2653 sizeof(VecParmTypeValue));
2655 CommentOS <<
"Padding";
2656 EmitCommentAndValue(0, 2);
2659 uint8_t ExtensionTableFlag = 0;
2661 if (ShouldEmitEHBlock)
2662 ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;
2665 ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;
2667 CommentOS <<
"ExtensionTableFlag = "
2669 EmitCommentAndValue(ExtensionTableFlag,
sizeof(ExtensionTableFlag));
2672 if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {
2673 auto &Ctx = OutStreamer->getContext();
2676 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock);
2677 const MCSymbol *TOCBaseSym =
static_cast<const MCSectionXCOFF *
>(
2678 getObjFileLowering().getTOCBaseSection())
2679 ->getQualNameSymbol();
2684 const DataLayout &
DL = getDataLayout();
2685 OutStreamer->emitValueToAlignment(
Align(4));
2686 OutStreamer->AddComment(
"EHInfo Table");
2687 OutStreamer->emitValue(Exp,
DL.getPointerSize());
2689#undef GENBOOLCOMMENT
2690#undef GENVALUECOMMENT
2699 .
Case(
"llvm.used",
true)
2701 .
Case(
"llvm.compiler.used",
true)
2707 .
Cases({
"llvm.global_ctors",
"llvm.global_dtors"},
true)
2711uint64_t PPCAIXAsmPrinter::getAliasOffset(
const Constant *
C) {
2713 return getAliasOffset(GA->getAliasee());
2724 return RHS->getValue();
2734 "GlobalVariables with an alignment requirement stricter than TOC entry "
2735 "size not supported by the toc data transformation.");
2738 assert(GVType->
isSized() &&
"A GlobalVariable's size must be known to be "
2739 "supported by the toc data transformation.");
2743 "A GlobalVariable with size larger than a TOC entry is not currently "
2744 "supported by the toc data transformation.");
2747 "currently supported by the toc data transformation.");
2750void PPCAIXAsmPrinter::emitGlobalVariable(
const GlobalVariable *GV) {
2768 emitGlobalVariableHelper(GV);
2771void PPCAIXAsmPrinter::emitGlobalVariableHelper(
const GlobalVariable *GV) {
2773 "Unhandled intrinsic global variable.");
2778 auto *GVSym =
static_cast<MCSymbolXCOFF *
>(getSymbol(GV));
2781 emitLinkage(GV, GVSym);
2785 SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
2789 "not supported yet.");
2796 OutStreamer->getCommentOS() <<
'\n';
2800 auto *Csect =
static_cast<MCSectionXCOFF *
>(
2801 getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
2804 OutStreamer->switchSection(Csect);
2806 if (GV->
hasMetadata(LLVMContext::MD_implicit_ref)) {
2807 emitRefMetadata(GV);
2817 GVSym->setStorageClass(
2821 OutStreamer->emitZeros(
Size);
2824 "BSS local toc-data already handled and TLS variables "
2825 "incompatible with XMC_TD");
2826 OutStreamer->emitXCOFFLocalCommonSymbol(
2827 OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()),
Size,
2830 OutStreamer->emitCommonSymbol(GVSym,
Size, Alignment);
2838 emitLinkage(GV, EmittedInitSym);
2839 for (
const GlobalAlias *GA : GOAliasMap[GV])
2840 emitLinkage(GA, getSymbol(GA));
2842 emitAlignment(getGVAlignment(GV,
DL), GV);
2846 if (!TM.getDataSections() || GV->hasSection()) {
2848 OutStreamer->emitLabel(EmittedInitSym);
2852 if (!GOAliasMap[GV].
size()) {
2853 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());
2859 AliasMapTy AliasList;
2860 for (
const GlobalAlias *GA : GOAliasMap[GV])
2861 AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);
2864 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),
2868void PPCAIXAsmPrinter::emitFunctionDescriptor() {
2869 const DataLayout &
DL = getDataLayout();
2870 const unsigned PointerSize =
DL.getPointerSizeInBits() == 64 ? 8 : 4;
2874 OutStreamer->switchSection(
2875 static_cast<MCSymbolXCOFF *
>(CurrentFnDescSym)->getRepresentedCsect());
2878 for (
const GlobalAlias *Alias : GOAliasMap[&MF->
getFunction()])
2879 OutStreamer->emitLabel(getSymbol(Alias));
2885 const MCSymbol *TOCBaseSym =
static_cast<const MCSectionXCOFF *
>(
2886 getObjFileLowering().getTOCBaseSection())
2887 ->getQualNameSymbol();
2891 OutStreamer->emitIntValue(0, PointerSize);
2893 OutStreamer->switchSection(Current.first, Current.second);
2896void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
2900 PPCAsmPrinter::emitFunctionEntryLabel();
2905 for (
const GlobalAlias *Alias : GOAliasMap[
F])
2906 OutStreamer->emitLabel(
2907 getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));
2909 if (
F->hasMetadata(LLVMContext::MD_implicit_ref)) {
2914void PPCAIXAsmPrinter::emitPGORefs(
Module &M) {
2915 if (!OutContext.hasXCOFFSection(
2926 bool HasNonZeroLengthPrfCntsSection =
false;
2927 const DataLayout &
DL =
M.getDataLayout();
2928 for (GlobalVariable &GV :
M.globals())
2929 if (GV.hasSection() && GV.getSection() ==
"__llvm_prf_cnts" &&
2930 DL.getTypeAllocSize(GV.getValueType()) > 0) {
2931 HasNonZeroLengthPrfCntsSection =
true;
2935 if (HasNonZeroLengthPrfCntsSection) {
2936 MCSection *CntsSection = OutContext.getXCOFFSection(
2941 OutStreamer->switchSection(CntsSection);
2942 if (OutContext.hasXCOFFSection(
2945 MCSymbol *S = OutContext.getOrCreateSymbol(
"__llvm_prf_data[RW]");
2946 OutStreamer->emitXCOFFRefDirective(S);
2948 if (OutContext.hasXCOFFSection(
2951 MCSymbol *S = OutContext.getOrCreateSymbol(
"__llvm_prf_names[RO]");
2952 OutStreamer->emitXCOFFRefDirective(S);
2954 if (OutContext.hasXCOFFSection(
2957 MCSymbol *S = OutContext.getOrCreateSymbol(
"__llvm_prf_vnds[RW]");
2958 OutStreamer->emitXCOFFRefDirective(S);
2963void PPCAIXAsmPrinter::emitGCOVRefs() {
2964 if (!OutContext.hasXCOFFSection(
2965 "__llvm_gcov_ctr_section",
2969 MCSection *CtrSection = OutContext.getXCOFFSection(
2974 OutStreamer->switchSection(CtrSection);
2977 if (OutContext.hasXCOFFSection(
2980 const char *SymbolStr = TM.Options.XCOFFReadOnlyPointers
2981 ?
"__llvm_covinit[RO]"
2982 :
"__llvm_covinit[RW]";
2983 MCSymbol *S = OutContext.getOrCreateSymbol(SymbolStr);
2984 OutStreamer->emitXCOFFRefDirective(S);
2988void PPCAIXAsmPrinter::emitEndOfAsmFile(
Module &M) {
2991 if (
M.empty() && TOCDataGlobalVars.
empty())
2998 OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
3000 PPCTargetStreamer *TS =
3001 static_cast<PPCTargetStreamer *
>(OutStreamer->getTargetStreamer());
3003 for (
auto &
I : TOC) {
3004 MCSectionXCOFF *TCEntry;
3011 (Subtarget->hasAIXShLibTLSModelOpt() &&
3013 SmallString<128>
Name;
3016 Name +=
static_cast<const MCSymbolXCOFF *
>(
I.first.first)
3017 ->getSymbolTableName();
3018 MCSymbol *S = OutContext.getOrCreateSymbol(Name);
3019 TCEntry =
static_cast<MCSectionXCOFF *
>(
3020 getObjFileLowering().getSectionForTOCEntry(S, TM));
3022 TCEntry =
static_cast<MCSectionXCOFF *
>(
3023 getObjFileLowering().getSectionForTOCEntry(
I.first.first, TM));
3025 OutStreamer->switchSection(TCEntry);
3027 OutStreamer->emitLabel(
I.second);
3034 for (
const auto *GV : TOCDataGlobalVars) {
3035 if (!GV->hasCommonLinkage())
3036 emitGlobalVariableHelper(GV);
3038 for (
const auto *GV : TOCDataGlobalVars) {
3039 if (GV->hasCommonLinkage())
3040 emitGlobalVariableHelper(GV);
3044bool PPCAIXAsmPrinter::doInitialization(
Module &M) {
3045 const bool Result = PPCAsmPrinter::doInitialization(M);
3048 const Triple &
Target = TM.getTargetTriple();
3055 if (FunCpuId > TargetCpuId)
3056 TargetCpuId = FunCpuId;
3062 StringRef TargetCPU = TM.getTargetCPU();
3067 PPCTargetStreamer *TS =
3068 static_cast<PPCTargetStreamer *
>(OutStreamer->getTargetStreamer());
3071 auto setCsectAlignment = [
this](
const GlobalObject *GO) {
3073 if (GO->isDeclarationForLinker())
3076 SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);
3077 auto *Csect =
static_cast<MCSectionXCOFF *
>(
3078 getObjFileLowering().SectionForGlobal(GO, GOKind, TM));
3080 Align GOAlign = getGVAlignment(GO, GO->getDataLayout());
3081 Csect->ensureMinAlignment(GOAlign);
3087 uint64_t TLSVarAddress = 0;
3088 auto DL =
M.getDataLayout();
3089 for (
const auto &
G :
M.globals()) {
3090 if (
G.isThreadLocal() && !
G.isDeclaration()) {
3091 TLSVarAddress =
alignTo(TLSVarAddress, getGVAlignment(&
G,
DL));
3092 TLSVarsToAddressMapping[&
G] = TLSVarAddress;
3093 TLSVarAddress +=
DL.getTypeAllocSize(
G.getValueType());
3100 for (
const auto &
G :
M.globals()) {
3107 if (FormatIndicatorAndUniqueModId.empty()) {
3109 if (UniqueModuleId !=
"")
3113 FormatIndicatorAndUniqueModId =
"clang_" + UniqueModuleId.substr(1);
3118 std::chrono::duration_cast<std::chrono::nanoseconds>(
3119 std::chrono::steady_clock::now().time_since_epoch())
3121 FormatIndicatorAndUniqueModId =
3128 emitSpecialLLVMGlobal(&
G);
3132 setCsectAlignment(&
G);
3133 std::optional<CodeModel::Model> OptionalCodeModel =
G.getCodeModel();
3134 if (OptionalCodeModel)
3136 *OptionalCodeModel);
3139 for (
const auto &
F : M)
3140 setCsectAlignment(&
F);
3143 for (
const auto &Alias :
M.aliases()) {
3144 const GlobalObject *Aliasee = Alias.getAliaseeObject();
3147 "alias without a base object is not yet supported on AIX");
3151 "\n\tAlias attribute for " +
3152 Alias.getName() +
" is invalid because " +
3153 Aliasee->
getName() +
" is common.",
3157 const GlobalVariable *GVar =
3160 std::optional<CodeModel::Model> OptionalCodeModel = GVar->
getCodeModel();
3161 if (OptionalCodeModel)
3163 *OptionalCodeModel);
3166 GOAliasMap[Aliasee].push_back(&Alias);
3172void PPCAIXAsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3173 switch (
MI->getOpcode()) {
3180 if (
MI->getNumOperands() < 5)
3182 const MachineOperand &LangMO =
MI->getOperand(3);
3183 const MachineOperand &ReasonMO =
MI->getOperand(4);
3186 MCSymbol *TempSym = OutContext.createNamedTempSymbol();
3187 OutStreamer->emitLabel(TempSym);
3188 OutStreamer->emitXCOFFExceptDirective(
3189 CurrentFnSym, TempSym, LangMO.
getImm(), ReasonMO.
getImm(),
3190 Subtarget->isPPC64() ?
MI->getMF()->getInstructionCount() * 8
3191 :
MI->getMF()->getInstructionCount() * 4,
3195 case PPC::GETtlsMOD32AIX:
3196 case PPC::GETtlsMOD64AIX:
3197 case PPC::GETtlsTpointer32AIX:
3198 case PPC::GETtlsADDR64AIX:
3199 case PPC::GETtlsADDR32AIX: {
3204 ExtSymSDNodeSymbols.
insert(TlsGetAddr);
3211 const MachineOperand &MO =
MI->getOperand(0);
3213 auto *S =
static_cast<MCSymbolXCOFF *
>(
3215 ExtSymSDNodeSymbols.
insert(S);
3221 case PPC::BL8_NOP_TLS:
3228 case PPC::TAILBCTR8:
3229 if (
MI->getOperand(0).isSymbol())
3242 MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));
3245 return PPCAsmPrinter::emitInstruction(
MI);
3248bool PPCAIXAsmPrinter::doFinalization(
Module &M) {
3254 auto *Sec = OutContext.getObjectFileInfo()->getTextSection();
3255 OutStreamer->switchSectionNoPrint(Sec);
3256 MCSymbol *Sym = Sec->getEndSymbol(OutContext);
3257 OutStreamer->emitLabel(Sym);
3260 for (MCSymbol *Sym : ExtSymSDNodeSymbols)
3261 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Extern);
3262 return PPCAsmPrinter::doFinalization(M);
3273 return 20 + (
P - 20) * 16;
3276 return 1004 + (
P - 81);
3279 return 2047 + (
P - 1124) * 33878;
3281 return 2147482625u + (
P - 64512);
3300 std::string PrioritySuffix;
3303 return PrioritySuffix;
3306void PPCAIXAsmPrinter::emitXXStructorList(
const DataLayout &
DL,
3307 const Constant *
List,
bool IsCtor) {
3309 preprocessXXStructorList(
DL,
List, Structors);
3310 if (Structors.
empty())
3314 for (Structor &S : Structors) {
3316 S.Func =
CE->getOperand(0);
3320 (IsCtor ? llvm::Twine(
"__sinit") : llvm::Twine(
"__sterm")) +
3322 llvm::Twine(
"_", FormatIndicatorAndUniqueModId) +
3328void PPCAIXAsmPrinter::emitTTypeReference(
const GlobalValue *GV,
3329 unsigned Encoding) {
3331 TOCEntryType GlobalType = TOCType_GlobalInternal;
3336 GlobalType = TOCType_GlobalExternal;
3337 MCSymbol *TypeInfoSym = TM.getSymbol(GV);
3338 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType);
3339 const MCSymbol *TOCBaseSym =
static_cast<const MCSectionXCOFF *
>(
3340 getObjFileLowering().getTOCBaseSection())
3341 ->getQualNameSymbol();
3342 auto &Ctx = OutStreamer->getContext();
3346 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));
3348 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));
3351void PPCAIXAsmPrinter::emitRefMetadata(
const GlobalObject *GO) {
3353 GO->
getMetadata(LLVMContext::MD_implicit_ref, MDs);
3354 assert(MDs.
size() &&
"Expected asscoiated metadata nodes");
3356 for (
const MDNode *MD : MDs) {
3359 MCSymbol *Referenced = TM.getSymbol(GV);
3360 OutStreamer->emitXCOFFRefDirective(Referenced);
3368 std::unique_ptr<MCStreamer> &&Streamer) {
3370 return new PPCAIXAsmPrinter(tm, std::move(Streamer));
3372 return new PPCLinuxAsmPrinter(tm, std::move(Streamer));
3375void PPCAIXAsmPrinter::emitModuleCommandLines(
Module &M) {
3376 const NamedMDNode *NMD =
M.getNamedMetadata(
"llvm.commandline");
3381 raw_string_ostream RSOS(S);
3384 assert(
N->getNumOperands() == 1 &&
3385 "llvm.commandline metadata entry can have only one operand");
3389 RSOS <<
"@(#)opt " << MDS->
getString() <<
"\n";
3392 OutStreamer->emitXCOFFCInfoSym(
".GCC.command.line", RSOS.str());
3395char PPCAIXAsmPrinter::ID = 0;
3398 "AIX PPC Assembly Printer",
false,
false)
3402LLVMInitializePowerPCAsmPrinter() {
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)
static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV)
static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV)
#define GENBOOLCOMMENT(Prefix, V, Field)
static MCSymbol * getMCSymbolForTOCPseudoMO(const MachineOperand &MO, AsmPrinter &AP)
Map a machine operand for a TOC pseudo-machine instruction to its corresponding MCSymbol.
static void setOptionalCodeModel(MCSymbolXCOFF *XSym, CodeModel::Model CM)
static AsmPrinter * createPPCAsmPrinterPass(TargetMachine &tm, std::unique_ptr< MCStreamer > &&Streamer)
static PPCAsmPrinter::TOCEntryType getTOCEntryTypeForMO(const MachineOperand &MO)
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static std::string convertToSinitPriority(int Priority)
static MCSymbol * createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc)
This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX.
#define GENVALUECOMMENT(PrefixAndName, V, Field)
static unsigned mapToSinitPriority(int P)
static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV)
static cl::opt< bool > EnableSSPCanaryBitInTB("aix-ssp-tb-bit", cl::init(false), cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden)
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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 hasMetadata() const
Return true if this value has any metadata attached to it.
bool hasSection() const
Check if this global has a custom object file section.
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
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<X> - 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<X> - 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)
std::pair< const MCSymbol *, PPCMCExpr::Specifier > TOCKey
static unsigned getHashValue(const TOCKey &PairVal)
static TOCKey getTombstoneKey()
static TOCKey getEmptyKey()
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