81 #define DEBUG_TYPE "asmprinter"
94 using TOCKey = std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>;
97 return {
nullptr, MCSymbolRefExpr::VariantKind::VK_None};
100 return {
nullptr, MCSymbolRefExpr::VariantKind::VK_Invalid};
115 Tag_GNU_Power_ABI_FP = 4,
116 Tag_GNU_Power_ABI_Vector = 8,
117 Tag_GNU_Power_ABI_Struct_Return = 12,
120 Val_GNU_Power_ABI_NoFloat = 0b00,
121 Val_GNU_Power_ABI_HardFloat_DP = 0b01,
122 Val_GNU_Power_ABI_SoftFloat_DP = 0b10,
123 Val_GNU_Power_ABI_HardFloat_SP = 0b11,
125 Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,
126 Val_GNU_Power_ABI_LDBL_64 = 0b1000,
127 Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,
147 std::unique_ptr<MCStreamer> Streamer)
150 StringRef getPassName()
const override {
return "PowerPC Assembly Printer"; }
154 MCSymbolRefExpr::VariantKind::VK_None);
156 bool doInitialization(
Module &M)
override {
175 void emitEndOfAsmFile(
Module &M)
override;
189 class PPCLinuxAsmPrinter :
public PPCAsmPrinter {
192 std::unique_ptr<MCStreamer> Streamer)
193 : PPCAsmPrinter(
TM,
std::
move(Streamer)) {}
196 return "Linux PPC Assembly Printer";
199 void emitGNUAttributes(
Module &M);
201 void emitStartOfAsmFile(
Module &M)
override;
202 void emitEndOfAsmFile(
Module &)
override;
204 void emitFunctionEntryLabel()
override;
206 void emitFunctionBodyStart()
override;
207 void emitFunctionBodyEnd()
override;
211 class PPCAIXAsmPrinter :
public PPCAsmPrinter {
219 std::string FormatIndicatorAndUniqueModId;
227 void emitTracebackTable();
234 PPCAIXAsmPrinter(
TargetMachine &
TM, std::unique_ptr<MCStreamer> Streamer)
235 : PPCAsmPrinter(
TM,
std::
move(Streamer)) {
236 if (MAI->isLittleEndian())
238 "cannot create AIX PPC Assembly Printer for a little-endian target");
241 StringRef getPassName()
const override {
return "AIX PPC Assembly Printer"; }
243 bool doInitialization(
Module &M)
override;
246 bool IsCtor)
override;
252 void emitFunctionDescriptor()
override;
254 void emitFunctionEntryLabel()
override;
256 void emitFunctionBodyEnd()
override;
260 void emitEndOfAsmFile(
Module &)
override;
266 bool doFinalization(
Module &M)
override;
268 void emitTTypeReference(
const GlobalValue *GV,
unsigned Encoding)
override;
277 getSymbol(GV)->
print(
O, MAI);
304 O <<
DL.getPrivateGlobalPrefix() <<
"CPI" << getFunctionNumber() <<
'_'
311 PrintSymbolOperand(MO,
O);
316 O <<
"<unknown operand type: " << (unsigned)MO.
getType() <<
">";
323 bool PPCAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
326 if (ExtraCode && ExtraCode[0]) {
327 if (ExtraCode[1] != 0)
return true;
329 switch (ExtraCode[0]) {
335 if (!
MI->getOperand(OpNo).isReg() ||
336 OpNo+1 ==
MI->getNumOperands() ||
337 !
MI->getOperand(OpNo+1).isReg())
344 if (
MI->getOperand(OpNo).isImm())
348 if(!
MI->getOperand(OpNo).isReg())
354 Reg = PPC::VSX32 + (
Reg - PPC::V0);
356 Reg = PPC::VSX32 + (
Reg - PPC::VF0);
372 bool PPCAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNo,
373 const char *ExtraCode,
375 if (ExtraCode && ExtraCode[0]) {
376 if (ExtraCode[1] != 0)
return true;
378 switch (ExtraCode[0]) {
379 default:
return true;
381 O << getDataLayout().getPointerSize() <<
"(";
392 if (
MI->getOperand(OpNo).isImm())
403 assert(
MI->getOperand(OpNo).isReg());
408 assert(
MI->getOperand(OpNo).isReg());
419 PPCAsmPrinter::lookUpOrCreateTOCEntry(
const MCSymbol *Sym,
423 TOCEntry = createTempSymbol(
"C");
427 void PPCAsmPrinter::emitEndOfAsmFile(
Module &M) {
432 unsigned NumNOPBytes =
MI.getOperand(1).getImm();
434 auto &Ctx = OutStreamer->getContext();
435 MCSymbol *MILabel = Ctx.createTempSymbol();
436 OutStreamer->emitLabel(MILabel);
439 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
445 while (NumNOPBytes > 0) {
446 if (MII ==
MBB.
end() || MII->isCall() ||
447 MII->getOpcode() == PPC::DBG_VALUE ||
448 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
449 MII->getOpcode() == TargetOpcode::STACKMAP)
456 for (
unsigned i = 0;
i < NumNOPBytes;
i += 4)
463 auto &Ctx = OutStreamer->getContext();
464 MCSymbol *MILabel = Ctx.createTempSymbol();
465 OutStreamer->emitLabel(MILabel);
470 unsigned EncodedBytes = 0;
473 if (CalleeMO.
isImm()) {
474 int64_t CallTarget = CalleeMO.
getImm();
476 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
477 "High 16 bits of call target should be zero.");
478 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
483 .addImm((CallTarget >> 32) & 0xFFFF));
488 .addImm(32).addImm(16));
493 .addImm((CallTarget >> 16) & 0xFFFF));
498 .addImm(CallTarget & 0xFFFF));
504 .addImm(TOCSaveOffset)
517 .addReg(ScratchReg));
522 .addReg(ScratchReg));
527 .addReg(ScratchReg));
535 .addImm(TOCSaveOffset)
541 MCSymbol *MOSymbol = getSymbol(GValue);
553 unsigned NumBytes = Opers.getNumPatchBytes();
554 assert(NumBytes >= EncodedBytes &&
555 "Patchpoint can't request size less than the length of a call.");
556 assert((NumBytes - EncodedBytes) % 4 == 0 &&
557 "Invalid number of NOP bytes requested!");
558 for (
unsigned i = EncodedBytes;
i < NumBytes;
i += 4)
577 unsigned Opcode = PPC::BL8_NOP_TLS;
579 assert(
MI->getNumOperands() >= 3 &&
"Expecting at least 3 operands from MI");
583 Opcode = PPC::BL8_NOTOC_TLS;
585 const Module *
M = MF->getFunction().getParent();
588 ((Subtarget->
isPPC64() &&
MI->getOperand(0).getReg() == PPC::X3) ||
589 (!Subtarget->
isPPC64() &&
MI->getOperand(0).getReg() == PPC::R3)) &&
590 "GETtls[ld]ADDR[32] must define GPR3");
592 ((Subtarget->
isPPC64() &&
MI->getOperand(1).getReg() == PPC::X3) ||
593 (!Subtarget->
isPPC64() &&
MI->getOperand(1).getReg() == PPC::R3)) &&
594 "GETtls[ld]ADDR[32] must read GPR3");
604 MI->getOperand(2).getReg() == VarOffsetReg &&
605 "GETtls[ld]ADDR[32] must read GPR4");
609 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::BLA).addExpr(TlsRef));
613 MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol(
"__tls_get_addr");
628 MCSymbol *MOSymbol = getSymbol(GValue);
630 EmitToStreamer(*OutStreamer,
632 : (
unsigned)PPC::BL_TLS)
660 const bool IsPPC64 = Subtarget->
isPPC64();
661 const bool IsAIX = Subtarget->
isAIXABI();
662 const Module *
M = MF->getFunction().getParent();
667 if (!
MI->isInlineAsm()) {
671 if (Subtarget->
hasSPE()) {
689 auto getTOCRelocAdjustedExprForXCOFF = [
this](
const MCExpr *Expr,
698 OriginalOffset - llvm::SignExtend32<16>(OriginalOffset);
703 auto getTOCEntryLoadingExprForXCOFF =
704 [IsPPC64, getTOCRelocAdjustedExprForXCOFF,
707 MCSymbolRefExpr::VariantKind::VK_None) ->
const MCExpr * {
708 const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
709 const auto TOCEntryIter = TOC.
find({MOSymbol, VK});
711 "Could not find the TOC entry for this symbol.");
712 const ptrdiff_t EntryDistanceFromTOCBase =
713 (TOCEntryIter - TOC.
begin()) * EntryByteSize;
714 constexpr int16_t PositiveTOCRange = INT16_MAX;
716 if (EntryDistanceFromTOCBase > PositiveTOCRange)
717 return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);
726 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM;
728 return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD;
729 return MCSymbolRefExpr::VariantKind::VK_None;
733 switch (
MI->getOpcode()) {
735 case TargetOpcode::DBG_VALUE:
737 case TargetOpcode::STACKMAP:
738 return LowerSTACKMAP(SM, *
MI);
739 case TargetOpcode::PATCHPOINT:
740 return LowerPATCHPOINT(SM, *
MI);
742 case PPC::MoveGOTtoLR: {
750 OutContext.getOrCreateSymbol(
StringRef(
"_GLOBAL_OFFSET_TABLE_"));
762 case PPC::MovePCtoLR:
763 case PPC::MovePCtoLR8: {
768 MCSymbol *PICBase = MF->getPICBaseSymbol();
771 EmitToStreamer(*OutStreamer,
778 OutStreamer->emitLabel(PICBase);
781 case PPC::UpdateGBR: {
790 if (Subtarget->
isSecurePlt() && isPositionIndependent() ) {
792 MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
804 MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));
809 MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));
829 EmitToStreamer(*OutStreamer, TmpInst);
835 EmitToStreamer(*OutStreamer, TmpInst);
848 "Invalid operand for LWZtoc.");
860 EmitToStreamer(*OutStreamer, TmpInst);
869 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK);
879 "This pseudo should only be selected for 32-bit small code model.");
880 Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);
885 OutStreamer->GetCommentOS() << MO <<
'\n';
886 EmitToStreamer(*OutStreamer, TmpInst);
893 OutContext.getOrCreateSymbol(
Twine(
".LTOC")), OutContext);
896 EmitToStreamer(*OutStreamer, TmpInst);
900 case PPC::ADDItoc8: {
902 "PseudoOp only valid for small code model AIX");
908 TmpInst.
setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
921 EmitToStreamer(*OutStreamer, TmpInst);
946 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK);
952 IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);
955 if (isVerbose() && IsAIX)
956 OutStreamer->GetCommentOS() << MO <<
'\n';
957 EmitToStreamer(*OutStreamer, TmpInst);
960 case PPC::ADDIStocHA: {
962 "This pseudo should only be selected for 32-bit large code model on"
973 "Invalid operand for ADDIStocHA.");
984 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK);
989 EmitToStreamer(*OutStreamer, TmpInst);
994 "This pseudo should only be selected for 32-bit large code model on"
1005 "Invalid operand for LWZtocL.");
1016 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK);
1021 EmitToStreamer(*OutStreamer, TmpInst);
1024 case PPC::ADDIStocHA8: {
1036 "Invalid operand for ADDIStocHA8!");
1042 const bool GlobalToc =
1046 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, VK);
1060 EmitToStreamer(*OutStreamer, TmpInst);
1076 "Invalid operand for LDtocL!");
1080 "LDtocL used on symbol that could be accessed directly is "
1081 "invalid. Must match ADDIStocHA8."));
1088 MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, VK);
1094 EmitToStreamer(*OutStreamer, TmpInst);
1097 case PPC::ADDItocL: {
1111 "Interposable definitions must use indirect access."));
1117 EmitToStreamer(*OutStreamer, TmpInst);
1120 case PPC::ADDISgotTprelHA: {
1123 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1126 MCSymbol *MOSymbol = getSymbol(GValue);
1127 const MCExpr *SymGotTprel =
1131 .addReg(
MI->getOperand(0).getReg())
1132 .
addReg(
MI->getOperand(1).getReg())
1136 case PPC::LDgotTprelL:
1137 case PPC::LDgotTprelL32: {
1145 MCSymbol *MOSymbol = getSymbol(GValue);
1151 EmitToStreamer(*OutStreamer, TmpInst);
1155 case PPC::PPC32PICGOT: {
1156 MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(
StringRef(
"_GLOBAL_OFFSET_TABLE_"));
1157 MCSymbol *GOTRef = OutContext.createTempSymbol();
1158 MCSymbol *NextInstr = OutContext.createTempSymbol();
1168 OutStreamer->emitLabel(GOTRef);
1169 OutStreamer->emitValue(OffsExpr, 4);
1170 OutStreamer->emitLabel(NextInstr);
1172 .addReg(
MI->getOperand(0).getReg()));
1174 .addReg(
MI->getOperand(1).getReg())
1176 .
addReg(
MI->getOperand(0).getReg()));
1178 .addReg(
MI->getOperand(0).getReg())
1179 .
addReg(
MI->getOperand(1).getReg())
1180 .
addReg(
MI->getOperand(0).getReg()));
1183 case PPC::PPC32GOT: {
1185 OutContext.getOrCreateSymbol(
StringRef(
"_GLOBAL_OFFSET_TABLE_"));
1191 .addReg(
MI->getOperand(0).getReg())
1194 .addReg(
MI->getOperand(0).getReg())
1195 .
addReg(
MI->getOperand(0).getReg())
1199 case PPC::ADDIStlsgdHA: {
1202 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1205 MCSymbol *MOSymbol = getSymbol(GValue);
1206 const MCExpr *SymGotTlsGD =
1210 .addReg(
MI->getOperand(0).getReg())
1211 .
addReg(
MI->getOperand(1).getReg())
1215 case PPC::ADDItlsgdL:
1218 case PPC::ADDItlsgdL32: {
1223 MCSymbol *MOSymbol = getSymbol(GValue);
1228 EmitToStreamer(*OutStreamer,
1230 .addReg(
MI->getOperand(0).getReg())
1231 .
addReg(
MI->getOperand(1).getReg())
1235 case PPC::GETtlsADDR:
1238 case PPC::GETtlsADDRPCREL:
1239 case PPC::GETtlsADDR32AIX:
1240 case PPC::GETtlsADDR64AIX:
1244 case PPC::GETtlsADDR32: {
1250 case PPC::ADDIStlsldHA: {
1253 assert(IsPPC64 &&
"Not supported for 32-bit PowerPC");
1256 MCSymbol *MOSymbol = getSymbol(GValue);
1257 const MCExpr *SymGotTlsLD =
1261 .addReg(
MI->getOperand(0).getReg())
1262 .
addReg(
MI->getOperand(1).getReg())
1266 case PPC::ADDItlsldL:
1269 case PPC::ADDItlsldL32: {
1274 MCSymbol *MOSymbol = getSymbol(GValue);
1279 EmitToStreamer(*OutStreamer,
1281 .addReg(
MI->getOperand(0).getReg())
1282 .
addReg(
MI->getOperand(1).getReg())
1286 case PPC::GETtlsldADDR:
1289 case PPC::GETtlsldADDRPCREL:
1290 case PPC::GETtlsldADDR32: {
1296 case PPC::ADDISdtprelHA:
1299 case PPC::ADDISdtprelHA32: {
1304 MCSymbol *MOSymbol = getSymbol(GValue);
1305 const MCExpr *SymDtprel =
1311 .addReg(
MI->getOperand(0).getReg())
1312 .
addReg(
MI->getOperand(1).getReg())
1316 case PPC::PADDIdtprel: {
1321 MCSymbol *MOSymbol = getSymbol(GValue);
1325 .addReg(
MI->getOperand(0).getReg())
1326 .
addReg(
MI->getOperand(1).getReg())
1331 case PPC::ADDIdtprelL:
1334 case PPC::ADDIdtprelL32: {
1339 MCSymbol *MOSymbol = getSymbol(GValue);
1340 const MCExpr *SymDtprel =
1343 EmitToStreamer(*OutStreamer,
1345 .addReg(
MI->getOperand(0).getReg())
1346 .
addReg(
MI->getOperand(1).getReg())
1355 unsigned NewOpcode =
1360 .addReg(
MI->getOperand(0).getReg()));
1369 unsigned NewOpcode =
1370 MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;
1371 unsigned Mask = 0x80 >> OutContext.getRegisterInfo()
1372 ->getEncodingValue(
MI->getOperand(0).getReg());
1377 .addReg(
MI->getOperand(1).getReg()));
1387 unsigned OpNum = (
MI->getOpcode() == PPC::STD) ? 2 : 1;
1397 case PPC::PseudoEIEIO: {
1400 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1403 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));
1404 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::EnforceIEIO));
1410 EmitToStreamer(*OutStreamer, TmpInst);
1413 void PPCLinuxAsmPrinter::emitGNUAttributes(
Module &M) {
1415 Metadata *MD =
M.getModuleFlag(
"float-abi");
1416 MDString *FloatABI = dyn_cast_or_null<MDString>(MD);
1421 if (flt ==
"doubledouble")
1422 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1423 Val_GNU_Power_ABI_HardFloat_DP |
1424 Val_GNU_Power_ABI_LDBL_IBM128);
1425 else if (flt ==
"ieeequad")
1426 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1427 Val_GNU_Power_ABI_HardFloat_DP |
1428 Val_GNU_Power_ABI_LDBL_IEEE128);
1429 else if (flt ==
"ieeedouble")
1430 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
1431 Val_GNU_Power_ABI_HardFloat_DP |
1432 Val_GNU_Power_ABI_LDBL_64);
1435 void PPCLinuxAsmPrinter::emitInstruction(
const MachineInstr *
MI) {
1437 return PPCAsmPrinter::emitInstruction(
MI);
1439 switch (
MI->getOpcode()) {
1441 return PPCAsmPrinter::emitInstruction(
MI);
1442 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1454 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1455 MCSymbol *EndOfSled = OutContext.createTempSymbol();
1456 OutStreamer->emitLabel(BeginOfSled);
1457 EmitToStreamer(*OutStreamer,
1463 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1464 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1465 EmitToStreamer(*OutStreamer,
1468 OutContext.getOrCreateSymbol(
"__xray_FunctionEntry"),
1470 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1471 OutStreamer->emitLabel(EndOfSled);
1472 recordSled(BeginOfSled, *
MI, SledKind::FUNCTION_ENTER, 2);
1475 case TargetOpcode::PATCHABLE_RET: {
1476 unsigned RetOpcode =
MI->getOperand(0).getImm();
1486 if (RetOpcode == PPC::BCCLR) {
1487 IsConditional =
true;
1488 }
else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||
1489 RetOpcode == PPC::TCRETURNai8) {
1491 }
else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {
1492 IsConditional =
false;
1494 EmitToStreamer(*OutStreamer, RetInst);
1499 if (IsConditional) {
1518 FallthroughLabel = OutContext.createTempSymbol();
1524 .
addReg(
MI->getOperand(2).getReg())
1541 OutStreamer->emitCodeAlignment(8, &getSubtargetInfo());
1542 MCSymbol *BeginOfSled = OutContext.createTempSymbol();
1543 OutStreamer->emitLabel(BeginOfSled);
1544 EmitToStreamer(*OutStreamer, RetInst);
1548 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));
1549 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));
1550 EmitToStreamer(*OutStreamer,
1553 OutContext.getOrCreateSymbol(
"__xray_FunctionExit"),
1555 EmitToStreamer(*OutStreamer,
MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));
1556 EmitToStreamer(*OutStreamer, RetInst);
1558 OutStreamer->emitLabel(FallthroughLabel);
1559 recordSled(BeginOfSled, *
MI, SledKind::FUNCTION_EXIT, 2);
1562 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1564 case TargetOpcode::PATCHABLE_TAIL_CALL:
1568 "around this assert.");
1572 void PPCLinuxAsmPrinter::emitStartOfAsmFile(
Module &M) {
1582 !isPositionIndependent())
1588 OutStreamer->SwitchSection(OutContext.getELFSection(
1591 MCSymbol *TOCSym = OutContext.getOrCreateSymbol(
Twine(
".LTOC"));
1592 MCSymbol *CurrentPos = OutContext.createTempSymbol();
1594 OutStreamer->emitLabel(CurrentPos);
1603 OutStreamer->emitAssignment(TOCSym, tocExpr);
1605 OutStreamer->SwitchSection(getObjFileLowering().getTextSection());
1608 void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {
1611 (!isPositionIndependent() ||
1619 MCSymbol *PICBase = MF->getPICBaseSymbol();
1620 OutStreamer->emitLabel(RelocSymbol);
1628 OutStreamer->emitValue(OffsExpr, 4);
1629 OutStreamer->emitLabel(CurrentFnSym);
1642 && !MF->getRegInfo().use_empty(PPC::X2)) {
1647 const MCExpr *TOCDeltaExpr =
1654 OutStreamer->emitValue(TOCDeltaExpr, 8);
1663 OutStreamer->SwitchSection(Section);
1664 OutStreamer->emitLabel(CurrentFnSym);
1665 OutStreamer->emitValueToAlignment(8);
1666 MCSymbol *Symbol1 = CurrentFnSymForSize;
1673 OutStreamer->emitValue(
1677 OutStreamer->emitIntValue(0, 8 );
1678 OutStreamer->SwitchSection(Current.first, Current.second);
1681 void PPCLinuxAsmPrinter::emitEndOfAsmFile(
Module &M) {
1684 bool isPPC64 =
DL.getPointerSizeInBits() == 64;
1689 emitGNUAttributes(M);
1692 const char *
Name = isPPC64 ?
".toc" :
".got2";
1695 OutStreamer->SwitchSection(Section);
1697 OutStreamer->emitValueToAlignment(4);
1699 for (
const auto &TOCMapPair : TOC) {
1700 const MCSymbol *
const TOCEntryTarget = TOCMapPair.first.first;
1701 MCSymbol *
const TOCEntryLabel = TOCMapPair.second;
1703 OutStreamer->emitLabel(TOCEntryLabel);
1704 if (isPPC64 && TS !=
nullptr)
1705 TS->
emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);
1707 OutStreamer->emitSymbolValue(TOCEntryTarget, 4);
1711 PPCAsmPrinter::emitEndOfAsmFile(M);
1715 void PPCLinuxAsmPrinter::emitFunctionBodyStart() {
1748 const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||
1749 !MF->getRegInfo().use_empty(
PPC::R2);
1758 if (NonPCrelGEPRequired || PCrelGEPRequired) {
1763 OutStreamer->emitLabel(GlobalEntryLabel);
1769 const MCExpr *TOCDeltaExpr =
1771 GlobalEntryLabelExp, OutContext);
1777 .addExpr(TOCDeltaHi));
1783 .addExpr(TOCDeltaLo));
1786 const MCExpr *TOCOffsetDeltaExpr =
1788 GlobalEntryLabelExp, OutContext);
1792 .addExpr(TOCOffsetDeltaExpr)
1801 OutStreamer->emitLabel(LocalEntryLabel);
1804 const MCExpr *LocalOffsetExp =
1806 GlobalEntryLabelExp, OutContext);
1812 TS->
emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym), LocalOffsetExp);
1835 if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||
1836 MF->hasInlineAsm() || (!PPCFI->
usesTOCBasePtr() && UsesX2OrR2)) {
1849 void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {
1858 OutStreamer->emitIntValue(0, 4);
1859 OutStreamer->emitIntValue(0, 8);
1863 void PPCAIXAsmPrinter::emitLinkage(
const GlobalValue *GV,
1866 assert(MAI->hasVisibilityOnlyWithLinkage() &&
1867 "AIX's linkage directives take a visibility setting.");
1888 "InternalLinkage should not have other visibility setting.");
1900 if (!
TM.getIgnoreXCOFFVisibility()) {
1903 "Cannot not be both dllexport and non-default visibility");
1909 VisibilityAttr = MAI->getExportedVisibilityAttr();
1912 VisibilityAttr = MAI->getHiddenVisibilityAttr();
1915 VisibilityAttr = MAI->getProtectedVisibilityAttr();
1920 OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
1927 cast<MCSectionXCOFF>(getObjFileLowering().getSectionForFunctionDescriptor(
1936 uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {
1942 TM.getAIXExtendedAltivecABI()) {
1944 for (
unsigned Reg = PPC::V20;
Reg <= PPC::V31; ++
Reg)
1947 return PPC::V31 -
Reg + 1;
1952 void PPCAIXAsmPrinter::emitFunctionBodyEnd() {
1954 if (!
TM.getXCOFFTracebackTable())
1957 emitTracebackTable();
1965 (getNumberOfVRSaved() > 0)) {
1967 OutStreamer->SwitchSection(getObjFileLowering().getCompactUnwindSection());
1970 OutStreamer->emitLabel(EHInfoLabel);
1973 OutStreamer->emitInt32(0);
1975 const DataLayout &
DL = MMI->getModule()->getDataLayout();
1982 OutStreamer->SwitchSection(MF->
getSection());
1986 void PPCAIXAsmPrinter::emitTracebackTable() {
1990 OutStreamer->emitLabel(FuncEnd);
1992 OutStreamer->AddComment(
"Traceback table begin");
1994 OutStreamer->emitIntValueInHexWithPadding(0, 4 );
1999 auto EmitComment = [&]() {
2000 OutStreamer->AddComment(CommentOS.str());
2001 CommentString.
clear();
2006 OutStreamer->emitIntValueInHexWithPadding(
Value, Size);
2010 CommentOS <<
"Version = " <<
Version;
2011 EmitCommentAndValue(
Version, 1);
2021 CommentOS <<
"Language = "
2023 EmitCommentAndValue(LanguageIdentifier, 1);
2026 uint32_t FirstHalfOfMandatoryField = 0;
2037 for (
unsigned Reg = PPC::F0;
Reg <= PPC::F31; ++
Reg) {
2044 #define GENBOOLCOMMENT(Prefix, V, Field) \
2045 CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \
2048 #define GENVALUECOMMENT(PrefixAndName, V, Field) \
2049 CommentOS << (PrefixAndName) << " = " \
2050 << static_cast<unsigned>(((V) & (TracebackTable::Field##Mask)) >> \
2051 (TracebackTable::Field##Shift))
2054 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);
2057 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, HasTraceBackTableOffset);
2058 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsInternalProcedure);
2061 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, HasControlledStorage);
2065 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, IsFloatingPointPresent);
2068 IsFloatingPointOperationLogOrAbortEnabled);
2071 OutStreamer->emitIntValueInHexWithPadding(
2072 (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2080 if (FrameReg == (Subtarget->
isPPC64() ? PPC::X31 : PPC::R31))
2084 if (!MustSaveCRs.empty())
2090 GENBOOLCOMMENT(
"", FirstHalfOfMandatoryField, IsInterruptHandler);
2091 GENBOOLCOMMENT(
", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);
2095 OnConditionDirective);
2099 OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),
2103 uint32_t SecondHalfOfMandatoryField = 0;
2109 for (
unsigned Reg = PPC::F14;
Reg <= PPC::F31; ++
Reg) {
2111 FPRSaved = PPC::F31 -
Reg + 1;
2117 GENBOOLCOMMENT(
"", SecondHalfOfMandatoryField, IsBackChainStored);
2119 GENVALUECOMMENT(
", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);
2121 OutStreamer->emitIntValueInHexWithPadding(
2122 (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);
2128 bool HasVectorInst =
false;
2129 for (
unsigned Reg = PPC::V0;
Reg <= PPC::V31; ++
Reg)
2132 HasVectorInst =
true;
2139 uint16_t NumOfVRSaved = getNumberOfVRSaved();
2140 bool ShouldEmitEHBlock =
2143 if (ShouldEmitEHBlock)
2149 unsigned GPRBegin = Subtarget->
isPPC64() ? PPC::X14 : PPC::R13;
2150 unsigned GPREnd = Subtarget->
isPPC64() ? PPC::X31 : PPC::R31;
2152 for (
unsigned Reg = GPRBegin;
Reg <= GPREnd; ++
Reg) {
2154 GPRSaved = GPREnd -
Reg + 1;
2162 GENBOOLCOMMENT(
"", SecondHalfOfMandatoryField, HasExtensionTable);
2164 GENVALUECOMMENT(
", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);
2166 OutStreamer->emitIntValueInHexWithPadding(
2167 (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);
2171 SecondHalfOfMandatoryField |=
2175 NumberOfFixedParms);
2177 OutStreamer->emitIntValueInHexWithPadding(
2178 (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);
2186 SecondHalfOfMandatoryField |=
2191 NumberOfFloatingPointParms);
2192 GENBOOLCOMMENT(
", ", SecondHalfOfMandatoryField, HasParmsOnStack);
2194 OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,
2200 if (NumberOfFixedParms || NumberOfFPParms) {
2206 ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,
2213 CommentOS <<
"Parameter type = " << ParmsType.
get();
2216 OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,
2217 sizeof(ParmsTypeValue));
2220 OutStreamer->AddComment(
"Function size");
2222 MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(
2224 OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);
2237 CommentOS <<
"Function name len = "
2240 OutStreamer->AddComment(
"Function Name");
2241 OutStreamer->emitBytes(
Name);
2246 OutStreamer->AddComment(
"AllocaUsed");
2247 OutStreamer->emitIntValueInHex(AllocReg,
sizeof(AllocReg));
2280 OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);
2285 OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);
2293 CommentOS <<
"Vector Parameter type = " << VecParmsType.
get();
2296 OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,
2297 sizeof(VecParmTypeValue));
2299 CommentOS <<
"Padding";
2300 EmitCommentAndValue(0, 2);
2303 uint8_t ExtensionTableFlag = 0;
2305 if (ShouldEmitEHBlock)
2311 CommentOS <<
"ExtensionTableFlag = "
2313 EmitCommentAndValue(ExtensionTableFlag,
sizeof(ExtensionTableFlag));
2317 auto &Ctx = OutStreamer->getContext();
2320 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym);
2322 cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2323 ->getQualNameSymbol();
2329 OutStreamer->emitValueToAlignment(4);
2330 OutStreamer->AddComment(
"EHInfo Table");
2331 OutStreamer->emitValue(Exp,
DL.getPointerSize());
2333 #undef GENBOOLCOMMENT
2334 #undef GENVALUECOMMENT
2343 .
Case(
"llvm.used",
true)
2345 .
Case(
"llvm.compiler.used",
true)
2351 .
Cases(
"llvm.global_ctors",
"llvm.global_dtors",
true)
2355 void PPCAIXAsmPrinter::emitGlobalVariable(
const GlobalVariable *GV) {
2363 TOCDataGlobalVars.push_back(GV);
2367 emitGlobalVariableHelper(GV);
2370 void PPCAIXAsmPrinter::emitGlobalVariableHelper(
const GlobalVariable *GV) {
2372 "Unhandled intrinsic global variable.");
2380 emitLinkage(GV, GVSym);
2384 SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV,
TM);
2388 "not supported yet.");
2395 OutStreamer->GetCommentOS() <<
'\n';
2400 getObjFileLowering().SectionForGlobal(GV, GVKind,
TM));
2403 OutStreamer->SwitchSection(Csect);
2416 OutStreamer->emitXCOFFLocalCommonSymbol(
2420 OutStreamer->emitCommonSymbol(GVSym, Size,
Alignment.value());
2425 emitLinkage(GV, EmittedInitSym);
2426 emitAlignment(getGVAlignment(GV,
DL), GV);
2431 OutStreamer->emitLabel(EmittedInitSym);
2436 OutStreamer->emitLabel(getSymbol(Alias));
2439 emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
2442 void PPCAIXAsmPrinter::emitFunctionDescriptor() {
2444 const unsigned PointerSize =
DL.getPointerSizeInBits() == 64 ? 8 : 4;
2448 OutStreamer->SwitchSection(
2449 cast<MCSymbolXCOFF>(CurrentFnDescSym)->getRepresentedCsect());
2454 OutStreamer->emitLabel(getSymbol(Alias));
2462 cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2463 ->getQualNameSymbol();
2469 OutStreamer->SwitchSection(Current.first, Current.second);
2472 void PPCAIXAsmPrinter::emitFunctionEntryLabel() {
2475 if (!
TM.getFunctionSections())
2476 PPCAsmPrinter::emitFunctionEntryLabel();
2481 OutStreamer->emitLabel(
2482 getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));
2486 void PPCAIXAsmPrinter::emitPGORefs() {
2487 if (OutContext.hasXCOFFSection(
2490 MCSection *CntsSection = OutContext.getXCOFFSection(
2495 OutStreamer->SwitchSection(CntsSection);
2496 if (OutContext.hasXCOFFSection(
2499 OutStreamer->emitXCOFFRefDirective(
"__llvm_prf_data[RW]");
2500 if (OutContext.hasXCOFFSection(
2503 OutStreamer->emitXCOFFRefDirective(
"__llvm_prf_names[RO]");
2504 if (OutContext.hasXCOFFSection(
2507 OutStreamer->emitXCOFFRefDirective(
"__llvm_prf_vnds[RW]");
2511 void PPCAIXAsmPrinter::emitEndOfAsmFile(
Module &M) {
2514 if (
M.empty() && TOCDataGlobalVars.empty())
2520 OutStreamer->SwitchSection(getObjFileLowering().getTOCBaseSection());
2525 for (
auto &
I : TOC) {
2530 if (
I.first.second == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM) {
2534 Name +=
I.first.first->getName();
2536 TCEntry = cast<MCSectionXCOFF>(
2537 getObjFileLowering().getSectionForTOCEntry(
S,
TM));
2539 TCEntry = cast<MCSectionXCOFF>(
2540 getObjFileLowering().getSectionForTOCEntry(
I.first.first,
TM));
2542 OutStreamer->SwitchSection(TCEntry);
2544 OutStreamer->emitLabel(
I.second);
2549 for (
const auto *GV : TOCDataGlobalVars)
2550 emitGlobalVariableHelper(GV);
2553 bool PPCAIXAsmPrinter::doInitialization(
Module &M) {
2554 const bool Result = PPCAsmPrinter::doInitialization(M);
2556 auto setCsectAlignment = [
this](
const GlobalObject *GO) {
2558 if (GO->isDeclarationForLinker())
2561 SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO,
TM);
2563 getObjFileLowering().SectionForGlobal(GO, GOKind,
TM));
2565 Align GOAlign = getGVAlignment(GO, GO->getParent()->getDataLayout());
2573 for (
const auto &
G :
M.globals()) {
2580 if (FormatIndicatorAndUniqueModId.empty()) {
2582 if (UniqueModuleId !=
"")
2586 FormatIndicatorAndUniqueModId =
"clang_" + UniqueModuleId.substr(1);
2592 FormatIndicatorAndUniqueModId =
2594 "_" + llvm::itostr(time(
nullptr));
2597 emitSpecialLLVMGlobal(&
G);
2601 setCsectAlignment(&
G);
2604 for (
const auto &
F : M)
2605 setCsectAlignment(&
F);
2608 for (
const auto &Alias :
M.aliases()) {
2612 "alias without a base object is not yet supported on AIX");
2613 GOAliasMap[
Base].push_back(&Alias);
2620 switch (
MI->getOpcode()) {
2623 case PPC::GETtlsADDR64AIX:
2624 case PPC::GETtlsADDR32AIX: {
2628 ExtSymSDNodeSymbols.insert(TlsGetAddr);
2638 cast<MCSymbolXCOFF>(OutContext.getOrCreateSymbol(MO.
getSymbolName()));
2639 ExtSymSDNodeSymbols.insert(
S);
2645 case PPC::BL8_NOP_TLS:
2652 case PPC::TAILBCTR8:
2653 if (
MI->getOperand(0).isSymbol())
2666 MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));
2669 return PPCAsmPrinter::emitInstruction(
MI);
2672 bool PPCAIXAsmPrinter::doFinalization(
Module &M) {
2674 if (!MAI->usesDwarfFileAndLocDirectives() && MMI->hasDebugInfo())
2675 OutStreamer->doFinalizationAtSectionEnd(
2676 OutStreamer->getContext().getObjectFileInfo()->getTextSection());
2678 for (
MCSymbol *Sym : ExtSymSDNodeSymbols)
2679 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Extern);
2680 return PPCAsmPrinter::doFinalization(M);
2684 if (P < 0 || P > 65535)
2691 return 20 + (
P - 20) * 16;
2694 return 1004 + (
P - 81);
2697 return 2047 + (
P - 1124) * 33878;
2699 return 2147482625u + (
P - 64512);
2718 std::string PrioritySuffix;
2722 return PrioritySuffix;
2725 void PPCAIXAsmPrinter::emitXXStructorList(
const DataLayout &
DL,
2726 const Constant *List,
bool IsCtor) {
2728 preprocessXXStructorList(
DL, List, Structors);
2729 if (Structors.empty())
2733 for (Structor &
S : Structors) {
2734 if (
const ConstantExpr *CE = dyn_cast<ConstantExpr>(
S.Func))
2735 S.Func =
CE->getOperand(0);
2743 cast<Function>(
S.Func));
2747 void PPCAIXAsmPrinter::emitTTypeReference(
const GlobalValue *GV,
2748 unsigned Encoding) {
2751 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym);
2753 cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection())
2754 ->getQualNameSymbol();
2755 auto &Ctx = OutStreamer->getContext();
2759 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));
2761 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));
2768 std::unique_ptr<MCStreamer> &&Streamer) {
2770 return new PPCAIXAsmPrinter(tm,
std::move(Streamer));
2772 return new PPCLinuxAsmPrinter(tm,
std::move(Streamer));