77 cl::desc(
"Check pointer authentication auth/resign failures"),
80#define DEBUG_TYPE "asm-printer"
88 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
90 unsigned InstsEmitted;
94 AArch64AsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
95 :
AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *
this),
115 const MCSymbol *BranchLabel)
const override;
138 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
140 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
141 HwasanMemaccessTuple;
142 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
145 void emitHwasanMemaccessSymbols(
Module &M);
152 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
160 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
185 bool MayUseAddrAsScratch =
false);
210 void emitFunctionHeaderComment()
override;
223 if (STI->isTargetCOFF()) {
280 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
282 MInstToMCSymbol LOHInstToLabel;
285 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
300void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
303 if (
TT.isOSBinFormatCOFF()) {
306 OutStreamer->beginCOFFSymbolDef(S);
309 OutStreamer->endCOFFSymbolDef();
310 int64_t Feat00Value = 0;
312 if (
M.getModuleFlag(
"cfguard")) {
314 Feat00Value |= COFF::Feat00Flags::GuardCF;
317 if (
M.getModuleFlag(
"ehcontguard")) {
319 Feat00Value |= COFF::Feat00Flags::GuardEHCont;
322 if (
M.getModuleFlag(
"ms-kernel")) {
324 Feat00Value |= COFF::Feat00Flags::Kernel;
328 OutStreamer->emitAssignment(
332 if (!
TT.isOSBinFormatELF())
337 if (
const auto *BTE = mdconst::extract_or_null<ConstantInt>(
338 M.getModuleFlag(
"branch-target-enforcement")))
342 if (
const auto *GCS = mdconst::extract_or_null<ConstantInt>(
343 M.getModuleFlag(
"guarded-control-stack")))
347 if (
const auto *Sign = mdconst::extract_or_null<ConstantInt>(
348 M.getModuleFlag(
"sign-return-address")))
353 if (
const auto *PAP = mdconst::extract_or_null<ConstantInt>(
354 M.getModuleFlag(
"aarch64-elf-pauthabi-platform")))
355 PAuthABIPlatform = PAP->getZExtValue();
357 if (
const auto *PAV = mdconst::extract_or_null<ConstantInt>(
358 M.getModuleFlag(
"aarch64-elf-pauthabi-version")))
359 PAuthABIVersion = PAV->getZExtValue();
367void AArch64AsmPrinter::emitFunctionHeaderComment() {
370 if (OutlinerString != std::nullopt)
371 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
374void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
377 if (
F.hasFnAttribute(
"patchable-function-entry")) {
379 if (
F.getFnAttribute(
"patchable-function-entry")
381 .getAsInteger(10, Num))
387 emitSled(
MI, SledKind::FUNCTION_ENTER);
390void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
391 emitSled(
MI, SledKind::FUNCTION_EXIT);
394void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
395 emitSled(
MI, SledKind::TAIL_CALL);
398void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
399 static const int8_t NoopsInSledCount = 7;
420 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
421 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
422 OutStreamer->emitLabel(CurSled);
423 auto Target = OutContext.createTempSymbol();
428 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::B).addImm(8));
430 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
431 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
433 OutStreamer->emitLabel(
Target);
434 recordSled(CurSled,
MI, Kind, 2);
452void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
454 auto &
O = *OutStreamer;
455 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
456 O.emitLabel(CurSled);
457 bool MachO =
TM.getTargetTriple().isOSBinFormatMachO();
459 OutContext.getOrCreateSymbol(
460 Twine(MachO ?
"_" :
"") +
461 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
464 O.AddComment(
"Begin XRay typed event");
476 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
477 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
478 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
484 O.AddComment(
"End XRay typed event");
492 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
494 O.AddComment(
"Begin XRay custom event");
502 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
503 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
505 O.AddComment(
"End XRay custom event");
513 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
519 assert(std::next(
MI.getIterator())->isCall() &&
520 "KCFI_CHECK not followed by a call instruction");
521 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
522 "KCFI_CHECK call target doesn't match call operand");
526 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
527 if (AddrReg == AArch64::XZR) {
531 emitMovXReg(AddrReg, AArch64::XZR);
537 for (
auto &Reg : ScratchRegs) {
543 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
544 "Invalid scratch registers for KCFI_CHECK");
548 int64_t PrefixNops = 0;
551 .getFnAttribute(
"patchable-function-prefix")
553 .getAsInteger(10, PrefixNops);
557 .addReg(ScratchRegs[0])
559 .addImm(-(PrefixNops * 4 + 4)));
563 const int64_t
Type =
MI.getOperand(1).getImm();
564 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
565 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
569 .addReg(AArch64::WZR)
570 .addReg(ScratchRegs[0])
571 .addReg(ScratchRegs[1])
575 EmitToStreamer(*OutStreamer,
585 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
589 AddrIndex = AddrReg - AArch64::X0;
599 assert(AddrIndex < 31 && TypeIndex < 31);
601 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
602 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BRK).addImm(ESR));
603 OutStreamer->emitLabel(
Pass);
606void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
609 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
611 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
612 uint32_t AccessInfo =
MI.getOperand(1).getImm();
614 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
616 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
617 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
619 MCSymbol *&
Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
620 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
623 if (!
TM.getTargetTriple().isOSBinFormatELF())
626 std::string SymName =
"__hwasan_check_x" + utostr(Reg - AArch64::X0) +
"_" +
629 SymName +=
"_fixed_" + utostr(FixedShadowOffset);
631 SymName +=
"_short_v2";
632 Sym = OutContext.getOrCreateSymbol(SymName);
635 EmitToStreamer(*OutStreamer,
640void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
641 if (HwasanMemaccessSymbols.empty())
646 std::unique_ptr<MCSubtargetInfo> STI(
647 TM.getTarget().createMCSubtargetInfo(
TT.str(),
"",
""));
648 assert(STI &&
"Unable to create subtarget info");
652 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
654 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
661 for (
auto &
P : HwasanMemaccessSymbols) {
662 unsigned Reg = std::get<0>(
P.first);
663 bool IsShort = std::get<1>(
P.first);
664 uint32_t AccessInfo = std::get<2>(
P.first);
665 bool IsFixedShadow = std::get<3>(
P.first);
666 uint64_t FixedShadowOffset = std::get<4>(
P.first);
668 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
671 bool HasMatchAllTag =
680 OutStreamer->switchSection(OutContext.getELFSection(
688 OutStreamer->emitLabel(
Sym);
691 .addReg(AArch64::X16)
701 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
703 .addReg(AArch64::W16)
704 .addReg(AArch64::X17)
705 .addReg(AArch64::X16)
710 .addReg(AArch64::W16)
711 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
712 .addReg(AArch64::X16)
718 .addReg(AArch64::XZR)
719 .addReg(AArch64::X16)
722 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
726 HandleMismatchOrPartialSym, OutContext)));
727 MCSymbol *ReturnSym = OutContext.createTempSymbol();
728 OutStreamer->emitLabel(ReturnSym);
729 EmitToStreamer(
MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
730 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
732 if (HasMatchAllTag) {
734 .addReg(AArch64::X17)
739 .addReg(AArch64::XZR)
740 .addReg(AArch64::X17)
751 .addReg(AArch64::WZR)
752 .addReg(AArch64::W16)
755 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
762 .addReg(AArch64::X17)
767 .addReg(AArch64::X17)
768 .addReg(AArch64::X17)
772 .addReg(AArch64::WZR)
773 .addReg(AArch64::W16)
774 .addReg(AArch64::W17)
782 .addReg(AArch64::X16)
786 .addReg(AArch64::W16)
787 .addReg(AArch64::X16)
791 .addReg(AArch64::XZR)
792 .addReg(AArch64::X16)
800 OutStreamer->emitLabel(HandleMismatchSym);
815 if (Reg != AArch64::X0)
816 emitMovXReg(AArch64::X0, Reg);
823 EmitToStreamer(
MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
830 .addReg(AArch64::X16)
832 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
836 .addReg(AArch64::X16)
837 .addReg(AArch64::X16)
839 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
841 EmitToStreamer(
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
849 const MCExpr *StubAuthPtrRef) {
852 OutStreamer.
emitValue(StubAuthPtrRef, 8);
855void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
856 emitHwasanMemaccessSymbols(M);
859 if (
TT.isOSBinFormatMachO()) {
866 if (!Stubs.empty()) {
868 OutStreamer->switchSection(
871 emitAlignment(
Align(8));
873 for (
const auto &Stub : Stubs)
876 OutStreamer->addBlankLine();
887 if (
TT.isOSBinFormatELF()) {
893 if (!Stubs.empty()) {
896 emitAlignment(
Align(8));
898 for (
const auto &Stub : Stubs)
901 OutStreamer->addBlankLine();
911 const auto *PtrAuthELFGOTFlag = mdconst::extract_or_null<ConstantInt>(
912 M.getModuleFlag(
"ptrauth-elf-got"));
913 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
915 if (!GV.use_empty() && isa<Function>(GV) &&
916 !GV.getName().starts_with(
"llvm."))
917 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
922 FM.serializeToFaultMapSection();
926void AArch64AsmPrinter::emitLOHs() {
929 for (
const auto &
D : AArch64FI->getLOHContainer()) {
931 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
932 assert(LabelIt != LOHInstToLabel.end() &&
933 "Label hasn't been inserted for LOH related instruction");
936 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
941void AArch64AsmPrinter::emitFunctionBodyEnd() {
942 if (!AArch64FI->getLOHRelated().empty())
947MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
951 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
952 return OutContext.getOrCreateSymbol(
953 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
954 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
959void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
977 PrintSymbolOperand(MO, O);
988bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1012bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1015 assert(MO.
isReg() &&
"Should only get here with a register!");
1025bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1034 if (ExtraCode && ExtraCode[0]) {
1035 if (ExtraCode[1] != 0)
1038 switch (ExtraCode[0]) {
1046 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1060 switch (ExtraCode[0]) {
1062 RC = &AArch64::FPR8RegClass;
1065 RC = &AArch64::FPR16RegClass;
1068 RC = &AArch64::FPR32RegClass;
1071 RC = &AArch64::FPR64RegClass;
1074 RC = &AArch64::FPR128RegClass;
1077 RC = &AArch64::ZPRRegClass;
1082 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1095 if (AArch64::GPR32allRegClass.
contains(Reg) ||
1096 AArch64::GPR64allRegClass.
contains(Reg))
1100 if (AArch64::GPR64x8ClassRegClass.
contains(Reg))
1103 unsigned AltName = AArch64::NoRegAltName;
1105 if (AArch64::ZPRRegClass.
contains(Reg)) {
1106 RegClass = &AArch64::ZPRRegClass;
1107 }
else if (AArch64::PPRRegClass.
contains(Reg)) {
1108 RegClass = &AArch64::PPRRegClass;
1109 }
else if (AArch64::PNRRegClass.
contains(Reg)) {
1110 RegClass = &AArch64::PNRRegClass;
1112 RegClass = &AArch64::FPR128RegClass;
1113 AltName = AArch64::vreg;
1117 return printAsmRegInClass(MO, RegClass, AltName, O);
1124bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1126 const char *ExtraCode,
1128 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1132 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1137void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1139 unsigned NOps =
MI->getNumOperands();
1141 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1143 OS <<
MI->getDebugVariable()->getName();
1146 assert(
MI->isIndirectDebugValue());
1148 for (
unsigned I = 0, E = std::distance(
MI->debug_operands().begin(),
1149 MI->debug_operands().end());
1160void AArch64AsmPrinter::emitJumpTableInfo() {
1165 if (
JT.empty())
return;
1169 OutStreamer->switchSection(ReadOnlySec);
1172 for (
unsigned JTI = 0, e =
JT.size(); JTI !=
e; ++JTI) {
1173 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1176 if (JTBBs.empty())
continue;
1178 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1180 OutStreamer->emitLabel(GetJTISymbol(JTI));
1182 const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1185 for (
auto *JTBB : JTBBs) {
1205AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1207 const MCSymbol *BranchLabel)
const {
1209 const auto Base = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1211 switch (AFI->getJumpTableEntrySize(JTI)) {
1213 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1216 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1219 EntrySize = codeview::JumpTableEntrySize::Int32;
1224 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1227void AArch64AsmPrinter::emitFunctionEntryLabel() {
1229 MF->getFunction().getCallingConv() ==
1239 if (
TM.getTargetTriple().isWindowsArm64EC() &&
1240 !MF->getFunction().hasLocalLinkage()) {
1245 OutStreamer->emitAssignment(
1247 MMI->getContext()));
1253 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1254 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1260 getSymbolFromMetadata(
"arm64ec_unmangled_name")) {
1261 MCSymbol *ECMangledSym = getSymbolFromMetadata(
"arm64ec_ecmangled_name");
1267 emitFunctionAlias(UnmangledSym, ECMangledSym);
1268 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1272 emitFunctionAlias(UnmangledSym, CurrentFnSym);
1278void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1280 if (
const auto *CPA = dyn_cast<ConstantPtrAuth>(CV))
1281 if (CPA->hasAddressDiscriminator() &&
1282 !CPA->hasSpecialAddressDiscriminator(
1285 "unexpected address discrimination value for ctors/dtors entry, only "
1286 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1295void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1297 if (
auto F = dyn_cast_or_null<Function>(GA.
getAliasee())) {
1302 if (
MDNode *
Node =
F->getMetadata(
"arm64ec_exp_name")) {
1303 StringRef ExpStr = cast<MDString>(
Node->getOperand(0))->getString();
1304 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1307 OutStreamer->beginCOFFSymbolDef(ExpSym);
1311 OutStreamer->endCOFFSymbolDef();
1313 OutStreamer->beginCOFFSymbolDef(
Sym);
1317 OutStreamer->endCOFFSymbolDef();
1319 OutStreamer->emitAssignment(
1321 MMI->getContext()));
1339 Register DestReg =
MI.getOperand(0).getReg();
1340 Register ScratchReg =
MI.getOperand(1).getReg();
1342 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1343 Register TableReg =
MI.getOperand(2).getReg();
1344 Register EntryReg =
MI.getOperand(3).getReg();
1345 int JTIdx =
MI.getOperand(4).getIndex();
1346 int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
1356 Label = MF->getContext().createTempSymbol();
1357 AArch64FI->setJumpTableEntryInfo(JTIdx,
Size, Label);
1364 .addExpr(LabelExpr));
1369 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1370 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1371 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1377 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1381 .addImm(
Size == 1 ? 0 : 1));
1389 .addImm(
Size == 4 ? 0 : 2));
1392void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1394 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1396 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1397 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1416 assert(!AArch64FI->getJumpTableEntryPCRelSymbol(JTI) &&
1417 "unsupported compressed jump table");
1419 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1423 uint64_t MaxTableEntry = NumTableEntries - 1;
1424 if (isUInt<12>(MaxTableEntry)) {
1425 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXri)
1426 .addReg(AArch64::XZR)
1427 .addReg(AArch64::X16)
1428 .addImm(MaxTableEntry)
1431 emitMOVZ(AArch64::X17,
static_cast<uint16_t>(MaxTableEntry), 0);
1436 if ((MaxTableEntry >>
Offset) == 0)
1438 emitMOVK(AArch64::X17,
static_cast<uint16_t>(MaxTableEntry >>
Offset),
1441 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXrs)
1442 .addReg(AArch64::XZR)
1443 .addReg(AArch64::X16)
1444 .addReg(AArch64::X17)
1451 .addReg(AArch64::X16)
1452 .addReg(AArch64::X16)
1453 .addReg(AArch64::XZR)
1463 MCInstLowering.lowerOperand(JTMOHi, JTMCHi);
1464 MCInstLowering.lowerOperand(JTMOLo, JTMCLo);
1471 .addReg(AArch64::X17)
1472 .addReg(AArch64::X17)
1476 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::LDRSWroX)
1477 .addReg(AArch64::X16)
1478 .addReg(AArch64::X17)
1479 .addReg(AArch64::X16)
1483 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1485 AArch64FI->setJumpTableEntryInfo(JTI, 4, AdrLabel);
1490 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1493 .addReg(AArch64::X16)
1494 .addReg(AArch64::X17)
1495 .addReg(AArch64::X16)
1498 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1503 unsigned Opcode =
MI.getOpcode();
1505 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1507 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1508 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1509 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1510 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1511 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1512 if (Opcode == AArch64::MOPSMemorySetPseudo)
1513 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1514 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1515 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1518 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1519 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1521 for (
auto Op : Ops) {
1525 MCIB.addReg(
MI.getOperand(i++).getReg());
1526 MCIB.addReg(
MI.getOperand(i++).getReg());
1528 MCIB.addReg(
MI.getOperand(i++).getReg());
1530 MCIB.addReg(
MI.getOperand(i++).getReg());
1531 MCIB.addReg(
MI.getOperand(i++).getReg());
1532 MCIB.addReg(
MI.getOperand(i++).getReg());
1534 EmitToStreamer(OutStreamer, MCIB);
1543 MCSymbol *MILabel = Ctx.createTempSymbol();
1547 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1553 while (NumNOPBytes > 0) {
1554 if (MII ==
MBB.
end() || MII->isCall() ||
1555 MII->getOpcode() == AArch64::DBG_VALUE ||
1556 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1557 MII->getOpcode() == TargetOpcode::STACKMAP)
1564 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1565 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1573 MCSymbol *MILabel = Ctx.createTempSymbol();
1579 int64_t CallTarget = Opers.getCallTarget().getImm();
1580 unsigned EncodedBytes = 0;
1582 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1583 "High 16 bits of call target should be zero.");
1584 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1587 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1588 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1589 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1590 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1593 unsigned NumBytes = Opers.getNumPatchBytes();
1594 assert(NumBytes >= EncodedBytes &&
1595 "Patchpoint can't request size less than the length of a call.");
1596 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1597 "Invalid number of NOP bytes requested!");
1598 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1599 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1605 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1606 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1607 for (
unsigned i = 0; i < PatchBytes; i += 4)
1608 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1613 unsigned CallOpcode;
1614 switch (CallTarget.
getType()) {
1617 MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
1618 CallOpcode = AArch64::BL;
1622 CallOpcode = AArch64::BL;
1626 CallOpcode = AArch64::BLR;
1633 EmitToStreamer(OutStreamer,
1638 MCSymbol *MILabel = Ctx.createTempSymbol();
1643void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1652 unsigned OperandsBeginIdx = 4;
1655 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1659 FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
1662 MI.setOpcode(Opcode);
1670 lowerOperand(MO, Dest);
1671 MI.addOperand(Dest);
1681 .addReg(AArch64::XZR)
1686void AArch64AsmPrinter::emitMOVZ(
Register Dest,
uint64_t Imm,
unsigned Shift) {
1687 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1688 EmitToStreamer(*OutStreamer,
1695void AArch64AsmPrinter::emitMOVK(
Register Dest,
uint64_t Imm,
unsigned Shift) {
1696 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1697 EmitToStreamer(*OutStreamer,
1706 Register DestReg =
MI.getOperand(0).getReg();
1707 if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() &&
1708 STI->isNeonAvailable()) {
1710 if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
1711 DestReg = AArch64::D0 + (DestReg - AArch64::H0);
1712 else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
1713 DestReg = AArch64::D0 + (DestReg - AArch64::S0);
1715 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
1718 MOVI.setOpcode(AArch64::MOVID);
1721 EmitToStreamer(*OutStreamer, MOVI);
1724 switch (
MI.getOpcode()) {
1726 case AArch64::FMOVH0:
1727 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1728 if (!STI->hasFullFP16())
1729 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1733 case AArch64::FMOVS0:
1738 case AArch64::FMOVD0:
1744 EmitToStreamer(*OutStreamer, FMov);
1751 bool MayUseAddrAsScratch) {
1752 assert(ScratchReg == AArch64::X16 || ScratchReg == AArch64::X17);
1754 if (AddrDisc == AArch64::NoRegister)
1755 AddrDisc = AArch64::XZR;
1763 if (AddrDisc == AArch64::XZR) {
1764 emitMOVZ(ScratchReg, Disc, 0);
1771 assert(MayUseAddrAsScratch || ScratchReg != AddrDisc);
1772 bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
1773 if (MayUseAddrAsScratch && AddrDiscIsSafe)
1774 ScratchReg = AddrDisc;
1776 emitMovXReg(ScratchReg, AddrDisc);
1778 emitMOVK(ScratchReg, Disc, 48);
1786void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
1819 if (Method == AuthCheckMethod::None)
1821 if (Method == AuthCheckMethod::DummyLoad) {
1826 assert(ShouldTrap && !OnFailure &&
"DummyLoad always traps on error");
1830 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
1831 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
1833 emitMovXReg(ScratchReg, TestedReg);
1835 if (Method == AuthCheckMethod::XPAC) {
1839 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
1844 assert(TestedReg == AArch64::LR &&
1845 "XPACHint mode is only compatible with checking the LR register");
1847 "XPACHint mode is only compatible with I-keys");
1853 .addReg(AArch64::XZR)
1863 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
1881 assert(!OnFailure &&
"Cannot specify OnFailure with ShouldTrap");
1884 EmitToStreamer(
MCInstBuilder(AArch64::BRK).addImm(0xc470 | Key));
1898 case AuthCheckMethod::XPACHint:
1901 case AuthCheckMethod::XPAC:
1903 emitMovXReg(TestedReg, ScratchReg);
1910 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
1930void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
1931 if (!AArch64FI->shouldSignReturnAddress(*MF))
1934 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
1935 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
1942 "Neither x16 nor x17 is available as a scratch register");
1945 emitPtrauthCheckAuthenticatedValue(
1946 AArch64::LR, ScratchReg, Key, LRCheckMethod,
1950void AArch64AsmPrinter::emitPtrauthAuthResign(
const MachineInstr *
MI) {
1951 const bool IsAUTPAC =
MI->getOpcode() == AArch64::AUTPAC;
1965 bool ShouldCheck =
true;
1967 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
1972 ShouldCheck = ShouldTrap =
false;
1979 ShouldCheck = ShouldTrap =
false;
1986 ShouldCheck = ShouldTrap =
true;
1991 uint64_t AUTDisc =
MI->getOperand(1).getImm();
1992 unsigned AUTAddrDisc =
MI->getOperand(2).getReg();
1995 assert(isUInt<16>(AUTDisc));
1997 emitPtrauthDiscriminator(AUTDisc, AUTAddrDisc, AArch64::X17);
1998 bool AUTZero = AUTDiscReg == AArch64::XZR;
2009 EmitToStreamer(*OutStreamer, AUTInst);
2012 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2018 if (IsAUTPAC && !ShouldTrap)
2019 EndSym = createTempSymbol(
"resign_end_");
2021 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AUTKey,
2022 AArch64PAuth::AuthCheckMethod::XPAC,
2023 ShouldTrap, EndSym);
2033 uint64_t PACDisc =
MI->getOperand(4).getImm();
2034 unsigned PACAddrDisc =
MI->getOperand(5).getReg();
2037 assert(isUInt<16>(PACDisc));
2039 emitPtrauthDiscriminator(PACDisc, PACAddrDisc, AArch64::X17);
2040 bool PACZero = PACDiscReg == AArch64::XZR;
2051 EmitToStreamer(*OutStreamer, PACInst);
2058void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2059 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2060 unsigned BrTarget =
MI->getOperand(0).getReg();
2064 "Invalid auth call key");
2067 assert(isUInt<16>(Disc));
2069 unsigned AddrDisc =
MI->getOperand(3).getReg();
2075 if (BrTarget == AddrDisc)
2083 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2085 bool IsZeroDisc = DiscReg == AArch64::XZR;
2090 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
2092 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
2095 Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
2097 Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
2105 EmitToStreamer(*OutStreamer, BRInst);
2115 getDataLayout(),
Offset,
true);
2117 auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
2123 "cannot resolve target base/addend of ptrauth constant");
2141 "' out of range [0, " +
2145 if (!isUInt<16>(Disc))
2147 "' out of range [0, 0xFFFF]");
2154void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2155 unsigned DstReg =
MI.getOperand(0).getReg();
2157 const uint64_t KeyC =
MI.getOperand(2).getImm();
2159 "key is out of range [0, AArch64PACKey::LAST]");
2161 const uint64_t Disc =
MI.getOperand(3).getImm();
2162 assert(isUInt<16>(Disc) &&
2163 "constant discriminator is out of range [0, 0xffff]");
2172 if (
TM.getTargetTriple().isOSBinFormatELF()) {
2177 "non-zero offset for $auth_ptr$ stub slots is not supported");
2179 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym, Key, Disc);
2181 assert(
TM.getTargetTriple().isOSBinFormatMachO() &&
2182 "LOADauthptrstatic is implemented only for MachO/ELF");
2185 getObjFileLowering());
2188 "non-zero offset for $auth_ptr$ stub slots is not supported");
2190 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym, Key, Disc);
2199 MCInstLowering.lowerOperand(StubMOHi, StubMCHi);
2200 MCInstLowering.lowerOperand(StubMOLo, StubMCLo);
2213 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2214 const bool IsELFSignedGOT =
MI.getParent()
2217 ->hasELFSignedGOT();
2219 const uint64_t KeyC =
MI.getOperand(1).getImm();
2221 "key is out of range [0, AArch64PACKey::LAST]");
2223 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2224 const uint64_t Disc =
MI.getOperand(3).getImm();
2225 assert(isUInt<16>(Disc) &&
2226 "constant discriminator is out of range [0, 0xffff]");
2283 MCInstLowering.lowerOperand(GAMOHi, GAMCHi);
2284 MCInstLowering.lowerOperand(GAMOLo, GAMCLo);
2288 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2292 if (IsELFSignedGOT) {
2294 .addReg(AArch64::X17)
2295 .addReg(AArch64::X17)
2300 .addReg(AArch64::X16)
2301 .addReg(AArch64::X17)
2311 .addReg(AArch64::X16)
2312 .addReg(AArch64::X16)
2313 .addReg(AArch64::X17));
2315 if (!STI->hasFPAC()) {
2319 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2320 AArch64PAuth::AuthCheckMethod::XPAC,
2326 .addReg(AArch64::X16)
2327 .addReg(AArch64::X16)
2332 .addReg(AArch64::X16)
2333 .addReg(AArch64::X16)
2340 const bool IsNeg =
Offset < 0;
2341 if (isUInt<24>(AbsOffset)) {
2342 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2346 .addReg(AArch64::X16)
2347 .addReg(AArch64::X16)
2348 .addImm((AbsOffset >> BitPos) & 0xfff)
2353 EmitToStreamer(
MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2354 .addReg(AArch64::X17)
2355 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
2357 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
2358 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2359 uint64_t Shifted = UOffset >> BitPos;
2361 return Shifted != 0;
2362 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2363 if (((Shifted >>
I) & 0xffff) != 0xffff)
2367 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2368 emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
2371 .addReg(AArch64::X16)
2372 .addReg(AArch64::X16)
2373 .addReg(AArch64::X17)
2378 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2383 if (DiscReg != AArch64::XZR)
2385 EmitToStreamer(MIB);
2388void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2390 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2396 MCInstLowering.lowerOperand(GAMO, GAMC);
2400 .addReg(AuthResultReg)
2401 .addReg(AArch64::X17)
2410 MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
2411 MCInstLowering.lowerOperand(GALoOp, GAMCLo);
2417 .addReg(AArch64::X17)
2418 .addReg(AArch64::X17)
2423 .addReg(AuthResultReg)
2424 .addReg(AArch64::X17)
2431 UndefWeakSym = createTempSymbol(
"undef_weak");
2434 .addReg(AuthResultReg)
2443 .addReg(AuthResultReg)
2444 .addReg(AuthResultReg)
2445 .addReg(AArch64::X17));
2450 if (!STI->hasFPAC()) {
2454 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2455 AArch64PAuth::AuthCheckMethod::XPAC,
2459 emitMovXReg(DstReg, AuthResultReg);
2464AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2468 if (std::optional<uint16_t> BADisc =
2469 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2478#include "AArch64GenMCPseudoLowering.inc"
2488 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
2493 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
2498 if (
MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
2499 EmitToStreamer(*OutStreamer, OutInst);
2503 if (
MI->getOpcode() == AArch64::ADRP) {
2504 for (
auto &Opd :
MI->operands()) {
2505 if (Opd.isSymbol() &&
StringRef(Opd.getSymbolName()) ==
2506 "swift_async_extendedFramePointerFlags") {
2507 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
2512 if (AArch64FI->getLOHRelated().count(
MI)) {
2514 MCSymbol *LOHLabel = createTempSymbol(
"loh");
2516 LOHInstToLabel[
MI] = LOHLabel;
2523 switch (
MI->getOpcode()) {
2526 "Unhandled tail call instruction");
2528 case AArch64::HINT: {
2533 if (CurrentPatchableFunctionEntrySym &&
2534 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
2535 MI == &MF->front().front()) {
2536 int64_t
Imm =
MI->getOperand(0).getImm();
2537 if ((Imm & 32) && (Imm & 6)) {
2539 MCInstLowering.Lower(
MI, Inst);
2540 EmitToStreamer(*OutStreamer, Inst);
2541 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
2542 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
2548 case AArch64::MOVMCSym: {
2549 Register DestReg =
MI->getOperand(0).getReg();
2557 MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
2558 MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
2565 EmitToStreamer(*OutStreamer, MovZ);
2573 EmitToStreamer(*OutStreamer, MovK);
2576 case AArch64::MOVIv2d_ns:
2584 if (STI->hasZeroCycleZeroingFPWorkaround() &&
2585 MI->getOperand(1).getImm() == 0) {
2587 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
2590 EmitToStreamer(*OutStreamer, TmpInst);
2595 case AArch64::DBG_VALUE:
2596 case AArch64::DBG_VALUE_LIST:
2600 PrintDebugValueComment(
MI,
OS);
2605 case AArch64::EMITBKEY: {
2607 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2608 ExceptionHandlingType != ExceptionHandling::ARM)
2611 if (getFunctionCFISectionType(*MF) == CFISection::None)
2618 case AArch64::EMITMTETAGGED: {
2620 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2621 ExceptionHandlingType != ExceptionHandling::ARM)
2624 if (getFunctionCFISectionType(*MF) != CFISection::None)
2630 case AArch64::AUTPAC:
2631 emitPtrauthAuthResign(
MI);
2634 case AArch64::LOADauthptrstatic:
2635 LowerLOADauthptrstatic(*
MI);
2638 case AArch64::LOADgotPAC:
2639 case AArch64::MOVaddrPAC:
2640 LowerMOVaddrPAC(*
MI);
2643 case AArch64::LOADgotAUTH:
2644 LowerLOADgotAUTH(*
MI);
2649 emitPtrauthBranch(
MI);
2655 case AArch64::AUTH_TCRETURN:
2656 case AArch64::AUTH_TCRETURN_BTI: {
2660 "Invalid auth key for tail-call return");
2662 const uint64_t Disc =
MI->getOperand(3).getImm();
2663 assert(isUInt<16>(Disc) &&
"Integer discriminator is too wide");
2665 Register AddrDisc =
MI->getOperand(4).getReg();
2667 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2669 emitPtrauthTailCallHardening(
MI);
2672 if (Callee == AddrDisc)
2674 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
2677 const bool IsZero = DiscReg == AArch64::XZR;
2678 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
2679 {AArch64::BRAB, AArch64::BRABZ}};
2682 TmpInst.
setOpcode(Opcodes[Key][IsZero]);
2686 EmitToStreamer(*OutStreamer, TmpInst);
2690 case AArch64::TCRETURNri:
2691 case AArch64::TCRETURNrix16x17:
2692 case AArch64::TCRETURNrix17:
2693 case AArch64::TCRETURNrinotx16:
2694 case AArch64::TCRETURNriALL: {
2695 emitPtrauthTailCallHardening(
MI);
2700 EmitToStreamer(*OutStreamer, TmpInst);
2703 case AArch64::TCRETURNdi: {
2704 emitPtrauthTailCallHardening(
MI);
2707 MCInstLowering.lowerOperand(
MI->getOperand(0), Dest);
2711 EmitToStreamer(*OutStreamer, TmpInst);
2714 case AArch64::SpeculationBarrierISBDSBEndBB: {
2719 EmitToStreamer(*OutStreamer, TmpInstDSB);
2723 EmitToStreamer(*OutStreamer, TmpInstISB);
2726 case AArch64::SpeculationBarrierSBEndBB: {
2730 EmitToStreamer(*OutStreamer, TmpInstSB);
2733 case AArch64::TLSDESC_CALLSEQ: {
2746 MCInstLowering.lowerOperand(MO_Sym,
Sym);
2747 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2748 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2754 EmitToStreamer(*OutStreamer, Adrp);
2757 if (STI->isTargetILP32()) {
2767 EmitToStreamer(*OutStreamer, Ldr);
2770 if (STI->isTargetILP32()) {
2771 Add.setOpcode(AArch64::ADDWri);
2775 Add.setOpcode(AArch64::ADDXri);
2779 Add.addOperand(SymTLSDescLo12);
2781 EmitToStreamer(*OutStreamer,
Add);
2786 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
2788 EmitToStreamer(*OutStreamer, TLSDescCall);
2796 EmitToStreamer(*OutStreamer, Blr);
2801 case AArch64::JumpTableDest32:
2802 case AArch64::JumpTableDest16:
2803 case AArch64::JumpTableDest8:
2804 LowerJumpTableDest(*OutStreamer, *
MI);
2807 case AArch64::BR_JumpTable:
2808 LowerHardenedBRJumpTable(*
MI);
2811 case AArch64::FMOVH0:
2812 case AArch64::FMOVS0:
2813 case AArch64::FMOVD0:
2817 case AArch64::MOPSMemoryCopyPseudo:
2818 case AArch64::MOPSMemoryMovePseudo:
2819 case AArch64::MOPSMemorySetPseudo:
2820 case AArch64::MOPSMemorySetTaggingPseudo:
2821 LowerMOPS(*OutStreamer, *
MI);
2824 case TargetOpcode::STACKMAP:
2825 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
2827 case TargetOpcode::PATCHPOINT:
2828 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
2830 case TargetOpcode::STATEPOINT:
2831 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
2833 case TargetOpcode::FAULTING_OP:
2834 return LowerFAULTING_OP(*
MI);
2836 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2837 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
2840 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2841 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
2844 case TargetOpcode::PATCHABLE_TAIL_CALL:
2845 LowerPATCHABLE_TAIL_CALL(*
MI);
2847 case TargetOpcode::PATCHABLE_EVENT_CALL:
2848 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
2849 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
2850 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
2852 case AArch64::KCFI_CHECK:
2853 LowerKCFI_CHECK(*
MI);
2856 case AArch64::HWASAN_CHECK_MEMACCESS:
2857 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
2858 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
2859 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
2860 LowerHWASAN_CHECK_MEMACCESS(*
MI);
2863 case AArch64::SEH_StackAlloc:
2867 case AArch64::SEH_SaveFPLR:
2871 case AArch64::SEH_SaveFPLR_X:
2872 assert(
MI->getOperand(0).getImm() < 0 &&
2873 "Pre increment SEH opcode must have a negative offset");
2877 case AArch64::SEH_SaveReg:
2879 MI->getOperand(1).getImm());
2882 case AArch64::SEH_SaveReg_X:
2883 assert(
MI->getOperand(1).getImm() < 0 &&
2884 "Pre increment SEH opcode must have a negative offset");
2886 -
MI->getOperand(1).getImm());
2889 case AArch64::SEH_SaveRegP:
2890 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
2891 MI->getOperand(0).getImm() <= 28) {
2892 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
2893 "Register paired with LR must be odd");
2895 MI->getOperand(2).getImm());
2898 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2899 "Non-consecutive registers not allowed for save_regp");
2901 MI->getOperand(2).getImm());
2904 case AArch64::SEH_SaveRegP_X:
2905 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2906 "Non-consecutive registers not allowed for save_regp_x");
2907 assert(
MI->getOperand(2).getImm() < 0 &&
2908 "Pre increment SEH opcode must have a negative offset");
2910 -
MI->getOperand(2).getImm());
2913 case AArch64::SEH_SaveFReg:
2915 MI->getOperand(1).getImm());
2918 case AArch64::SEH_SaveFReg_X:
2919 assert(
MI->getOperand(1).getImm() < 0 &&
2920 "Pre increment SEH opcode must have a negative offset");
2922 -
MI->getOperand(1).getImm());
2925 case AArch64::SEH_SaveFRegP:
2926 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2927 "Non-consecutive registers not allowed for save_regp");
2929 MI->getOperand(2).getImm());
2932 case AArch64::SEH_SaveFRegP_X:
2933 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2934 "Non-consecutive registers not allowed for save_regp_x");
2935 assert(
MI->getOperand(2).getImm() < 0 &&
2936 "Pre increment SEH opcode must have a negative offset");
2938 -
MI->getOperand(2).getImm());
2941 case AArch64::SEH_SetFP:
2945 case AArch64::SEH_AddFP:
2949 case AArch64::SEH_Nop:
2953 case AArch64::SEH_PrologEnd:
2957 case AArch64::SEH_EpilogStart:
2961 case AArch64::SEH_EpilogEnd:
2965 case AArch64::SEH_PACSignLR:
2969 case AArch64::SEH_SaveAnyRegQP:
2970 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2971 "Non-consecutive registers not allowed for save_any_reg");
2972 assert(
MI->getOperand(2).getImm() >= 0 &&
2973 "SaveAnyRegQP SEH opcode offset must be non-negative");
2974 assert(
MI->getOperand(2).getImm() <= 1008 &&
2975 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
2977 MI->getOperand(2).getImm());
2980 case AArch64::SEH_SaveAnyRegQPX:
2981 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2982 "Non-consecutive registers not allowed for save_any_reg");
2983 assert(
MI->getOperand(2).getImm() < 0 &&
2984 "SaveAnyRegQPX SEH opcode offset must be negative");
2985 assert(
MI->getOperand(2).getImm() >= -1008 &&
2986 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
2988 -
MI->getOperand(2).getImm());
2994 MCInstLowering.Lower(
MI, TmpInst);
2995 EmitToStreamer(*OutStreamer, TmpInst);
3011 MCInstLowering.lowerOperand(
3016 EmitToStreamer(Adrp);
3025 MCInstLowering.lowerOperand(
3031 EmitToStreamer(Ldr);
3035 .addReg(AArch64::X16)
3036 .addReg(AArch64::X16)
3039 EmitToStreamer(
MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3044void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3079 .addReg(AArch64::SP)
3080 .addReg(AArch64::FP)
3081 .addReg(AArch64::LR)
3082 .addReg(AArch64::SP)
3086 .addReg(AArch64::FP)
3087 .addReg(AArch64::SP)
3091 for (
int I = 0;
I != 4; ++
I)
3093 .addReg(AArch64::SP)
3094 .addReg(AArch64::X1 + 2 *
I)
3095 .addReg(AArch64::X0 + 2 *
I)
3096 .addReg(AArch64::SP)
3099 for (
int I = 0;
I != 4; ++
I)
3101 .addReg(AArch64::SP)
3102 .addReg(AArch64::D1 + 2 *
I)
3103 .addReg(AArch64::D0 + 2 *
I)
3104 .addReg(AArch64::SP)
3116 MCInstLowering.lowerOperand(
3121 EmitToStreamer(Adrp);
3130 MCInstLowering.lowerOperand(
3136 EmitToStreamer(Ldr);
3140 .addReg(AArch64::X0)
3141 .addReg(AArch64::X16)
3145 .addReg(AArch64::X16)
3146 .addReg(AArch64::X0)
3150 for (
int I = 3;
I != -1; --
I)
3152 .addReg(AArch64::SP)
3153 .addReg(AArch64::D1 + 2 *
I)
3154 .addReg(AArch64::D0 + 2 *
I)
3155 .addReg(AArch64::SP)
3158 for (
int I = 3;
I != -1; --
I)
3160 .addReg(AArch64::SP)
3161 .addReg(AArch64::X1 + 2 *
I)
3162 .addReg(AArch64::X0 + 2 *
I)
3163 .addReg(AArch64::SP)
3167 .addReg(AArch64::SP)
3168 .addReg(AArch64::FP)
3169 .addReg(AArch64::LR)
3170 .addReg(AArch64::SP)
3173 EmitToStreamer(
MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3178const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV) {
3179 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
static cl::opt< PtrauthCheckMode > PtrauthAuthChecks("aarch64-ptrauth-auth-checks", cl::Hidden, cl::values(clEnumValN(Unchecked, "none", "don't test for failure"), clEnumValN(Poison, "poison", "poison on failure"), clEnumValN(Trap, "trap", "trap on failure")), cl::desc("Check pointer authentication auth/resign failures"), cl::init(Default))
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64AsmPrinter()
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_EXTERNAL_VISIBILITY
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
unsigned const TargetRegisterInfo * TRI
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallString class.
This file defines the SmallVector class.
static bool printAsmMRegister(const X86AsmPrinter &P, const MachineOperand &MO, char Mode, raw_ostream &O)
static const AArch64AuthMCExpr * create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, bool HasAddressDiversity, MCContext &Ctx)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
std::optional< std::string > getOutliningStyle() const
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
static const AArch64MCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
virtual void emitARM64WinCFISaveRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPACSignLR()
virtual void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFIAllocStack(unsigned Size)
virtual void emitARM64WinCFISaveFPLRX(int Offset)
virtual void emitDirectiveVariantPCS(MCSymbol *Symbol)
Callback used to implement the .variant_pcs directive.
virtual void emitARM64WinCFIAddFP(unsigned Size)
virtual void emitARM64WinCFISaveFPLR(int Offset)
virtual void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISetFP()
virtual void emitARM64WinCFIEpilogEnd()
virtual void emitARM64WinCFIPrologEnd()
void emitNoteSection(unsigned Flags, uint64_t PAuthABIPlatform=-1, uint64_t PAuthABIVersion=-1)
Callback used to implement the .note.gnu.property section.
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFINop()
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
virtual void emitARM64WinCFIEpilogStart()
This implementation is used for AArch64 ELF targets (Linux in particular).
AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin.
Class for arbitrary precision integers.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
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.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
virtual const MCExpr * lowerConstantPtrAuth(const ConstantPtrAuth &CPA)
void emitXRayTable()
Emit a table with all XRay instrumentation points.
virtual void emitGlobalAlias(const Module &M, const GlobalAlias &GA)
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
virtual void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI, MCSymbol *LazyPointer)
virtual void emitJumpTableInfo()
Print assembly representations of the jump tables used by the current function to the current output ...
virtual void SetupMachineFunction(MachineFunction &MF)
This should be called when a new MachineFunction is being processed from runOnMachineFunction.
void emitFunctionBody()
This method emits the body and trailer for a function.
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
virtual void emitEndOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the end of their file...
virtual void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI, MCSymbol *LazyPointer)
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
virtual bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const
virtual const MCSubtargetInfo * getIFuncMCSubtargetInfo() const
getSubtargetInfo() cannot be used where this is needed because we don't have a MachineFunction when w...
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
virtual const MCExpr * lowerConstant(const Constant *CV)
Lower the specified LLVM Constant to an MCExpr.
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...
virtual void emitXXStructor(const DataLayout &DL, const Constant *CV)
Targets can override this to change how global constants that are part of a C++ static/global constru...
virtual void emitFunctionBodyEnd()
Targets can override this to emit stuff after the last basic block in the function.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual std::tuple< const MCSymbol *, uint64_t, const MCSymbol *, codeview::JumpTableEntrySize > getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr, const MCSymbol *BranchLabel) const
Gets information required to create a CodeView debug symbol for a jump table.
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.
virtual const MCExpr * lowerBlockAddressConstant(const BlockAddress &BA)
Lower the specified BlockAddress to an MCExpr.
The address of a basic block.
Function * getFunction() const
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
A signed pointer, in the ptrauth sense.
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
ConstantInt * getKey() const
The Key ID, an i32 constant.
@ AddrDiscriminator_CtorsDtors
bool hasAddressDiscriminator() const
Whether there is any non-null address discriminator.
ConstantInt * getDiscriminator() const
The integer discriminator, an i64 constant, or 0.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
const Constant * getAliasee() const
const Constant * getResolver() const
bool hasLocalLinkage() const
bool hasExternalWeakLinkage() const
Type * getValueType() const
void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
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.
Base class for the full range of assembler expressions which are needed for parsing.
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
MCSection * getDataSection() const
Instances of this class represent operands of the MCInst class.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Streaming machine code generation interface.
virtual void emitCFIBKeyFrame()
virtual void beginCOFFSymbolDef(const MCSymbol *Symbol)
Start emitting COFF symbol definition.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitCOFFSymbolType(int Type)
Emit the type of the symbol.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
virtual void endCOFFSymbolDef()
Marks the end of the symbol definition.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCFIMTETaggedFrame()
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
void emitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ....
virtual void emitCOFFSymbolStorageClass(int StorageClass)
Emit the storage class of the symbol.
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
StringRef getName() const
getName - Get the symbol name.
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
iterator_range< mop_iterator > operands()
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation for ELF targets.
ExprStubListTy getAuthGVStubList()
MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation for MachO targets.
ExprStubListTy getAuthGVStubList()
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
static MachineOperand CreateMCSymbol(MCSymbol *Sym, unsigned TargetFlags=0)
const GlobalValue * getGlobal() const
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const BlockAddress * getBlockAddress() const
void setOffset(int64_t Offset)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
int64_t getOffset() const
Return the offset from the symbol in this operand.
A Module instance is used to store all the information related to an LLVM module.
Pass interface - Implemented by all 'passes'.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
MI-level patchpoint operands.
Wrapper class representing virtual and physical registers.
static SectionKind getMetadata()
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
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.
MI-level Statepoint operands.
StringRef - Represent a constant reference to a string, i.e.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
virtual MCSection * getSectionForJumpTable(const Function &F, const TargetMachine &TM) const
Primary interface to the complete machine description for the target machine.
MCRegister getRegister(unsigned i) const
Return the specified register in the class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool regsOverlap(Register RegA, Register RegB) const
Returns true if the two registers are equal or alias each other.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
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.
bool isFunctionTy() const
True if this is an instance of FunctionType.
LLVM Value Representation.
const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr) const
Accumulate the constant offset this value has compared to a base pointer.
LLVMContext & getContext() const
All values hold a context through their type.
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 SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
AuthCheckMethod
Variants of check performed on an authenticated pointer.
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
SymbolStorageClass
Storage class tells where and what the symbol represents.
@ IMAGE_SYM_CLASS_EXTERNAL
External symbol.
@ IMAGE_SYM_CLASS_STATIC
Static.
@ IMAGE_SYM_DTYPE_NULL
No complex type; simple scalar variable.
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
@ SCT_COMPLEX_TYPE_SHIFT
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
@ AArch64_VectorCall
Used between AArch64 Advanced SIMD functions.
@ AArch64_SVE_VectorCall
Used between AArch64 SVE functions.
@ GNU_PROPERTY_AARCH64_FEATURE_1_BTI
@ GNU_PROPERTY_AARCH64_FEATURE_1_PAC
@ GNU_PROPERTY_AARCH64_FEATURE_1_GCS
@ S_REGULAR
S_REGULAR - Regular section.
Reg
All possible values of the reg field in the ModR/M byte.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
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.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
Target & getTheAArch64leTarget()
Target & getTheAArch64_32Target()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Target & getTheARM64_32Target()
@ MCAF_SubsectionsViaSymbols
.subsections_via_symbols (MachO)
static MCRegister getXRegFromWReg(MCRegister Reg)
Target & getTheARM64Target()
static MCRegister getXRegFromXRegTuple(MCRegister RegTuple)
static unsigned getPACOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return PAC opcode to be used for a ptrauth sign using the given key, or its PAC*Z variant that doesn'...
static MCRegister getWRegFromXReg(MCRegister Reg)
static unsigned getAUTOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return AUT opcode to be used for a ptrauth auth using the given key, or its AUT*Z variant that doesn'...
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_WeakAntiDep
.weak_anti_dep (COFF)
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
This struct is a compact representation of a valid (non-zero power of two) alignment.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...