84#define DEBUG_TYPE "asmprinter"
86STATISTIC(NumTOCEntries,
"Number of Total TOC Entries Emitted.");
87STATISTIC(NumTOCConstPool,
"Number of Constant Pool TOC Entries.");
89 "Number of Internal Linkage Global TOC Entries.");
91 "Number of External Linkage Global TOC Entries.");
92STATISTIC(NumTOCJumpTable,
"Number of Jump Table TOC Entries.");
93STATISTIC(NumTOCThreadLocal,
"Number of Thread Local TOC Entries.");
94STATISTIC(NumTOCBlockAddress,
"Number of Block Address TOC Entries.");
95STATISTIC(NumTOCEHBlock,
"Number of EH Block TOC Entries.");
108 using TOCKey = std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>;
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,
160 std::unique_ptr<MCStreamer> Streamer)
166 TOCType_ConstantPool,
167 TOCType_GlobalExternal,
168 TOCType_GlobalInternal,
171 TOCType_BlockAddress,
177 MCSymbolRefExpr::VariantKind::VK_None);
211class PPCLinuxAsmPrinter :
public PPCAsmPrinter {
214 std::unique_ptr<MCStreamer> Streamer)
215 : PPCAsmPrinter(
TM,
std::
move(Streamer)) {}
218 return "Linux PPC Assembly Printer";
221 void emitGNUAttributes(
Module &M);
223 void emitStartOfAsmFile(
Module &M)
override;
224 void emitEndOfAsmFile(
Module &)
override;
226 void emitFunctionEntryLabel()
override;
228 void emitFunctionBodyStart()
override;
229 void emitFunctionBodyEnd()
override;
233class PPCAIXAsmPrinter :
public PPCAsmPrinter {
241 std::string FormatIndicatorAndUniqueModId;
249 void emitTracebackTable();
259 PPCAIXAsmPrinter(
TargetMachine &
TM, std::unique_ptr<MCStreamer> Streamer)
260 : PPCAsmPrinter(
TM,
std::
move(Streamer)) {
261 if (MAI->isLittleEndian())
263 "cannot create AIX PPC Assembly Printer for a little-endian target");
266 StringRef getPassName()
const override {
return "AIX PPC Assembly Printer"; }
268 bool doInitialization(
Module &M)
override;
271 bool IsCtor)
override;
277 void emitFunctionDescriptor()
override;
279 void emitFunctionEntryLabel()
override;
281 void emitFunctionBodyEnd()
override;
283 void emitPGORefs(
Module &M);
285 void emitEndOfAsmFile(
Module &)
override;
291 bool doFinalization(
Module &M)
override;
293 void emitTTypeReference(
const GlobalValue *GV,
unsigned Encoding)
override;
295 void emitModuleCommandLines(
Module &M)
override;
304 getSymbol(GV)->
print(O, MAI);
308void PPCAsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNo,
331 O <<
DL.getPrivateGlobalPrefix() <<
"CPI" << getFunctionNumber() <<
'_'
338 PrintSymbolOperand(MO, O);
350bool PPCAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
353 if (ExtraCode && ExtraCode[0]) {
354 if (ExtraCode[1] != 0)
return true;
356 switch (ExtraCode[0]) {
362 if (!
MI->getOperand(OpNo).isReg() ||
363 OpNo+1 ==
MI->getNumOperands() ||
364 !
MI->getOperand(OpNo+1).isReg())
371 if (
MI->getOperand(OpNo).isImm())
375 if(!
MI->getOperand(OpNo).isReg())
381 Reg = PPC::VSX32 + (
Reg - PPC::V0);
383 Reg = PPC::VSX32 + (Reg - PPC::VF0);
399bool PPCAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNo,
400 const char *ExtraCode,
402 if (ExtraCode && ExtraCode[0]) {
403 if (ExtraCode[1] != 0)
return true;
405 switch (ExtraCode[0]) {
406 default:
return true;
408 O << getDataLayout().getPointerSize() <<
"(";
419 if (
MI->getOperand(OpNo).isImm())
430 assert(
MI->getOperand(OpNo).isReg());
435 assert(
MI->getOperand(OpNo).isReg());
445 case PPCAsmPrinter::TOCType_ConstantPool:
448 case PPCAsmPrinter::TOCType_GlobalInternal:
449 ++NumTOCGlobalInternal;
451 case PPCAsmPrinter::TOCType_GlobalExternal:
452 ++NumTOCGlobalExternal;
454 case PPCAsmPrinter::TOCType_JumpTable:
457 case PPCAsmPrinter::TOCType_ThreadLocal:
460 case PPCAsmPrinter::TOCType_BlockAddress:
461 ++NumTOCBlockAddress;
463 case PPCAsmPrinter::TOCType_EHBlock:
473PPCAsmPrinter::lookUpOrCreateTOCEntry(
const MCSymbol *
Sym, TOCEntryType
Type,
476 if (!
TOC.contains({Sym, Kind}))
481 TOCEntry = createTempSymbol(
"C");
486 unsigned NumNOPBytes =
MI.getOperand(1).getImm();
488 auto &Ctx = OutStreamer->getContext();
489 MCSymbol *MILabel = Ctx.createTempSymbol();
490 OutStreamer->emitLabel(MILabel);
493 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
499 while (NumNOPBytes > 0) {
500 if (MII ==
MBB.
end() || MII->isCall() ||
501 MII->getOpcode() == PPC::DBG_VALUE ||
502 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
503 MII->getOpcode() == TargetOpcode::STACKMAP)
510 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
517 auto &Ctx = OutStreamer->getContext();
518 MCSymbol *MILabel = Ctx.createTempSymbol();
519 OutStreamer->emitLabel(MILabel);
524 unsigned EncodedBytes = 0;
527 if (CalleeMO.
isImm()) {
528 int64_t CallTarget = CalleeMO.
getImm();
530 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
531 "High 16 bits of call target should be zero.");
532 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
537 .addImm((CallTarget >> 32) & 0xFFFF));
542 .addImm(32).addImm(16));
547 .addImm((CallTarget >> 16) & 0xFFFF));
552 .addImm(CallTarget & 0xFFFF));
558 .addImm(TOCSaveOffset)
571 .addReg(ScratchReg));
576 .addReg(ScratchReg));
581 .addReg(ScratchReg));
589 .addImm(TOCSaveOffset)
595 MCSymbol *MOSymbol = getSymbol(GValue);
607 unsigned NumBytes = Opers.getNumPatchBytes();
608 assert(NumBytes >= EncodedBytes &&
609 "Patchpoint can't request size less than the length of a call.");
610 assert((NumBytes - EncodedBytes) % 4 == 0 &&
611 "Invalid number of NOP bytes requested!");
612 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
621 MIOpc == PPC::GETtlsTpointer32AIX ?
".__get_tpointer" :
".__tls_get_addr";
630 "Only expecting to emit calls to get the thread pointer on AIX!");
635 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::BLA).addExpr(TlsRef));
643 unsigned Opcode = PPC::BL8_NOP_TLS;
645 assert(
MI->getNumOperands() >= 3 &&
"Expecting at least 3 operands from MI");
649 Opcode = PPC::BL8_NOTOC_TLS;
651 const Module *
M = MF->getFunction().getParent();
654 ((Subtarget->
isPPC64() &&
MI->getOperand(0).getReg() == PPC::X3) ||
655 (!Subtarget->
isPPC64() &&
MI->getOperand(0).getReg() == PPC::R3)) &&
656 "GETtls[ld]ADDR[32] must define GPR3");
658 ((Subtarget->
isPPC64() &&
MI->getOperand(1).getReg() == PPC::X3) ||
659 (!Subtarget->
isPPC64() &&
MI->getOperand(1).getReg() == PPC::R3)) &&
660 "GETtls[ld]ADDR[32] must read GPR3");
670 MI->getOperand(2).getReg() == VarOffsetReg &&
671 "GETtls[ld]ADDR[32] must read GPR4");
672 EmitAIXTlsCallHelper(
MI);
676 MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol(
"__tls_get_addr");
691 MCSymbol *MOSymbol = getSymbol(GValue);
693 EmitToStreamer(*OutStreamer,
695 : (
unsigned)PPC::BL_TLS)
732static PPCAsmPrinter::TOCEntryType
737 return PPCAsmPrinter::TOCType_ThreadLocal;
746 return PPCAsmPrinter::TOCType_GlobalExternal;
748 return PPCAsmPrinter::TOCType_GlobalInternal;
751 return PPCAsmPrinter::TOCType_ConstantPool;
753 return PPCAsmPrinter::TOCType_JumpTable;
755 return PPCAsmPrinter::TOCType_BlockAddress;
764 PPC_MC::verifyInstructionPredicates(
MI->getOpcode(),
765 getSubtargetInfo().getFeatureBits());
768 const bool IsPPC64 = Subtarget->
isPPC64();
769 const bool IsAIX = Subtarget->
isAIXABI();
770 const Module *
M = MF->getFunction().getParent();
775 if (!
MI->isInlineAsm()) {
779 if (Subtarget->hasSPE()) {
780 if (PPC::F4RCRegClass.
contains(Reg) ||
789 if (PPC::SPERCRegClass.
contains(Reg))
797 auto getTOCRelocAdjustedExprForXCOFF = [
this](
const MCExpr *Expr,
806 OriginalOffset - llvm::SignExtend32<16>(OriginalOffset);
811 auto getTOCEntryLoadingExprForXCOFF =
812 [IsPPC64, getTOCRelocAdjustedExprForXCOFF,
815 MCSymbolRefExpr::VariantKind::VK_None) ->
const MCExpr * {
816 const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
817 const auto TOCEntryIter =
TOC.find({MOSymbol, VK});
819 "Could not find the TOC entry for this symbol.");
820 const ptrdiff_t EntryDistanceFromTOCBase =
821 (TOCEntryIter -
TOC.begin()) * EntryByteSize;
822 constexpr int16_t PositiveTOCRange = INT16_MAX;
824 if (EntryDistanceFromTOCBase > PositiveTOCRange)
825 return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);
834 assert(MO.
isGlobal() &&
"Only expecting a global MachineOperand here!\n");
837 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
839 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
846 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM;
848 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD;
849 return MCSymbolRefExpr::VariantKind::VK_None;
853 switch (
MI->getOpcode()) {
855 case TargetOpcode::DBG_VALUE:
857 case TargetOpcode::STACKMAP:
858 return LowerSTACKMAP(SM, *
MI);
859 case TargetOpcode::PATCHPOINT:
860 return LowerPATCHPOINT(SM, *
MI);
862 case PPC::MoveGOTtoLR: {
870 OutContext.getOrCreateSymbol(
StringRef(
"_GLOBAL_OFFSET_TABLE_"));
879 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::BL).addExpr(OffsExpr));
882 case PPC::MovePCtoLR:
883 case PPC::MovePCtoLR8: {
888 MCSymbol *PICBase = MF->getPICBaseSymbol();
891 EmitToStreamer(*OutStreamer,
898 OutStreamer->emitLabel(PICBase);
901 case PPC::UpdateGBR: {
910 if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
912 MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
924 MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));
929 MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));
949 EmitToStreamer(*OutStreamer, TmpInst);
955 EmitToStreamer(*OutStreamer, TmpInst);
968 "Invalid operand for LWZtoc.");
980 EmitToStreamer(*OutStreamer, TmpInst);
1000 "This pseudo should only be selected for 32-bit small code model.");
1001 Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
1006 OutStreamer->getCommentOS() << MO <<
'\n';
1007 EmitToStreamer(*OutStreamer, TmpInst);
1014 OutContext.getOrCreateSymbol(
Twine(
".LTOC")), OutContext);
1017 EmitToStreamer(*OutStreamer, TmpInst);
1021 case PPC::ADDItoc8: {
1023 "PseudoOp only valid for small code model AIX");
1029 TmpInst.
setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
1042 EmitToStreamer(*OutStreamer, TmpInst);
1057 "Invalid operand!");
1074 IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);
1077 if (isVerbose() && IsAIX)
1078 OutStreamer->getCommentOS() << MO <<
'\n';
1079 EmitToStreamer(*OutStreamer, TmpInst);
1082 case PPC::ADDIStocHA: {
1084 "This pseudo should only be selected for 32-bit large code model on"
1095 "Invalid operand for ADDIStocHA.");
1112 EmitToStreamer(*OutStreamer, TmpInst);
1115 case PPC::LWZtocL: {
1117 "This pseudo should only be selected for 32-bit large code model on"
1128 "Invalid operand for LWZtocL.");
1145 EmitToStreamer(*OutStreamer, TmpInst);
1148 case PPC::ADDIStocHA8: {
1160 "Invalid operand for ADDIStocHA8!");
1166 const bool GlobalToc =
1184 EmitToStreamer(*OutStreamer, TmpInst);
1200 "Invalid operand for LDtocL!");
1204 "LDtocL used on symbol that could be accessed directly is "
1205 "invalid. Must match ADDIStocHA8."));
1218 EmitToStreamer(*OutStreamer, TmpInst);
1221 case PPC::ADDItocL: {
1235 "Interposable definitions must use indirect access."));
1241 EmitToStreamer(*OutStreamer, TmpInst);
1244 case PPC::ADDISgotTprelHA: {
1247 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1250 MCSymbol *MOSymbol = getSymbol(GValue);
1251 const MCExpr *SymGotTprel =
1255 .addReg(
MI->getOperand(0).getReg())
1256 .
addReg(
MI->getOperand(1).getReg())
1260 case PPC::LDgotTprelL:
1261 case PPC::LDgotTprelL32: {
1266 TmpInst.
setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);
1269 MCSymbol *MOSymbol = getSymbol(GValue);
1275 EmitToStreamer(*OutStreamer, TmpInst);
1279 case PPC::PPC32PICGOT: {
1280 MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(
StringRef(
"_GLOBAL_OFFSET_TABLE_"));
1281 MCSymbol *GOTRef = OutContext.createTempSymbol();
1282 MCSymbol *NextInstr = OutContext.createTempSymbol();
1292 OutStreamer->emitLabel(GOTRef);
1293 OutStreamer->emitValue(OffsExpr, 4);
1294 OutStreamer->emitLabel(NextInstr);
1296 .addReg(
MI->getOperand(0).getReg()));
1298 .addReg(
MI->getOperand(1).getReg())
1300 .
addReg(
MI->getOperand(0).getReg()));
1302 .addReg(
MI->getOperand(0).getReg())
1303 .
addReg(
MI->getOperand(1).getReg())
1304 .
addReg(
MI->getOperand(0).getReg()));
1307 case PPC::PPC32GOT: {
1309 OutContext.getOrCreateSymbol(
StringRef(
"_GLOBAL_OFFSET_TABLE_"));
1315 .addReg(
MI->getOperand(0).getReg())
1318 .addReg(
MI->getOperand(0).getReg())
1319 .
addReg(
MI->getOperand(0).getReg())
1323 case PPC::ADDIStlsgdHA: {
1326 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1329 MCSymbol *MOSymbol = getSymbol(GValue);
1330 const MCExpr *SymGotTlsGD =
1334 .addReg(
MI->getOperand(0).getReg())
1335 .
addReg(
MI->getOperand(1).getReg())
1339 case PPC::ADDItlsgdL:
1342 case PPC::ADDItlsgdL32: {
1347 MCSymbol *MOSymbol = getSymbol(GValue);
1352 EmitToStreamer(*OutStreamer,
1354 .addReg(
MI->getOperand(0).getReg())
1355 .
addReg(
MI->getOperand(1).getReg())
1359 case PPC::GETtlsADDR:
1362 case PPC::GETtlsADDRPCREL:
1363 case PPC::GETtlsADDR32AIX:
1364 case PPC::GETtlsADDR64AIX:
1368 case PPC::GETtlsADDR32: {
1374 case PPC::GETtlsTpointer32AIX: {
1377 EmitAIXTlsCallHelper(
MI);
1380 case PPC::ADDIStlsldHA: {
1383 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1386 MCSymbol *MOSymbol = getSymbol(GValue);
1387 const MCExpr *SymGotTlsLD =
1391 .addReg(
MI->getOperand(0).getReg())
1392 .
addReg(
MI->getOperand(1).getReg())
1396 case PPC::ADDItlsldL:
1399 case PPC::ADDItlsldL32: {
1404 MCSymbol *MOSymbol = getSymbol(GValue);
1409 EmitToStreamer(*OutStreamer,
1411 .addReg(
MI->getOperand(0).getReg())
1412 .
addReg(
MI->getOperand(1).getReg())
1416 case PPC::GETtlsldADDR:
1419 case PPC::GETtlsldADDRPCREL:
1420 case PPC::GETtlsldADDR32: {
1426 case PPC::ADDISdtprelHA:
1429 case PPC::ADDISdtprelHA32: {
1434 MCSymbol *MOSymbol = getSymbol(GValue);
1435 const MCExpr *SymDtprel =
1441 .addReg(
MI->getOperand(0).getReg())
1442 .
addReg(
MI->getOperand(1).getReg())
1446 case PPC::PADDIdtprel: {
1451 MCSymbol *MOSymbol = getSymbol(GValue);
1455 .addReg(
MI->getOperand(0).getReg())
1456 .
addReg(
MI->getOperand(1).getReg())
1461 case PPC::ADDIdtprelL:
1464 case PPC::ADDIdtprelL32: {
1469 MCSymbol *MOSymbol = getSymbol(GValue);
1470 const MCExpr *SymDtprel =
1473 EmitToStreamer(*OutStreamer,
1475 .addReg(
MI->getOperand(0).getReg())
1476 .
addReg(
MI->getOperand(1).getReg())
1482 if (!Subtarget->hasMFOCRF()) {
1485 unsigned NewOpcode =
1486 MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;
1490 .addReg(
MI->getOperand(0).getReg()));
1496 if (!Subtarget->hasMFOCRF()) {
1499 unsigned NewOpcode =
1500 MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
1501 unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
1502 ->getEncodingValue(
MI->getOperand(0).getReg());
1507 .addReg(
MI->getOperand(1).getReg()));
1517 unsigned OpNum = (
MI->getOpcode() == PPC::STD) ? 2 : 1;
1527 case PPC::PseudoEIEIO: {
1530 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1533 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1534 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::EnforceIEIO));
1544 Subtarget->hasAIXSmallLocalExecTLS() &&
1545 "addi with thread-pointer only expected with local-exec small TLS");
1548 EmitToStreamer(*OutStreamer, TmpInst);
1556 EmitToStreamer(*OutStreamer, TmpInst);
1559void PPCLinuxAsmPrinter::emitGNUAttributes(
Module &M) {
1561 Metadata *MD =
M.getModuleFlag(
"float-abi");
1562 MDString *FloatABI = dyn_cast_or_null<MDString>(MD);
1567 if (flt ==
"doubledouble")
1568 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1569 Val_GNU_Power_ABI_HardFloat_DP |
1570 Val_GNU_Power_ABI_LDBL_IBM128);
1571 else if (flt ==
"ieeequad")
1572 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1573 Val_GNU_Power_ABI_HardFloat_DP |
1574 Val_GNU_Power_ABI_LDBL_IEEE128);
1575 else if (flt ==
"ieeedouble")
1576 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1577 Val_GNU_Power_ABI_HardFloat_DP |
1578 Val_GNU_Power_ABI_LDBL_64);
1581void PPCLinuxAsmPrinter::emitInstruction(
const MachineInstr *
MI) {
1583 return PPCAsmPrinter::emitInstruction(
MI);
1585 switch (
MI->getOpcode()) {
1587 return PPCAsmPrinter::emitInstruction(
MI);
1588 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1600 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1601 MCSymbol *EndOfSled = OutContext.createTempSymbol();
1602 OutStreamer->emitLabel(BeginOfSled);
1603 EmitToStreamer(*OutStreamer,
1609 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1610 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1611 EmitToStreamer(*OutStreamer,
1614 OutContext.getOrCreateSymbol(
"__xray_FunctionEntry"),
1616 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1617 OutStreamer->emitLabel(EndOfSled);
1618 recordSled(BeginOfSled, *
MI, SledKind::FUNCTION_ENTER, 2);
1621 case TargetOpcode::PATCHABLE_RET: {
1622 unsigned RetOpcode =
MI->getOperand(0).getImm();
1632 if (RetOpcode == PPC::BCCLR) {
1633 IsConditional =
true;
1634 }
else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
1635 RetOpcode == PPC::TCRETURNai8) {
1637 }
else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
1638 IsConditional =
false;
1640 EmitToStreamer(*OutStreamer, RetInst);
1645 if (IsConditional) {
1664 FallthroughLabel = OutContext.createTempSymbol();
1670 .
addReg(
MI->getOperand(2).getReg())
1687 OutStreamer->emitCodeAlignment(
Align(8), &getSubtargetInfo());
1688 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1689 OutStreamer->emitLabel(BeginOfSled);
1690 EmitToStreamer(*OutStreamer, RetInst);
1694 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1695 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1696 EmitToStreamer(*OutStreamer,
1699 OutContext.getOrCreateSymbol(
"__xray_FunctionExit"),
1701 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1702 EmitToStreamer(*OutStreamer, RetInst);
1704 OutStreamer->emitLabel(FallthroughLabel);
1705 recordSled(BeginOfSled, *
MI, SledKind::FUNCTION_EXIT, 2);
1708 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1710 case TargetOpcode::PATCHABLE_TAIL_CALL:
1714 "around this assert.");
1718void PPCLinuxAsmPrinter::emitStartOfAsmFile(
Module &M) {
1726 !isPositionIndependent())
1732 OutStreamer->switchSection(OutContext.getELFSection(
1735 MCSymbol *TOCSym = OutContext.getOrCreateSymbol(
Twine(
".LTOC"));
1736 MCSymbol *CurrentPos = OutContext.createTempSymbol();
1738 OutStreamer->emitLabel(CurrentPos);
1747 OutStreamer->emitAssignment(TOCSym, tocExpr);
1749 OutStreamer->switchSection(getObjFileLowering().getTextSection());
1752void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {
1755 (!isPositionIndependent() ||
1761 if (PPCFI->
usesPICBase() && !Subtarget->isSecurePlt()) {
1763 MCSymbol *PICBase = MF->getPICBaseSymbol();
1764 OutStreamer->emitLabel(RelocSymbol);
1772 OutStreamer->emitValue(OffsExpr, 4);
1773 OutStreamer->emitLabel(CurrentFnSym);
1786 && !MF->getRegInfo().use_empty(PPC::X2)) {
1791 const MCExpr *TOCDeltaExpr =
1798 OutStreamer->emitValue(TOCDeltaExpr, 8);
1807 OutStreamer->switchSection(Section);
1808 OutStreamer->emitLabel(CurrentFnSym);
1809 OutStreamer->emitValueToAlignment(
Align(8));
1810 MCSymbol *Symbol1 = CurrentFnSymForSize;
1817 OutStreamer->emitValue(
1821 OutStreamer->emitIntValue(0, 8 );
1822 OutStreamer->switchSection(Current.first, Current.second);
1825void PPCLinuxAsmPrinter::emitEndOfAsmFile(
Module &M) {
1828 bool isPPC64 =
DL.getPointerSizeInBits() == 64;
1833 emitGNUAttributes(M);
1836 const char *
Name = isPPC64 ?
".toc" :
".got2";
1839 OutStreamer->switchSection(Section);
1841 OutStreamer->emitValueToAlignment(
Align(4));
1843 for (
const auto &TOCMapPair : TOC) {
1844 const MCSymbol *
const TOCEntryTarget = TOCMapPair.first.first;
1845 MCSymbol *
const TOCEntryLabel = TOCMapPair.second;
1847 OutStreamer->emitLabel(TOCEntryLabel);
1849 TS->
emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);
1851 OutStreamer->emitSymbolValue(TOCEntryTarget, 4);
1855 PPCAsmPrinter::emitEndOfAsmFile(M);
1859void PPCLinuxAsmPrinter::emitFunctionBodyStart() {
1892 const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||
1893 !MF->getRegInfo().use_empty(PPC::R2);
1902 if (NonPCrelGEPRequired || PCrelGEPRequired) {
1907 OutStreamer->emitLabel(GlobalEntryLabel);
1913 const MCExpr *TOCDeltaExpr =
1915 GlobalEntryLabelExp, OutContext);
1921 .addExpr(TOCDeltaHi));
1927 .addExpr(TOCDeltaLo));
1930 const MCExpr *TOCOffsetDeltaExpr =
1932 GlobalEntryLabelExp, OutContext);
1936 .addExpr(TOCOffsetDeltaExpr)
1945 OutStreamer->emitLabel(LocalEntryLabel);
1948 const MCExpr *LocalOffsetExp =
1950 GlobalEntryLabelExp, OutContext);
1954 TS->
emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym), LocalOffsetExp);
1977 if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||
1978 MF->hasInlineAsm() || (!PPCFI->
usesTOCBasePtr() && UsesX2OrR2)) {
1990void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
1999 OutStreamer->emitIntValue(0, 4);
2000 OutStreamer->emitIntValue(0, 8);
2004void PPCAIXAsmPrinter::emitLinkage(
const GlobalValue *GV,
2007 assert(MAI->hasVisibilityOnlyWithLinkage() &&
2008 "AIX's linkage directives take a visibility setting.");
2029 "InternalLinkage should not have other visibility setting.");
2041 if (!
TM.getIgnoreXCOFFVisibility()) {
2044 "Cannot not be both dllexport and non-default visibility");
2050 VisibilityAttr = MAI->getExportedVisibilityAttr();
2053 VisibilityAttr = MAI->getHiddenVisibilityAttr();
2056 VisibilityAttr = MAI->getProtectedVisibilityAttr();
2061 OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
2068 cast<MCSectionXCOFF>(getObjFileLowering().getSectionForFunctionDescriptor(
2077uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {
2082 if (Subtarget.
isAIXABI() && Subtarget.hasAltivec() &&
2083 TM.getAIXExtendedAltivecABI()) {
2085 for (
unsigned Reg = PPC::V20;
Reg <= PPC::V31; ++
Reg)
2086 if (
MRI.isPhysRegModified(Reg))
2088 return PPC::V31 - Reg + 1;
2093void PPCAIXAsmPrinter::emitFunctionBodyEnd() {
2095 if (!
TM.getXCOFFTracebackTable())
2098 emitTracebackTable();
2106 (getNumberOfVRSaved() > 0)) {
2108 OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());
2111 OutStreamer->emitLabel(EHInfoLabel);
2114 OutStreamer->emitInt32(0);
2116 const DataLayout &
DL = MMI->getModule()->getDataLayout();
2119 OutStreamer->emitValueToAlignment(
Align(PointerSize));
2121 OutStreamer->emitIntValue(0, PointerSize);
2122 OutStreamer->emitIntValue(0, PointerSize);
2123 OutStreamer->switchSection(MF->
getSection());
2127void PPCAIXAsmPrinter::emitTracebackTable() {
2131 OutStreamer->emitLabel(FuncEnd);
2133 OutStreamer->AddComment(
"Traceback table begin");
2135 OutStreamer->emitIntValueInHexWithPadding(0, 4 );
2140 auto EmitComment = [&]() {
2141 OutStreamer->AddComment(CommentOS.str());
2142 CommentString.
clear();
2147 OutStreamer->emitIntValueInHexWithPadding(
Value,
Size);
2151 CommentOS <<
"Version = " <<
Version;
2152 EmitCommentAndValue(Version, 1);
2162 CommentOS <<
"Language = "
2164 EmitCommentAndValue(LanguageIdentifier, 1);
2167 uint32_t FirstHalfOfMandatoryField = 0;
2178 for (
unsigned Reg = PPC::F0;
Reg <= PPC::F31; ++
Reg) {
2179 if (
MRI.isPhysRegUsed(Reg,
true)) {
2185#define GENBOOLCOMMENT(Prefix, V, Field) \
2186 CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \
2189#define GENVALUECOMMENT(PrefixAndName, V, Field) \
2190 CommentOS << (PrefixAndName) << " = " \
2191 << static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >> \
2192 (TracebackTable::Field##Shift))
2195 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);
2198 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, HasTraceBackTableOffset);
2199 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsInternalProcedure);
2202 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, HasControlledStorage);
2206 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, IsFloatingPointPresent);
2209 IsFloatingPointOperationLogOrAbortEnabled);
2212 OutStreamer->emitIntValueInHexWithPadding(
2213 (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2221 if (FrameReg == (Subtarget->
isPPC64() ? PPC::X31 : PPC::R31))
2225 if (!MustSaveCRs.
empty())
2231 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, IsInterruptHandler);
2232 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);
2236 OnConditionDirective);
2240 OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),
2244 uint32_t SecondHalfOfMandatoryField = 0;
2251 for (
unsigned Reg = PPC::F14;
Reg <= PPC::F31; ++
Reg) {
2252 if (
MRI.isPhysRegModified(Reg)) {
2253 FPRSaved = PPC::F31 -
Reg + 1;
2259 GENBOOLCOMMENT(
"", SecondHalfOfMandatoryField, IsBackChainStored);
2261 GENVALUECOMMENT(
", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);
2263 OutStreamer->emitIntValueInHexWithPadding(
2264 (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);
2270 bool HasVectorInst =
false;
2271 for (
unsigned Reg = PPC::V0;
Reg <= PPC::V31; ++
Reg)
2272 if (
MRI.isPhysRegUsed(Reg,
true)) {
2274 HasVectorInst =
true;
2281 uint16_t NumOfVRSaved = getNumberOfVRSaved();
2282 bool ShouldEmitEHBlock =
2285 if (ShouldEmitEHBlock)
2291 unsigned GPRBegin = Subtarget->
isPPC64() ? PPC::X14 : PPC::R13;
2292 unsigned GPREnd = Subtarget->
isPPC64() ? PPC::X31 : PPC::R31;
2294 for (
unsigned Reg = GPRBegin;
Reg <= GPREnd; ++
Reg) {
2295 if (
MRI.isPhysRegModified(Reg)) {
2296 GPRSaved = GPREnd -
Reg + 1;
2304 GENBOOLCOMMENT(
"", SecondHalfOfMandatoryField, HasExtensionTable);
2306 GENVALUECOMMENT(
", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);
2308 OutStreamer->emitIntValueInHexWithPadding(
2309 (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);
2313 SecondHalfOfMandatoryField |=
2317 NumberOfFixedParms);
2319 OutStreamer->emitIntValueInHexWithPadding(
2320 (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2328 SecondHalfOfMandatoryField |=
2333 NumberOfFloatingPointParms);
2334 GENBOOLCOMMENT(
", ", SecondHalfOfMandatoryField, HasParmsOnStack);
2336 OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,
2342 if (NumberOfFixedParms || NumberOfFPParms) {
2348 ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,
2355 CommentOS <<
"Parameter type = " << ParmsType.
get();
2358 OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,
2359 sizeof(ParmsTypeValue));
2362 OutStreamer->AddComment(
"Function size");
2364 MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(
2366 OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);
2378 int16_t NameLength =
Name.size();
2379 CommentOS <<
"Function name len = "
2380 <<
static_cast<unsigned int>(NameLength);
2381 EmitCommentAndValue(NameLength, 2);
2382 OutStreamer->AddComment(
"Function Name");
2383 OutStreamer->emitBytes(
Name);
2388 OutStreamer->AddComment(
"AllocaUsed");
2389 OutStreamer->emitIntValueInHex(AllocReg,
sizeof(AllocReg));
2422 OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);
2427 OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);
2435 CommentOS <<
"Vector Parameter type = " << VecParmsType.
get();
2438 OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,
2439 sizeof(VecParmTypeValue));
2441 CommentOS <<
"Padding";
2442 EmitCommentAndValue(0, 2);
2445 uint8_t ExtensionTableFlag = 0;
2447 if (ShouldEmitEHBlock)
2448 ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;
2451 ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;
2453 CommentOS <<
"ExtensionTableFlag = "
2455 EmitCommentAndValue(ExtensionTableFlag,
sizeof(ExtensionTableFlag));
2458 if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {
2459 auto &Ctx = OutStreamer->getContext();
2462 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock);
2464 cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2465 ->getQualNameSymbol();
2471 OutStreamer->emitValueToAlignment(
Align(4));
2472 OutStreamer->AddComment(
"EHInfo Table");
2473 OutStreamer->emitValue(Exp,
DL.getPointerSize());
2475#undef GENBOOLCOMMENT
2476#undef GENVALUECOMMENT
2485 .
Case(
"llvm.used",
true)
2487 .
Case(
"llvm.compiler.used",
true)
2493 .
Cases(
"llvm.global_ctors",
"llvm.global_dtors",
true)
2498 if (
auto *GA = dyn_cast<GlobalAlias>(
C))
2499 return getAliasOffset(GA->getAliasee());
2500 if (
auto *CE = dyn_cast<ConstantExpr>(
C)) {
2502 const MCBinaryExpr *CBE = dyn_cast<MCBinaryExpr>(LowC);
2507 auto *
RHS = dyn_cast<MCConstantExpr>(CBE->
getRHS());
2510 return RHS->getValue();
2515void PPCAIXAsmPrinter::emitGlobalVariable(
const GlobalVariable *GV) {
2523 TOCDataGlobalVars.push_back(GV);
2527 emitGlobalVariableHelper(GV);
2530void PPCAIXAsmPrinter::emitGlobalVariableHelper(
const GlobalVariable *GV) {
2532 "Unhandled intrinsic global variable.");
2540 emitLinkage(GV, GVSym);
2544 SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV,
TM);
2548 "not supported yet.");
2555 OutStreamer->getCommentOS() <<
'\n';
2560 getObjFileLowering().SectionForGlobal(GV, GVKind,
TM));
2563 OutStreamer->switchSection(Csect);
2576 OutStreamer->emitXCOFFLocalCommonSymbol(
2580 OutStreamer->emitCommonSymbol(GVSym,
Size, Alignment);
2587 emitLinkage(GV, EmittedInitSym);
2589 emitLinkage(GA, getSymbol(GA));
2591 emitAlignment(getGVAlignment(GV,
DL), GV);
2595 if (!
TM.getDataSections() || GV->hasSection())
2596 OutStreamer->emitLabel(EmittedInitSym);
2599 if (!GOAliasMap[GV].
size()) {
2600 emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
2606 AliasMapTy AliasList;
2608 AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);
2611 emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer(),
2615void PPCAIXAsmPrinter::emitFunctionDescriptor() {
2617 const unsigned PointerSize =
DL.getPointerSizeInBits() == 64 ? 8 : 4;
2621 OutStreamer->switchSection(
2622 cast<MCSymbolXCOFF>(CurrentFnDescSym)->getRepresentedCsect());
2626 OutStreamer->emitLabel(getSymbol(Alias));
2633 cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2634 ->getQualNameSymbol();
2638 OutStreamer->emitIntValue(0, PointerSize);
2640 OutStreamer->switchSection(Current.first, Current.second);
2643void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
2646 if (!
TM.getFunctionSections())
2647 PPCAsmPrinter::emitFunctionEntryLabel();
2651 OutStreamer->emitLabel(
2652 getObjFileLowering().getFunctionEntryPointSymbol(Alias,
TM));
2655void PPCAIXAsmPrinter::emitPGORefs(
Module &M) {
2656 if (!OutContext.hasXCOFFSection(
2667 bool HasNonZeroLengthPrfCntsSection =
false;
2670 if (GV.hasSection() && GV.getSection().equals(
"__llvm_prf_cnts") &&
2671 DL.getTypeAllocSize(GV.getValueType()) > 0) {
2672 HasNonZeroLengthPrfCntsSection =
true;
2676 if (HasNonZeroLengthPrfCntsSection) {
2677 MCSection *CntsSection = OutContext.getXCOFFSection(
2682 OutStreamer->switchSection(CntsSection);
2683 if (OutContext.hasXCOFFSection(
2686 MCSymbol *S = OutContext.getOrCreateSymbol(
"__llvm_prf_data[RW]");
2687 OutStreamer->emitXCOFFRefDirective(S);
2689 if (OutContext.hasXCOFFSection(
2692 MCSymbol *S = OutContext.getOrCreateSymbol(
"__llvm_prf_names[RO]");
2693 OutStreamer->emitXCOFFRefDirective(S);
2695 if (OutContext.hasXCOFFSection(
2698 MCSymbol *S = OutContext.getOrCreateSymbol(
"__llvm_prf_vnds[RW]");
2699 OutStreamer->emitXCOFFRefDirective(S);
2704void PPCAIXAsmPrinter::emitEndOfAsmFile(
Module &M) {
2707 if (
M.empty() && TOCDataGlobalVars.empty())
2713 OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
2718 for (
auto &
I : TOC) {
2723 if (
I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM) {
2727 Name += cast<MCSymbolXCOFF>(
I.first.first)->getSymbolTableName();
2729 TCEntry = cast<MCSectionXCOFF>(
2730 getObjFileLowering().getSectionForTOCEntry(S,
TM));
2732 TCEntry = cast<MCSectionXCOFF>(
2733 getObjFileLowering().getSectionForTOCEntry(
I.first.first,
TM));
2735 OutStreamer->switchSection(TCEntry);
2737 OutStreamer->emitLabel(
I.second);
2741 for (
const auto *GV : TOCDataGlobalVars)
2742 emitGlobalVariableHelper(GV);
2745bool PPCAIXAsmPrinter::doInitialization(
Module &M) {
2746 const bool Result = PPCAsmPrinter::doInitialization(M);
2748 auto setCsectAlignment = [
this](
const GlobalObject *GO) {
2750 if (GO->isDeclarationForLinker())
2753 SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO,
TM);
2755 getObjFileLowering().SectionForGlobal(GO, GOKind,
TM));
2757 Align GOAlign = getGVAlignment(GO, GO->getParent()->getDataLayout());
2764 for (
const auto &
G :
M.globals()) {
2771 if (FormatIndicatorAndUniqueModId.empty()) {
2773 if (UniqueModuleId !=
"")
2777 FormatIndicatorAndUniqueModId =
"clang_" + UniqueModuleId.substr(1);
2782 std::chrono::duration_cast<std::chrono::nanoseconds>(
2783 std::chrono::steady_clock::now().time_since_epoch())
2785 FormatIndicatorAndUniqueModId =
2788 llvm::itostr(CurTime);
2792 emitSpecialLLVMGlobal(&
G);
2796 setCsectAlignment(&
G);
2799 for (
const auto &
F : M)
2800 setCsectAlignment(&
F);
2803 for (
const auto &Alias :
M.aliases()) {
2807 "alias without a base object is not yet supported on AIX");
2811 "\n\tAlias attribute for " +
2812 Alias.getGlobalIdentifier() +
2813 " is invalid because " + Aliasee->
getName() +
2818 GOAliasMap[Aliasee].push_back(&Alias);
2825 switch (
MI->getOpcode()) {
2832 if (
MI->getNumOperands() < 5)
2838 MCSymbol *TempSym = OutContext.createNamedTempSymbol();
2839 OutStreamer->emitLabel(TempSym);
2840 OutStreamer->emitXCOFFExceptDirective(CurrentFnSym, TempSym,
2842 Subtarget->
isPPC64() ?
MI->getMF()->getInstructionCount() * 8 :
2843 MI->getMF()->getInstructionCount() * 4,
2844 MMI->hasDebugInfo());
2847 case PPC::GETtlsTpointer32AIX:
2848 case PPC::GETtlsADDR64AIX:
2849 case PPC::GETtlsADDR32AIX: {
2854 ExtSymSDNodeSymbols.insert(TlsGetAddr);
2864 cast<MCSymbolXCOFF>(OutContext.getOrCreateSymbol(MO.
getSymbolName()));
2865 ExtSymSDNodeSymbols.insert(S);
2871 case PPC::BL8_NOP_TLS:
2878 case PPC::TAILBCTR8:
2879 if (
MI->getOperand(0).isSymbol())
2892 MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));
2895 return PPCAsmPrinter::emitInstruction(
MI);
2898bool PPCAIXAsmPrinter::doFinalization(
Module &M) {
2900 if (!MAI->usesDwarfFileAndLocDirectives() && MMI->hasDebugInfo())
2901 OutStreamer->doFinalizationAtSectionEnd(
2902 OutStreamer->getContext().getObjectFileInfo()->getTextSection());
2906 return PPCAsmPrinter::doFinalization(M);
2910 if (P < 0 || P > 65535)
2917 return 20 + (
P - 20) * 16;
2920 return 1004 + (
P - 81);
2923 return 2047 + (
P - 1124) * 33878;
2925 return 2147482625u + (
P - 64512);
2944 std::string PrioritySuffix;
2948 return PrioritySuffix;
2951void PPCAIXAsmPrinter::emitXXStructorList(
const DataLayout &
DL,
2952 const Constant *List,
bool IsCtor) {
2954 preprocessXXStructorList(
DL, List, Structors);
2955 if (Structors.
empty())
2959 for (Structor &S : Structors) {
2960 if (
const ConstantExpr *CE = dyn_cast<ConstantExpr>(S.Func))
2961 S.Func =
CE->getOperand(0);
2969 cast<Function>(S.Func));
2973void PPCAIXAsmPrinter::emitTTypeReference(
const GlobalValue *GV,
2974 unsigned Encoding) {
2976 TOCEntryType GlobalType = TOCType_GlobalInternal;
2981 GlobalType = TOCType_GlobalExternal;
2983 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType);
2985 cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2986 ->getQualNameSymbol();
2987 auto &Ctx = OutStreamer->getContext();
2991 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));
2993 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));
3000 std::unique_ptr<MCStreamer> &&Streamer) {
3002 return new PPCAIXAsmPrinter(tm, std::move(Streamer));
3004 return new PPCLinuxAsmPrinter(tm, std::move(Streamer));
3007void PPCAIXAsmPrinter::emitModuleCommandLines(
Module &M) {
3008 const NamedMDNode *NMD =
M.getNamedMetadata(
"llvm.commandline");
3016 assert(
N->getNumOperands() == 1 &&
3017 "llvm.commandline metadata entry can have only one operand");
3018 const MDString *MDS = cast<MDString>(
N->getOperand(0));
3021 RSOS <<
"@(#)opt " << MDS->
getString() <<
"\n";
3024 OutStreamer->emitXCOFFCInfoSym(
".GCC.command.line", RSOS.str());
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_EXTERNAL_VISIBILITY
static std::string getRegisterName(const TargetRegisterInfo *TRI, Register Reg)
This file implements a map that provides insertion order iteration.
Module.h This file contains the declarations for the Module class.
static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type)
static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV)
static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmPrinter()
#define GENBOOLCOMMENT(Prefix, V, Field)
static bool hasTLSFlag(const MachineOperand &MO)
static MCSymbol * getMCSymbolForTOCPseudoMO(const MachineOperand &MO, AsmPrinter &AP)
Map a machine operand for a TOC pseudo-machine instruction to its corresponding MCSymbol.
static AsmPrinter * createPPCAsmPrinterPass(TargetMachine &tm, std::unique_ptr< MCStreamer > &&Streamer)
static PPCAsmPrinter::TOCEntryType getTOCEntryTypeForMO(const MachineOperand &MO)
static std::string convertToSinitPriority(int Priority)
static MCSymbol * createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc)
This helper function creates the TlsGetAddr MCSymbol for AIX.
#define GENVALUECOMMENT(PrefixAndName, V, Field)
static unsigned mapToSinitPriority(int P)
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)
const char LLVMTargetMachineRef TM
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallPtrSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static constexpr uint32_t Opcode
This class is intended to be used as a driving class for all asm writers.
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
MCSymbol * getSymbol(const GlobalValue *GV) const
void emitXRayTable()
Emit a table with all XRay instrumentation points.
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)
Print the MachineOperand as a symbol.
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.
virtual bool PrintAsmMemoryOperand(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 as...
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.
A constant value that is initialized with an expression using other constant values.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
static 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...
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
VisibilityTypes getVisibility() const
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LinkageTypes getLinkage() const
bool hasDefaultVisibility() const
bool hasDLLExportStorageClass() const
bool isDeclarationForLinker() const
Module * getParent()
Get the module that this global value is contained inside of...
const GlobalObject * getAliaseeObject() const
@ DefaultVisibility
The GV is visible.
@ HiddenVisibility
The GV is hidden.
@ ProtectedVisibility
The GV is protected.
bool hasCommonLinkage() const
bool hasAppendingLinkage() const
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ CommonLinkage
Tentative definitions.
@ InternalLinkage
Rename collisions when linking (static functions).
@ LinkOnceAnyLinkage
Keep one copy of function when linking (inline)
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AppendingLinkage
Special purpose, only applies to global arrays.
@ AvailableExternallyLinkage
Available for inspection, not emission.
@ ExternalWeakLinkage
ExternalWeak linkage description.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
bool hasAttribute(Attribute::AttrKind Kind) const
Return true if the attribute exists.
bool hasInitializer() const
Definitions have initializers, declarations don't.
Binary assembler expressions.
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Opcode getOpcode() const
Get the kind of this binary expression.
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
MCSectionXCOFF * getXCOFFSection(StringRef Section, SectionKind K, std::optional< XCOFF::CsectProperties > CsectProp=std::nullopt, bool MultiSymbolsAllowed=false, const char *BeginSymName=nullptr, std::optional< XCOFF::DwarfSectionSubtypeFlags > DwarfSubtypeFlags=std::nullopt)
Base class for the full range of assembler expressions which are needed for parsing.
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
const MCOperand & getOperand(unsigned i) const
Instances of this class represent operands of the MCInst class.
static MCOperand createExpr(const MCExpr *Val)
unsigned getReg() const
Returns the register number.
This represents a section on linux, lots of unix variants and some bare metal systems.
MCSymbolXCOFF * getQualNameSymbol() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
void setAlignment(Align Value)
void ensureMinAlignment(Align MinAlignment)
Makes sure that Alignment is at least MinAlignment.
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
StringRef getSymbolTableName() const
void setStorageClass(XCOFF::StorageClass SC)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getString() const
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...
Representation of each machine instruction.
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.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
MDNode * getOperand(unsigned i) const
unsigned getNumOperands() const
uint64_t getTOCSaveOffset() const
getTOCSaveOffset - Return the previous frame offset to save the TOC register – 64-bit SVR4 ABI only.
PPCFunctionInfo - This class is derived from MachineFunction private PowerPC target-specific informat...
uint32_t getParmsType() const
MCSymbol * getPICOffsetSymbol(MachineFunction &MF) const
const SmallVectorImpl< Register > & getMustSaveCRs() const
unsigned getFloatingPointParmsNum() 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 const PPCMCExpr * createLo(const MCExpr *Expr, MCContext &Ctx)
static const PPCMCExpr * createHa(const MCExpr *Expr, MCContext &Ctx)
bool is32BitELFABI() const
const PPCFrameLowering * getFrameLowering() const override
bool isPPC64() const
isPPC64 - Return true if we are generating code for 64-bit pointer mode.
bool isUsingPCRelativeCalls() const
const PPCRegisterInfo * getRegisterInfo() const override
bool isGVIndirectSymbol(const GlobalValue *GV) const
True if the GV will be accessed via an indirect symbol.
Common code between 32-bit and 64-bit PowerPC targets.
virtual void emitAbiVersion(int AbiVersion)
virtual void emitTCEntry(const MCSymbol &S, MCSymbolRefExpr::VariantKind Kind)
virtual void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset)
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
MI-level patchpoint operands.
Wrapper class representing virtual and physical registers.
SectionKind - This is a simple POD value that classifies the properties of a section.
bool isThreadBSSLocal() const
static SectionKind getText()
static SectionKind getData()
bool isThreadLocal() const
bool isGlobalWriteableData() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
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 startswith(StringRef Prefix) const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, 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
bool isOSAIX() const
Tests whether the OS is AIX.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
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.
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.
A raw_ostream that writes to an SmallVector or SmallString.
static Pid getProcessId()
Get the process's identifier.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
@ C
The default llvm calling convention, compatible with C.
@ 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_DTPREL_LO
These values identify relocations on immediates folded into memory operations.
@ 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...
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(unsigned Reg)
static bool isVFRegister(unsigned Reg)
@ CE
Windows NT (Windows on ARM)
Reg
All possible values of the reg field in the ModR/M byte.
SmallString< 32 > getExtendedTBTableFlagString(uint8_t Flag)
Expected< SmallString< 32 > > parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, unsigned FloatingParmsNum, unsigned VectorParmsNum)
Expected< SmallString< 32 > > parseParmsType(uint32_t Value, unsigned FixedParmsNum, unsigned FloatingParmsNum)
Expected< SmallString< 32 > > parseVectorParmsType(uint32_t Value, unsigned ParmsNum)
@ XMC_RO
Read Only Constant.
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)
static unsigned combineHashValue(unsigned a, unsigned b)
Simplistic combination of 32-bit hash values into 32-bit hash values.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
constexpr uint64_t PointerSize
aarch64 pointer size.
Linkage
Describes symbol linkage. This can be used to resolve definition clashes.
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.
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.
bool LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, MCOperand &OutMO, AsmPrinter &AP)
Target & getThePPC32Target()
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)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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()
uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
std::pair< MCSection *, const MCExpr * > MCSectionSubPair
Target & getThePPC32LETarget()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_Extern
.extern (XCOFF)
@ MCSA_LGlobal
.lglobl (XCOFF)
@ MCSA_Invalid
Not a valid directive.
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static unsigned getHashValue(const TOCKey &PairVal)
static bool isEqual(const TOCKey &A, const TOCKey &B)
std::pair< const MCSymbol *, MCSymbolRefExpr::VariantKind > TOCKey
static TOCKey getTombstoneKey()
static TOCKey getEmptyKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...
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