82 cl::desc(
"Check pointer authentication auth/resign failures"),
85#define DEBUG_TYPE "asm-printer"
93 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
95 unsigned InstsEmitted;
97 bool EnableImportCallOptimization =
false;
99 SectionToImportedFunctionCalls;
100 unsigned PAuthIFuncNextUniqueID = 1;
105 AArch64AsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
107 MCInstLowering(OutContext, *
this), FM(*
this) {}
109 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
121 void emitStartOfAsmFile(
Module &M)
override;
126 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
127 const MCSymbol *BranchLabel)
const override;
129 void emitFunctionEntryLabel()
override;
150 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
152 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
153 HwasanMemaccessTuple;
154 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
157 void emitHwasanMemaccessSymbols(
Module &M);
164 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
168 const MCSymbol *OnFailure =
nullptr);
171 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
178 std::optional<AArch64PACKey::ID> PACKey,
184 bool emitDeactivationSymbolRelocation(
Value *DS);
208 bool MayUseAddrAsScratch =
false);
222 const MCExpr *emitPAuthRelocationAsIRelative(
224 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
231 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
238 void EmitToStreamer(
const MCInst &Inst) {
239 EmitToStreamer(*OutStreamer, Inst);
244 void emitFunctionHeaderComment()
override;
252 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
253 PSI = &PSIW->getPSI();
255 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
256 SDPI = &SDPIW->getStaticDataProfileInfo();
261 SetupMachineFunction(MF);
263 if (STI->isTargetCOFF()) {
299 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
304 void emitFunctionBodyEnd()
override;
307 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
308 void emitEndOfAsmFile(
Module &M)
override;
323 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
325 MInstToMCSymbol LOHInstToLabel;
327 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
328 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
348void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
349 const Triple &
TT = TM.getTargetTriple();
351 if (
TT.isOSBinFormatCOFF()) {
352 emitCOFFFeatureSymbol(M);
353 emitCOFFReplaceableFunctionData(M);
355 if (
M.getModuleFlag(
"import-call-optimization"))
356 EnableImportCallOptimization =
true;
359 if (!
TT.isOSBinFormatELF())
364 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
367 unsigned BAFlags = 0;
368 unsigned GNUFlags = 0;
370 M.getModuleFlag(
"branch-target-enforcement"))) {
371 if (!BTE->isZero()) {
372 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
378 M.getModuleFlag(
"guarded-control-stack"))) {
379 if (!GCS->isZero()) {
380 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
386 M.getModuleFlag(
"sign-return-address"))) {
387 if (!Sign->isZero()) {
388 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
393 uint64_t PAuthABIPlatform = -1;
395 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
396 PAuthABIPlatform = PAP->getZExtValue();
399 uint64_t PAuthABIVersion = -1;
401 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
402 PAuthABIVersion = PAV->getZExtValue();
406 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
408 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
411void AArch64AsmPrinter::emitFunctionHeaderComment() {
412 const AArch64FunctionInfo *FI = MF->getInfo<AArch64FunctionInfo>();
414 if (OutlinerString != std::nullopt)
415 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
418void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
421 if (
F.hasFnAttribute(
"patchable-function-entry")) {
423 if (
F.getFnAttribute(
"patchable-function-entry")
425 .getAsInteger(10, Num))
431 emitSled(
MI, SledKind::FUNCTION_ENTER);
434void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
435 emitSled(
MI, SledKind::FUNCTION_EXIT);
438void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
439 emitSled(
MI, SledKind::TAIL_CALL);
442void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
443 static const int8_t NoopsInSledCount = 7;
464 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
465 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
466 OutStreamer->emitLabel(CurSled);
467 auto Target = OutContext.createTempSymbol();
472 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
474 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
475 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
477 OutStreamer->emitLabel(Target);
478 recordSled(CurSled,
MI, Kind, 2);
481void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
482 uint64_t PAuthABIPlatform,
483 uint64_t PAuthABIVersion,
484 AArch64TargetStreamer *TS) {
486 PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
487 PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
489 if (PAuthABIPlatform || PAuthABIVersion) {
493 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
494 AArch64BuildAttributes::SubsectionType::ULEB128);
498 PAuthABIPlatform,
"");
512 if (BTIValue || PACValue || GCSValue) {
516 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
517 AArch64BuildAttributes::SubsectionType::ULEB128);
545void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
547 auto &
O = *OutStreamer;
548 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
549 O.emitLabel(CurSled);
550 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
552 OutContext.getOrCreateSymbol(
553 Twine(MachO ?
"_" :
"") +
554 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
557 O.AddComment(
"Begin XRay typed event");
558 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
559 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
565 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
569 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
570 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
571 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
572 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
573 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
577 O.AddComment(
"End XRay typed event");
578 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
585 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
587 O.AddComment(
"Begin XRay custom event");
588 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
589 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
595 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
596 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
597 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
598 O.AddComment(
"End XRay custom event");
599 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
606 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
610void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
612 assert(std::next(
MI.getIterator())->isCall() &&
613 "KCFI_CHECK not followed by a call instruction");
614 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
615 "KCFI_CHECK call target doesn't match call operand");
619 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
620 if (AddrReg == AArch64::XZR) {
624 emitMovXReg(AddrReg, AArch64::XZR);
630 for (
auto &
Reg : ScratchRegs) {
636 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
637 "Invalid scratch registers for KCFI_CHECK");
641 int64_t PrefixNops = 0;
644 .getFnAttribute(
"patchable-function-prefix")
646 .getAsInteger(10, PrefixNops);
649 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
650 .addReg(ScratchRegs[0])
652 .addImm(-(PrefixNops * 4 + 4)));
656 const int64_t
Type =
MI.getOperand(1).getImm();
657 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
658 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
661 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
662 .addReg(AArch64::WZR)
663 .addReg(ScratchRegs[0])
664 .addReg(ScratchRegs[1])
668 EmitToStreamer(*OutStreamer,
669 MCInstBuilder(AArch64::Bcc)
678 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
682 AddrIndex = AddrReg - AArch64::X0;
692 assert(AddrIndex < 31 && TypeIndex < 31);
694 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
695 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
696 OutStreamer->emitLabel(
Pass);
699void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
707 if (
Reg == AArch64::XZR)
711 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
713 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
714 uint32_t AccessInfo =
MI.getOperand(1).getImm();
716 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
718 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
719 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
721 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
722 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
725 if (!TM.getTargetTriple().isOSBinFormatELF())
728 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
731 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
733 SymName +=
"_short_v2";
734 Sym = OutContext.getOrCreateSymbol(SymName);
737 EmitToStreamer(*OutStreamer,
738 MCInstBuilder(AArch64::BL)
742void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
743 if (HwasanMemaccessSymbols.empty())
746 const Triple &
TT = TM.getTargetTriple();
748 std::unique_ptr<MCSubtargetInfo> STI(
749 TM.getTarget().createMCSubtargetInfo(TT,
"",
""));
750 assert(STI &&
"Unable to create subtarget info");
751 this->STI =
static_cast<const AArch64Subtarget *
>(&*STI);
754 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
756 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
758 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
760 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
763 for (
auto &
P : HwasanMemaccessSymbols) {
764 unsigned Reg = std::get<0>(
P.first);
765 bool IsShort = std::get<1>(
P.first);
766 uint32_t AccessInfo = std::get<2>(
P.first);
767 bool IsFixedShadow = std::get<3>(
P.first);
768 uint64_t FixedShadowOffset = std::get<4>(
P.first);
769 const MCSymbolRefExpr *HwasanTagMismatchRef =
770 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
773 bool HasMatchAllTag =
775 uint8_t MatchAllTag =
782 OutStreamer->switchSection(OutContext.getELFSection(
788 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
789 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
790 OutStreamer->emitLabel(Sym);
792 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
793 .addReg(AArch64::X16)
803 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
804 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
805 .addReg(AArch64::W16)
806 .addReg(AArch64::X17)
807 .addReg(AArch64::X16)
811 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
812 .addReg(AArch64::W16)
813 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
814 .addReg(AArch64::X16)
819 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
820 .addReg(AArch64::XZR)
821 .addReg(AArch64::X16)
824 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
825 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
828 HandleMismatchOrPartialSym, OutContext)));
829 MCSymbol *ReturnSym = OutContext.createTempSymbol();
830 OutStreamer->emitLabel(ReturnSym);
831 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
832 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
834 if (HasMatchAllTag) {
835 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
836 .addReg(AArch64::X17)
840 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
841 .addReg(AArch64::XZR)
842 .addReg(AArch64::X17)
846 MCInstBuilder(AArch64::Bcc)
852 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
853 .addReg(AArch64::WZR)
854 .addReg(AArch64::W16)
857 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
859 MCInstBuilder(AArch64::Bcc)
863 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
864 .addReg(AArch64::X17)
868 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
869 .addReg(AArch64::X17)
870 .addReg(AArch64::X17)
873 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
874 .addReg(AArch64::WZR)
875 .addReg(AArch64::W16)
876 .addReg(AArch64::W17)
879 MCInstBuilder(AArch64::Bcc)
883 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
884 .addReg(AArch64::X16)
887 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
888 .addReg(AArch64::W16)
889 .addReg(AArch64::X16)
892 MCInstBuilder(AArch64::SUBSXrs)
893 .addReg(AArch64::XZR)
894 .addReg(AArch64::X16)
898 MCInstBuilder(AArch64::Bcc)
902 OutStreamer->emitLabel(HandleMismatchSym);
905 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
911 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
917 if (
Reg != AArch64::X0)
918 emitMovXReg(AArch64::X0,
Reg);
925 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
930 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
931 .addReg(AArch64::X16)
935 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
936 .addReg(AArch64::X16)
937 .addReg(AArch64::X16)
941 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
949 const MCExpr *StubAuthPtrRef) {
952 OutStreamer.
emitValue(StubAuthPtrRef, 8);
955void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
956 emitHwasanMemaccessSymbols(M);
958 const Triple &
TT = TM.getTargetTriple();
959 if (
TT.isOSBinFormatMachO()) {
961 MachineModuleInfoMachO &MMIMacho =
962 MMI->getObjFileInfo<MachineModuleInfoMachO>();
966 if (!Stubs.empty()) {
968 OutStreamer->switchSection(
971 emitAlignment(
Align(8));
973 for (
const auto &Stub : Stubs)
976 OutStreamer->addBlankLine();
984 OutStreamer->emitSubsectionsViaSymbols();
987 if (
TT.isOSBinFormatELF()) {
989 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
993 if (!Stubs.empty()) {
994 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
996 emitAlignment(
Align(8));
998 for (
const auto &Stub : Stubs)
1001 OutStreamer->addBlankLine();
1012 M.getModuleFlag(
"ptrauth-elf-got"));
1013 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1014 for (
const GlobalValue &GV :
M.global_values())
1016 !GV.getName().starts_with(
"llvm."))
1017 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1026 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1027 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1030 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1031 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1042 for (
auto &[Section, CallsToImportedFuncs] :
1043 SectionToImportedFunctionCalls) {
1045 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1046 OutStreamer->emitInt32(SectionSize);
1047 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1048 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1050 OutStreamer->emitInt32(0x13);
1051 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1052 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1058void AArch64AsmPrinter::emitLOHs() {
1062 for (
const MachineInstr *
MI :
D.getArgs()) {
1063 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1064 assert(LabelIt != LOHInstToLabel.end() &&
1065 "Label hasn't been inserted for LOH related instruction");
1068 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1073void AArch64AsmPrinter::emitFunctionBodyEnd() {
1079MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1083 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1084 return OutContext.getOrCreateSymbol(
1085 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1086 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1091void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1093 const MachineOperand &MO =
MI->getOperand(OpNum);
1109 PrintSymbolOperand(MO, O);
1120bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1144bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1145 const TargetRegisterClass *RC,
1146 unsigned AltName, raw_ostream &O) {
1147 assert(MO.
isReg() &&
"Should only get here with a register!");
1157bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1158 const char *ExtraCode, raw_ostream &O) {
1159 const MachineOperand &MO =
MI->getOperand(OpNum);
1166 if (ExtraCode && ExtraCode[0]) {
1167 if (ExtraCode[1] != 0)
1170 switch (ExtraCode[0]) {
1178 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1191 const TargetRegisterClass *RC;
1192 switch (ExtraCode[0]) {
1194 RC = &AArch64::FPR8RegClass;
1197 RC = &AArch64::FPR16RegClass;
1200 RC = &AArch64::FPR32RegClass;
1203 RC = &AArch64::FPR64RegClass;
1206 RC = &AArch64::FPR128RegClass;
1209 RC = &AArch64::ZPRRegClass;
1214 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1235 unsigned AltName = AArch64::NoRegAltName;
1236 const TargetRegisterClass *RegClass;
1238 RegClass = &AArch64::ZPRRegClass;
1240 RegClass = &AArch64::PPRRegClass;
1242 RegClass = &AArch64::PNRRegClass;
1244 RegClass = &AArch64::FPR128RegClass;
1245 AltName = AArch64::vreg;
1249 return printAsmRegInClass(MO, RegClass, AltName, O);
1256bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1258 const char *ExtraCode,
1260 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1263 const MachineOperand &MO =
MI->getOperand(OpNum);
1264 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1269void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1271 unsigned NOps =
MI->getNumOperands();
1273 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1275 OS <<
MI->getDebugVariable()->getName();
1278 assert(
MI->isIndirectDebugValue());
1290void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1291 ArrayRef<unsigned> JumpTableIndices) {
1293 if (JumpTableIndices.
empty())
1295 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1296 const auto &
F = MF->getFunction();
1299 MCSection *ReadOnlySec =
nullptr;
1300 if (TM.Options.EnableStaticDataPartitioning) {
1306 OutStreamer->switchSection(ReadOnlySec);
1308 auto AFI = MF->getInfo<AArch64FunctionInfo>();
1309 for (
unsigned JTI : JumpTableIndices) {
1310 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1313 if (JTBBs.empty())
continue;
1315 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1317 OutStreamer->emitLabel(GetJTISymbol(JTI));
1322 for (
auto *JTBB : JTBBs) {
1323 const MCExpr *
Value =
1342AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1343 const MachineInstr *BranchInstr,
1344 const MCSymbol *BranchLabel)
const {
1345 const auto AFI = MF->getInfo<AArch64FunctionInfo>();
1348 switch (AFI->getJumpTableEntrySize(JTI)) {
1350 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1353 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1356 EntrySize = codeview::JumpTableEntrySize::Int32;
1361 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1364void AArch64AsmPrinter::emitFunctionEntryLabel() {
1365 const Triple &
TT = TM.getTargetTriple();
1366 if (
TT.isOSBinFormatELF() &&
1367 (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall ||
1368 MF->getFunction().getCallingConv() ==
1369 CallingConv::AArch64_SVE_VectorCall ||
1370 MF->getInfo<AArch64FunctionInfo>()->isSVECC())) {
1372 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1378 if (
TT.isWindowsArm64EC() && !MF->getFunction().hasLocalLinkage()) {
1383 OutStreamer->emitAssignment(
1387 auto getSymbolFromMetadata = [&](StringRef
Name) {
1389 if (MDNode *Node = MF->getFunction().getMetadata(Name)) {
1391 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1397 MF->getFunction().getMetadata(
"arm64ec_unmangled_name", UnmangledNames);
1398 for (MDNode *Node : UnmangledNames) {
1400 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1401 if (std::optional<std::string> MangledName =
1404 MMI->getContext().getOrCreateSymbol(*MangledName);
1405 emitFunctionAlias(UnmangledSym, ECMangledSym);
1408 if (MCSymbol *ECMangledSym =
1409 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1410 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1414void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1415 const Constant *CV) {
1417 if (CPA->hasAddressDiscriminator() &&
1418 !CPA->hasSpecialAddressDiscriminator(
1421 "unexpected address discrimination value for ctors/dtors entry, only "
1422 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1431void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1432 const GlobalAlias &GA) {
1438 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1440 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1443 OutStreamer->beginCOFFSymbolDef(ExpSym);
1447 OutStreamer->endCOFFSymbolDef();
1449 OutStreamer->beginCOFFSymbolDef(Sym);
1453 OutStreamer->endCOFFSymbolDef();
1454 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1455 OutStreamer->emitAssignment(
1472void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1473 const llvm::MachineInstr &
MI) {
1474 Register DestReg =
MI.getOperand(0).getReg();
1475 Register ScratchReg =
MI.getOperand(1).getReg();
1478 Register TableReg =
MI.getOperand(2).getReg();
1479 Register EntryReg =
MI.getOperand(3).getReg();
1480 int JTIdx =
MI.getOperand(4).getIndex();
1486 MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1491 Label = MF->getContext().createTempSymbol();
1497 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1499 .addExpr(LabelExpr));
1504 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1505 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1506 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1511 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1512 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1516 .addImm(
Size == 1 ? 0 : 1));
1520 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1524 .addImm(
Size == 4 ? 0 : 2));
1527void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1528 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1529 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1531 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1532 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1548 MachineOperand JTOp =
MI.getOperand(0);
1552 "unsupported compressed jump table");
1554 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1558 uint64_t MaxTableEntry = NumTableEntries - 1;
1560 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1561 .addReg(AArch64::XZR)
1562 .addReg(AArch64::X16)
1563 .addImm(MaxTableEntry)
1566 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1571 if ((MaxTableEntry >>
Offset) == 0)
1573 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1576 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1577 .addReg(AArch64::XZR)
1578 .addReg(AArch64::X16)
1579 .addReg(AArch64::X17)
1585 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1586 .addReg(AArch64::X16)
1587 .addReg(AArch64::X16)
1588 .addReg(AArch64::XZR)
1592 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1593 MCOperand JTMCHi, JTMCLo;
1603 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1605 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1606 .addReg(AArch64::X17)
1607 .addReg(AArch64::X17)
1611 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1612 .addReg(AArch64::X16)
1613 .addReg(AArch64::X17)
1614 .addReg(AArch64::X16)
1618 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1625 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1627 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1628 .addReg(AArch64::X16)
1629 .addReg(AArch64::X17)
1630 .addReg(AArch64::X16)
1633 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1636void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1637 const llvm::MachineInstr &
MI) {
1638 unsigned Opcode =
MI.getOpcode();
1640 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1642 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1643 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1644 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1645 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1646 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1647 if (Opcode == AArch64::MOPSMemorySetPseudo)
1648 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1649 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1650 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1653 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1654 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1656 for (
auto Op :
Ops) {
1658 auto MCIB = MCInstBuilder(
Op);
1660 MCIB.addReg(
MI.getOperand(i++).getReg());
1661 MCIB.addReg(
MI.getOperand(i++).getReg());
1663 MCIB.addReg(
MI.getOperand(i++).getReg());
1665 MCIB.addReg(
MI.getOperand(i++).getReg());
1666 MCIB.addReg(
MI.getOperand(i++).getReg());
1667 MCIB.addReg(
MI.getOperand(i++).getReg());
1669 EmitToStreamer(OutStreamer, MCIB);
1673void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1674 const MachineInstr &
MI) {
1675 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1678 MCSymbol *MILabel = Ctx.createTempSymbol();
1682 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1685 const MachineBasicBlock &
MBB = *
MI.getParent();
1688 while (NumNOPBytes > 0) {
1689 if (MII ==
MBB.
end() || MII->isCall() ||
1690 MII->getOpcode() == AArch64::DBG_VALUE ||
1691 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1692 MII->getOpcode() == TargetOpcode::STACKMAP)
1699 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1700 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
1705void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1706 const MachineInstr &
MI) {
1708 MCSymbol *MILabel = Ctx.createTempSymbol();
1712 PatchPointOpers Opers(&
MI);
1714 int64_t CallTarget = Opers.getCallTarget().getImm();
1715 unsigned EncodedBytes = 0;
1717 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1718 "High 16 bits of call target should be zero.");
1719 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1722 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1723 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1724 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1725 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1728 unsigned NumBytes = Opers.getNumPatchBytes();
1729 assert(NumBytes >= EncodedBytes &&
1730 "Patchpoint can't request size less than the length of a call.");
1731 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1732 "Invalid number of NOP bytes requested!");
1733 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1734 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
1737void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1738 const MachineInstr &
MI) {
1739 StatepointOpers SOpers(&
MI);
1740 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1741 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1742 for (
unsigned i = 0; i < PatchBytes; i += 4)
1743 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
1746 const MachineOperand &CallTarget = SOpers.getCallTarget();
1747 MCOperand CallTargetMCOp;
1748 unsigned CallOpcode;
1749 switch (CallTarget.
getType()) {
1752 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1753 CallOpcode = AArch64::BL;
1757 CallOpcode = AArch64::BL;
1761 CallOpcode = AArch64::BLR;
1768 EmitToStreamer(OutStreamer,
1769 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1773 MCSymbol *MILabel = Ctx.createTempSymbol();
1778void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1787 unsigned OperandsBeginIdx = 4;
1790 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1797 MI.setOpcode(Opcode);
1802 for (
const MachineOperand &MO :
1805 lowerOperand(MO, Dest);
1806 MI.addOperand(Dest);
1814 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1816 .addReg(AArch64::XZR)
1821void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1822 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1823 EmitToStreamer(*OutStreamer,
1824 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1830void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1831 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1832 EmitToStreamer(*OutStreamer,
1833 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1840void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1841 Register DestReg =
MI.getOperand(0).getReg();
1842 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->
isNeonAvailable()) {
1843 if (STI->hasZeroCycleZeroingFPR64()) {
1846 if (AArch64::FPR16RegClass.
contains(DestReg))
1847 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1848 &AArch64::FPR64RegClass);
1849 else if (AArch64::FPR32RegClass.
contains(DestReg))
1850 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1851 &AArch64::FPR64RegClass);
1859 EmitToStreamer(*OutStreamer, MOVI);
1860 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1863 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1864 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1865 &AArch64::FPR128RegClass);
1866 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1867 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1868 &AArch64::FPR128RegClass);
1871 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1872 &AArch64::FPR128RegClass);
1879 EmitToStreamer(*OutStreamer, MOVI);
1881 emitFMov0AsFMov(
MI, DestReg);
1884 emitFMov0AsFMov(
MI, DestReg);
1888void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1891 switch (
MI.getOpcode()) {
1894 case AArch64::FMOVH0:
1895 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1896 if (!STI->hasFullFP16())
1897 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1901 case AArch64::FMOVS0:
1906 case AArch64::FMOVD0:
1912 EmitToStreamer(*OutStreamer, FMov);
1915Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc,
1918 bool MayUseAddrAsScratch) {
1919 assert(ScratchReg == AArch64::X16 || ScratchReg == AArch64::X17 ||
1922 if (AddrDisc == AArch64::NoRegister)
1923 AddrDisc = AArch64::XZR;
1931 if (AddrDisc == AArch64::XZR) {
1932 emitMOVZ(ScratchReg, Disc, 0);
1939 assert(MayUseAddrAsScratch || ScratchReg != AddrDisc);
1940 bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17 ||
1942 if (MayUseAddrAsScratch && AddrDiscIsSafe)
1943 ScratchReg = AddrDisc;
1945 emitMovXReg(ScratchReg, AddrDisc);
1947 emitMOVK(ScratchReg, Disc, 48);
1961void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
1993 if (Method == AuthCheckMethod::None)
1995 if (Method == AuthCheckMethod::DummyLoad) {
1996 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2000 assert(!OnFailure &&
"DummyLoad always traps on error");
2004 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2005 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2007 emitMovXReg(ScratchReg, TestedReg);
2009 if (Method == AuthCheckMethod::XPAC) {
2013 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2018 assert(TestedReg == AArch64::LR &&
2019 "XPACHint mode is only compatible with checking the LR register");
2021 "XPACHint mode is only compatible with I-keys");
2022 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2026 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2027 .addReg(AArch64::XZR)
2034 MCInstBuilder(AArch64::Bcc)
2037 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2039 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2046 MCInstBuilder(AArch64::TBZX)
2057 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2071 case AuthCheckMethod::XPACHint:
2074 case AuthCheckMethod::XPAC:
2076 emitMovXReg(TestedReg, ScratchReg);
2083 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2088 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2100void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2105 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2112 "Neither x16 nor x17 is available as a scratch register");
2115 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2119bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2125 EmitToStreamer(MCInstBuilder(AArch64::HINT).addImm(0));
2128 MCSymbol *Dot = OutContext.createTempSymbol();
2133 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2139void AArch64AsmPrinter::emitPtrauthAuthResign(
2141 const MachineOperand *AUTAddrDisc,
Register Scratch,
2142 std::optional<AArch64PACKey::ID> PACKey, uint64_t PACDisc,
2144 const bool IsAUTPAC = PACKey.has_value();
2158 bool ShouldCheck =
true;
2160 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
2165 ShouldCheck = ShouldTrap =
false;
2172 ShouldCheck = ShouldTrap =
false;
2179 ShouldCheck = ShouldTrap =
true;
2185 Register AUTDiscReg = emitPtrauthDiscriminator(
2186 AUTDisc, AUTAddrDisc->
getReg(), Scratch, AUTAddrDisc->
isKill());
2187 bool AUTZero = AUTDiscReg == AArch64::XZR;
2190 if (!emitDeactivationSymbolRelocation(DS)) {
2199 EmitToStreamer(*OutStreamer, AUTInst);
2203 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2209 if (IsAUTPAC && !ShouldTrap)
2210 EndSym = createTempSymbol(
"resign_end_");
2212 emitPtrauthCheckAuthenticatedValue(
2213 AUTVal, Scratch, AUTKey, AArch64PAuth::AuthCheckMethod::XPAC, EndSym);
2225 emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
2226 bool PACZero = PACDiscReg == AArch64::XZR;
2237 EmitToStreamer(*OutStreamer, PACInst);
2244void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2247 uint64_t Disc =
MI->getOperand(3).getImm();
2248 Register AddrDisc =
MI->getOperand(4).getReg();
2249 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2253 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2254 assert(ScratchReg != AddrDisc &&
2255 "Neither X16 nor X17 is available as a scratch register");
2259 Register DiscReg = emitPtrauthDiscriminator(
2260 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2261 bool IsZeroDisc = DiscReg == AArch64::XZR;
2264 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2275 EmitToStreamer(*OutStreamer, PACInst);
2278void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2279 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2280 unsigned BrTarget =
MI->getOperand(0).getReg();
2284 "Invalid auth call key");
2286 uint64_t Disc =
MI->getOperand(2).getImm();
2289 unsigned AddrDisc =
MI->getOperand(3).getReg();
2295 if (BrTarget == AddrDisc)
2312 bool AddrDiscIsImplicitDef =
2313 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2314 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2315 AddrDiscIsImplicitDef);
2316 bool IsZeroDisc = DiscReg == AArch64::XZR;
2321 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
2323 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
2326 Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
2328 Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
2336 EmitToStreamer(*OutStreamer, BRInst);
2340 const MCExpr *Expr,
bool DSOLocal,
2402 if (!TT.isOSBinFormatELF())
2463const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2465 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2466 const Triple &
TT = TM.getTargetTriple();
2478 std::unique_ptr<MCSubtargetInfo> STI(
2479 TM.getTarget().createMCSubtargetInfo(TT,
"",
""));
2480 assert(STI &&
"Unable to create subtarget info");
2481 this->STI =
static_cast<const AArch64Subtarget *
>(&*STI);
2489 0,
"",
true, PAuthIFuncNextUniqueID++,
nullptr));
2496 .addReg(AArch64::X0)
2501 emitAddress(*OutStreamer, AArch64::X0, Target, IsDSOLocal, *STI);
2503 if (HasAddressDiversity) {
2509 emitAddress(*OutStreamer, AArch64::X1, PlacePlusDisc,
true,
2512 emitMOVZ(AArch64::X1, Disc, 0);
2519 auto *PrePACInstExpr =
2531 const MCSymbolRefExpr *EmuPACRef =
2533 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2540 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2548AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2549 MCContext &Ctx = OutContext;
2554 getDataLayout(),
Offset,
true);
2572 const MCExpr *DSExpr =
nullptr;
2584 "' out of range [0, " +
2592 "' out of range [0, 0xFFFF]");
2597 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2599 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2604 "expressions on this target");
2611void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2612 unsigned DstReg =
MI.getOperand(0).getReg();
2613 const MachineOperand &GAOp =
MI.getOperand(1);
2614 const uint64_t KeyC =
MI.getOperand(2).getImm();
2616 "key is out of range [0, AArch64PACKey::LAST]");
2618 const uint64_t Disc =
MI.getOperand(3).getImm();
2620 "constant discriminator is out of range [0, 0xffff]");
2629 if (TM.getTargetTriple().isOSBinFormatELF()) {
2631 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2634 "non-zero offset for $auth_ptr$ stub slots is not supported");
2636 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2638 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2639 "LOADauthptrstatic is implemented only for MachO/ELF");
2641 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2642 getObjFileLowering());
2645 "non-zero offset for $auth_ptr$ stub slots is not supported");
2647 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2650 MachineOperand StubMOHi =
2654 MCOperand StubMCHi, StubMCLo;
2661 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2663 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2669void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2670 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2671 const bool IsELFSignedGOT =
MI.getParent()
2673 ->getInfo<AArch64FunctionInfo>()
2674 ->hasELFSignedGOT();
2675 MachineOperand GAOp =
MI.getOperand(0);
2676 const uint64_t KeyC =
MI.getOperand(1).getImm();
2678 "key is out of range [0, AArch64PACKey::LAST]");
2680 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2681 const uint64_t Disc =
MI.getOperand(3).getImm();
2683 "constant discriminator is out of range [0, 0xffff]");
2730 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2731 MCOperand GAMCHi, GAMCLo;
2744 MCInstBuilder(AArch64::ADRP)
2745 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2749 if (IsELFSignedGOT) {
2750 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2751 .addReg(AArch64::X17)
2752 .addReg(AArch64::X17)
2756 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2757 .addReg(AArch64::X16)
2758 .addReg(AArch64::X17)
2767 EmitToStreamer(MCInstBuilder(AuthOpcode)
2768 .addReg(AArch64::X16)
2769 .addReg(AArch64::X16)
2770 .addReg(AArch64::X17));
2772 if (!STI->hasFPAC()) {
2776 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2777 AArch64PAuth::AuthCheckMethod::XPAC);
2780 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2781 .addReg(AArch64::X16)
2782 .addReg(AArch64::X16)
2786 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2787 .addReg(AArch64::X16)
2788 .addReg(AArch64::X16)
2795 const bool IsNeg =
Offset < 0;
2797 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2800 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2801 .addReg(AArch64::X16)
2802 .addReg(AArch64::X16)
2803 .addImm((AbsOffset >> BitPos) & 0xfff)
2807 const uint64_t UOffset =
Offset;
2808 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2809 .addReg(AArch64::X17)
2810 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
2812 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
2813 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2814 uint64_t Shifted = UOffset >> BitPos;
2816 return Shifted != 0;
2817 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2818 if (((Shifted >>
I) & 0xffff) != 0xffff)
2822 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2823 emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
2825 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2826 .addReg(AArch64::X16)
2827 .addReg(AArch64::X16)
2828 .addReg(AArch64::X17)
2833 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2836 .addReg(AArch64::X16)
2837 .addReg(AArch64::X16);
2838 if (DiscReg != AArch64::XZR)
2839 MIB.addReg(DiscReg);
2840 EmitToStreamer(MIB);
2843void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2845 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2846 const MachineOperand &GAMO =
MI.getOperand(1);
2853 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2854 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2855 .addReg(AuthResultReg)
2856 .addReg(AArch64::X17)
2859 MachineOperand GAHiOp(GAMO);
2860 MachineOperand GALoOp(GAMO);
2864 MCOperand GAMCHi, GAMCLo;
2869 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2871 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2872 .addReg(AArch64::X17)
2873 .addReg(AArch64::X17)
2877 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2878 .addReg(AuthResultReg)
2879 .addReg(AArch64::X17)
2886 UndefWeakSym = createTempSymbol(
"undef_weak");
2888 MCInstBuilder(AArch64::CBZX)
2889 .addReg(AuthResultReg)
2897 EmitToStreamer(MCInstBuilder(AuthOpcode)
2898 .addReg(AuthResultReg)
2899 .addReg(AuthResultReg)
2900 .addReg(AArch64::X17));
2905 if (!STI->hasFPAC()) {
2909 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2910 AArch64PAuth::AuthCheckMethod::XPAC);
2912 emitMovXReg(DstReg, AuthResultReg);
2917AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2921 if (std::optional<uint16_t> BADisc =
2929void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
2933 switch (
MI->getOpcode()) {
2936 case AArch64::CBBAssertExt:
2940 case AArch64::CBHAssertExt:
2944 case AArch64::CBWPrr:
2947 case AArch64::CBXPrr:
2950 case AArch64::CBWPri:
2954 case AArch64::CBXPri:
2962 bool NeedsRegSwap =
false;
2963 bool NeedsImmDec =
false;
2964 bool NeedsImmInc =
false;
2966#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
2968 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
2970 ? AArch64::CBB##RegCond##Wrr \
2971 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
2972 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
2973 : AArch64::CB##RegCond##Xrr))))
2989 NeedsImmDec = IsImm;
2993 NeedsRegSwap = !IsImm;
3000 NeedsRegSwap = !IsImm;
3001 NeedsImmInc = IsImm;
3005 NeedsImmDec = IsImm;
3009 NeedsRegSwap = !IsImm;
3016 NeedsRegSwap = !IsImm;
3017 NeedsImmInc = IsImm;
3025 MCOperand Lhs, Rhs, Trgt;
3026 lowerOperand(
MI->getOperand(1), Lhs);
3027 lowerOperand(
MI->getOperand(2), Rhs);
3028 lowerOperand(
MI->getOperand(3), Trgt);
3032 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3033 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3036 }
else if (NeedsImmDec) {
3040 }
else if (NeedsImmInc) {
3050 "CB immediate operand out-of-bounds");
3053 EmitToStreamer(*OutStreamer, Inst);
3058#include "AArch64GenMCPseudoLowering.inc"
3060void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3067void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3068 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
3078 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3079 EmitToStreamer(*OutStreamer, OutInst);
3083 if (
MI->getOpcode() == AArch64::ADRP) {
3084 for (
auto &Opd :
MI->operands()) {
3085 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3086 "swift_async_extendedFramePointerFlags") {
3087 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3094 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3096 LOHInstToLabel[
MI] = LOHLabel;
3100 AArch64TargetStreamer *TS =
3103 switch (
MI->getOpcode()) {
3106 "Unhandled tail call instruction");
3108 case AArch64::HINT: {
3113 if (CurrentPatchableFunctionEntrySym &&
3114 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3115 MI == &MF->front().front()) {
3116 int64_t
Imm =
MI->getOperand(0).getImm();
3117 if ((Imm & 32) && (Imm & 6)) {
3119 MCInstLowering.
Lower(
MI, Inst);
3120 EmitToStreamer(*OutStreamer, Inst);
3121 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3122 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3128 case AArch64::MOVMCSym: {
3129 Register DestReg =
MI->getOperand(0).getReg();
3130 const MachineOperand &MO_Sym =
MI->getOperand(1);
3131 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3132 MCOperand Hi_MCSym, Lo_MCSym;
3145 EmitToStreamer(*OutStreamer, MovZ);
3153 EmitToStreamer(*OutStreamer, MovK);
3156 case AArch64::MOVIv2d_ns:
3164 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3165 MI->getOperand(1).getImm() == 0) {
3167 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3170 EmitToStreamer(*OutStreamer, TmpInst);
3175 case AArch64::DBG_VALUE:
3176 case AArch64::DBG_VALUE_LIST:
3178 SmallString<128> TmpStr;
3179 raw_svector_ostream OS(TmpStr);
3180 PrintDebugValueComment(
MI, OS);
3185 case AArch64::EMITBKEY: {
3187 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3188 ExceptionHandlingType != ExceptionHandling::ARM)
3191 if (getFunctionCFISectionType(*MF) == CFISection::None)
3198 case AArch64::EMITMTETAGGED: {
3200 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3201 ExceptionHandlingType != ExceptionHandling::ARM)
3204 if (getFunctionCFISectionType(*MF) != CFISection::None)
3209 case AArch64::AUTx16x17:
3210 emitPtrauthAuthResign(
3212 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3213 std::nullopt, 0, 0,
MI->getDeactivationSymbol());
3216 case AArch64::AUTxMxN:
3217 emitPtrauthAuthResign(
MI->getOperand(0).getReg(),
3219 MI->getOperand(4).getImm(), &
MI->getOperand(5),
3220 MI->getOperand(1).getReg(), std::nullopt, 0, 0,
3221 MI->getDeactivationSymbol());
3224 case AArch64::AUTPAC:
3225 emitPtrauthAuthResign(
3227 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3229 MI->getOperand(4).getImm(),
MI->getOperand(5).getReg(),
3230 MI->getDeactivationSymbol());
3234 emitPtrauthSign(
MI);
3237 case AArch64::LOADauthptrstatic:
3238 LowerLOADauthptrstatic(*
MI);
3241 case AArch64::LOADgotPAC:
3242 case AArch64::MOVaddrPAC:
3243 LowerMOVaddrPAC(*
MI);
3246 case AArch64::LOADgotAUTH:
3247 LowerLOADgotAUTH(*
MI);
3252 emitPtrauthBranch(
MI);
3258 case AArch64::AUTH_TCRETURN:
3259 case AArch64::AUTH_TCRETURN_BTI: {
3261 const uint64_t
Key =
MI->getOperand(2).getImm();
3263 "Invalid auth key for tail-call return");
3265 const uint64_t Disc =
MI->getOperand(3).getImm();
3268 Register AddrDisc =
MI->getOperand(4).getReg();
3270 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3272 emitPtrauthTailCallHardening(
MI);
3275 if (Callee == AddrDisc)
3282 bool AddrDiscIsImplicitDef =
3283 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3284 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3285 AddrDiscIsImplicitDef);
3287 const bool IsZero = DiscReg == AArch64::XZR;
3288 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
3289 {AArch64::BRAB, AArch64::BRABZ}};
3296 EmitToStreamer(*OutStreamer, TmpInst);
3300 case AArch64::TCRETURNri:
3301 case AArch64::TCRETURNrix16x17:
3302 case AArch64::TCRETURNrix17:
3303 case AArch64::TCRETURNrinotx16:
3304 case AArch64::TCRETURNriALL: {
3305 emitPtrauthTailCallHardening(
MI);
3307 recordIfImportCall(
MI);
3311 EmitToStreamer(*OutStreamer, TmpInst);
3314 case AArch64::TCRETURNdi: {
3315 emitPtrauthTailCallHardening(
MI);
3319 recordIfImportCall(
MI);
3323 EmitToStreamer(*OutStreamer, TmpInst);
3326 case AArch64::SpeculationBarrierISBDSBEndBB: {
3331 EmitToStreamer(*OutStreamer, TmpInstDSB);
3335 EmitToStreamer(*OutStreamer, TmpInstISB);
3338 case AArch64::SpeculationBarrierSBEndBB: {
3342 EmitToStreamer(*OutStreamer, TmpInstSB);
3345 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3352 const MachineOperand &MO_Sym =
MI->getOperand(0);
3353 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3354 MCOperand SymTLSDescLo12, SymTLSDesc;
3357 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3364 EmitToStreamer(*OutStreamer, Adrp);
3372 EmitToStreamer(*OutStreamer, Ldr);
3375 Add.setOpcode(AArch64::ADDXri);
3378 Add.addOperand(SymTLSDescLo12);
3380 EmitToStreamer(*OutStreamer,
Add);
3389 EmitToStreamer(*OutStreamer, Blraa);
3393 case AArch64::TLSDESC_CALLSEQ: {
3401 const MachineOperand &MO_Sym =
MI->getOperand(0);
3402 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3403 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3407 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3414 EmitToStreamer(*OutStreamer, Adrp);
3427 EmitToStreamer(*OutStreamer, Ldr);
3431 Add.setOpcode(AArch64::ADDWri);
3435 Add.setOpcode(AArch64::ADDXri);
3439 Add.addOperand(SymTLSDescLo12);
3441 EmitToStreamer(*OutStreamer,
Add);
3446 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3448 EmitToStreamer(*OutStreamer, TLSDescCall);
3456 EmitToStreamer(*OutStreamer, Blr);
3461 case AArch64::JumpTableDest32:
3462 case AArch64::JumpTableDest16:
3463 case AArch64::JumpTableDest8:
3464 LowerJumpTableDest(*OutStreamer, *
MI);
3467 case AArch64::BR_JumpTable:
3468 LowerHardenedBRJumpTable(*
MI);
3471 case AArch64::FMOVH0:
3472 case AArch64::FMOVS0:
3473 case AArch64::FMOVD0:
3477 case AArch64::MOPSMemoryCopyPseudo:
3478 case AArch64::MOPSMemoryMovePseudo:
3479 case AArch64::MOPSMemorySetPseudo:
3480 case AArch64::MOPSMemorySetTaggingPseudo:
3481 LowerMOPS(*OutStreamer, *
MI);
3484 case TargetOpcode::STACKMAP:
3485 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3487 case TargetOpcode::PATCHPOINT:
3488 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3490 case TargetOpcode::STATEPOINT:
3491 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3493 case TargetOpcode::FAULTING_OP:
3494 return LowerFAULTING_OP(*
MI);
3496 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3497 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3500 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3501 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3504 case TargetOpcode::PATCHABLE_TAIL_CALL:
3505 LowerPATCHABLE_TAIL_CALL(*
MI);
3507 case TargetOpcode::PATCHABLE_EVENT_CALL:
3508 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3509 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3510 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3512 case AArch64::KCFI_CHECK:
3513 LowerKCFI_CHECK(*
MI);
3516 case AArch64::HWASAN_CHECK_MEMACCESS:
3517 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3518 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3519 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3520 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3523 case AArch64::SEH_StackAlloc:
3527 case AArch64::SEH_SaveFPLR:
3531 case AArch64::SEH_SaveFPLR_X:
3532 assert(
MI->getOperand(0).getImm() < 0 &&
3533 "Pre increment SEH opcode must have a negative offset");
3537 case AArch64::SEH_SaveReg:
3539 MI->getOperand(1).getImm());
3542 case AArch64::SEH_SaveReg_X:
3543 assert(
MI->getOperand(1).getImm() < 0 &&
3544 "Pre increment SEH opcode must have a negative offset");
3546 -
MI->getOperand(1).getImm());
3549 case AArch64::SEH_SaveRegP:
3550 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3551 MI->getOperand(0).getImm() <= 28) {
3552 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3553 "Register paired with LR must be odd");
3555 MI->getOperand(2).getImm());
3558 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3559 "Non-consecutive registers not allowed for save_regp");
3561 MI->getOperand(2).getImm());
3564 case AArch64::SEH_SaveRegP_X:
3565 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3566 "Non-consecutive registers not allowed for save_regp_x");
3567 assert(
MI->getOperand(2).getImm() < 0 &&
3568 "Pre increment SEH opcode must have a negative offset");
3570 -
MI->getOperand(2).getImm());
3573 case AArch64::SEH_SaveFReg:
3575 MI->getOperand(1).getImm());
3578 case AArch64::SEH_SaveFReg_X:
3579 assert(
MI->getOperand(1).getImm() < 0 &&
3580 "Pre increment SEH opcode must have a negative offset");
3582 -
MI->getOperand(1).getImm());
3585 case AArch64::SEH_SaveFRegP:
3586 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3587 "Non-consecutive registers not allowed for save_regp");
3589 MI->getOperand(2).getImm());
3592 case AArch64::SEH_SaveFRegP_X:
3593 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3594 "Non-consecutive registers not allowed for save_regp_x");
3595 assert(
MI->getOperand(2).getImm() < 0 &&
3596 "Pre increment SEH opcode must have a negative offset");
3598 -
MI->getOperand(2).getImm());
3601 case AArch64::SEH_SetFP:
3605 case AArch64::SEH_AddFP:
3609 case AArch64::SEH_Nop:
3613 case AArch64::SEH_PrologEnd:
3617 case AArch64::SEH_EpilogStart:
3621 case AArch64::SEH_EpilogEnd:
3625 case AArch64::SEH_PACSignLR:
3629 case AArch64::SEH_SaveAnyRegI:
3630 assert(
MI->getOperand(1).getImm() <= 1008 &&
3631 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3633 MI->getOperand(1).getImm());
3636 case AArch64::SEH_SaveAnyRegIP:
3637 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3638 "Non-consecutive registers not allowed for save_any_reg");
3639 assert(
MI->getOperand(2).getImm() <= 1008 &&
3640 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3642 MI->getOperand(2).getImm());
3645 case AArch64::SEH_SaveAnyRegQP:
3646 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3647 "Non-consecutive registers not allowed for save_any_reg");
3648 assert(
MI->getOperand(2).getImm() >= 0 &&
3649 "SaveAnyRegQP SEH opcode offset must be non-negative");
3650 assert(
MI->getOperand(2).getImm() <= 1008 &&
3651 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3653 MI->getOperand(2).getImm());
3656 case AArch64::SEH_SaveAnyRegQPX:
3657 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3658 "Non-consecutive registers not allowed for save_any_reg");
3659 assert(
MI->getOperand(2).getImm() < 0 &&
3660 "SaveAnyRegQPX SEH opcode offset must be negative");
3661 assert(
MI->getOperand(2).getImm() >= -1008 &&
3662 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3664 -
MI->getOperand(2).getImm());
3667 case AArch64::SEH_AllocZ:
3668 assert(
MI->getOperand(0).getImm() >= 0 &&
3669 "AllocZ SEH opcode offset must be non-negative");
3670 assert(
MI->getOperand(0).getImm() <= 255 &&
3671 "AllocZ SEH opcode offset must fit into 8 bits");
3675 case AArch64::SEH_SaveZReg:
3676 assert(
MI->getOperand(1).getImm() >= 0 &&
3677 "SaveZReg SEH opcode offset must be non-negative");
3678 assert(
MI->getOperand(1).getImm() <= 255 &&
3679 "SaveZReg SEH opcode offset must fit into 8 bits");
3681 MI->getOperand(1).getImm());
3684 case AArch64::SEH_SavePReg:
3685 assert(
MI->getOperand(1).getImm() >= 0 &&
3686 "SavePReg SEH opcode offset must be non-negative");
3687 assert(
MI->getOperand(1).getImm() <= 255 &&
3688 "SavePReg SEH opcode offset must fit into 8 bits");
3690 MI->getOperand(1).getImm());
3695 recordIfImportCall(
MI);
3697 MCInstLowering.
Lower(
MI, TmpInst);
3698 EmitToStreamer(*OutStreamer, TmpInst);
3701 case AArch64::CBWPri:
3702 case AArch64::CBXPri:
3703 case AArch64::CBBAssertExt:
3704 case AArch64::CBHAssertExt:
3705 case AArch64::CBWPrr:
3706 case AArch64::CBXPrr:
3707 emitCBPseudoExpansion(
MI);
3711 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3716 MCInstLowering.
Lower(
MI, TmpInst);
3717 EmitToStreamer(*OutStreamer, TmpInst);
3720void AArch64AsmPrinter::recordIfImportCall(
3721 const llvm::MachineInstr *BranchInst) {
3722 if (!EnableImportCallOptimization)
3726 if (GV && GV->hasDLLImportStorageClass()) {
3727 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3732 .push_back({CallSiteSymbol, CalledSymbol});
3736void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3737 MCSymbol *LazyPointer) {
3754 EmitToStreamer(Adrp);
3762 MCOperand SymPageOff;
3769 EmitToStreamer(Ldr);
3772 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3773 .addReg(AArch64::X16)
3774 .addReg(AArch64::X16)
3777 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3779 .addReg(AArch64::X16));
3782void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3783 const GlobalIFunc &GI,
3784 MCSymbol *LazyPointer) {
3816 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3817 .addReg(AArch64::SP)
3818 .addReg(AArch64::FP)
3819 .addReg(AArch64::LR)
3820 .addReg(AArch64::SP)
3823 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3824 .addReg(AArch64::FP)
3825 .addReg(AArch64::SP)
3829 for (
int I = 0;
I != 4; ++
I)
3830 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3831 .addReg(AArch64::SP)
3832 .addReg(AArch64::X1 + 2 *
I)
3833 .addReg(AArch64::X0 + 2 *
I)
3834 .addReg(AArch64::SP)
3837 for (
int I = 0;
I != 4; ++
I)
3838 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3839 .addReg(AArch64::SP)
3840 .addReg(AArch64::D1 + 2 *
I)
3841 .addReg(AArch64::D0 + 2 *
I)
3842 .addReg(AArch64::SP)
3846 MCInstBuilder(AArch64::BL)
3859 EmitToStreamer(Adrp);
3867 MCOperand SymPageOff;
3874 EmitToStreamer(Ldr);
3877 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3878 .addReg(AArch64::X0)
3879 .addReg(AArch64::X16)
3882 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3883 .addReg(AArch64::X16)
3884 .addReg(AArch64::X0)
3888 for (
int I = 3;
I != -1; --
I)
3889 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3890 .addReg(AArch64::SP)
3891 .addReg(AArch64::D1 + 2 *
I)
3892 .addReg(AArch64::D0 + 2 *
I)
3893 .addReg(AArch64::SP)
3896 for (
int I = 3;
I != -1; --
I)
3897 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3898 .addReg(AArch64::SP)
3899 .addReg(AArch64::X1 + 2 *
I)
3900 .addReg(AArch64::X0 + 2 *
I)
3901 .addReg(AArch64::SP)
3904 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3905 .addReg(AArch64::SP)
3906 .addReg(AArch64::FP)
3907 .addReg(AArch64::LR)
3908 .addReg(AArch64::SP)
3911 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3913 .addReg(AArch64::X16));
3916const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
3917 const Constant *BaseCV,
3927char AArch64AsmPrinter::ID = 0;
3930 "AArch64 Assembly Printer",
false,
false)
3934LLVMInitializeAArch64AsmPrinter() {
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))
#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond)
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
static void emitAddress(MCStreamer &Streamer, MCRegister Reg, const MCExpr *Expr, bool DSOLocal, const MCSubtargetInfo &STI)
static bool targetSupportsPAuthRelocation(const Triple &TT, const MCExpr *Target, const MCExpr *DSExpr)
static bool targetSupportsIRelativeRelocation(const Triple &TT)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_EXTERNAL_VISIBILITY
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
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 TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton 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, SMLoc Loc=SMLoc())
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
const SetOfInstructions & getLOHRelated() const
unsigned getJumpTableEntrySize(int Idx) const
MCSymbol * getJumpTableEntryPCRelSymbol(int Idx) const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
std::optional< std::string > getOutliningStyle() const
const MILOHContainer & getLOHContainer() const
void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym)
bool shouldSignWithBKey() 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.
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MCSymbol * GetGlobalValueSymbol(const GlobalValue *GV, unsigned TargetFlags) const
void Lower(const MachineInstr *MI, MCInst &OutMI) const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
const AArch64RegisterInfo * getRegisterInfo() const override
bool isNeonAvailable() const
Returns true if the target has NEON and the function at runtime is known to have NEON enabled (e....
const AArch64InstrInfo * getInstrInfo() const override
bool isTargetILP32() const
std::optional< uint16_t > getPtrAuthBlockAddressDiscriminatorIfEnabled(const Function &ParentFn) const
Compute the integer discriminator for a given BlockAddress constant, if blockaddress signing is enabl...
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
AArch64PAuth::AuthCheckMethod getAuthenticatedLRCheckMethod(const MachineFunction &MF) const
Choose a method of checking LR before performing a tail call.
virtual void emitARM64WinCFISaveRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset)
virtual void emitAttributesSubsection(StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, AArch64BuildAttributes::SubsectionType ParameterType)
Build attributes implementation.
virtual void emitARM64WinCFISavePReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPACSignLR()
virtual void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset)
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 emitARM64WinCFIAllocZ(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 emitARM64WinCFISaveZReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPrologEnd()
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFINop()
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
virtual void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, std::string String)
virtual void emitARM64WinCFIEpilogStart()
virtual void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset)
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
bool empty() const
empty - Check if the array is empty.
This class is intended to be used as a driving class for all asm writers.
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 const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
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 emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
virtual const MCExpr * lowerBlockAddressConstant(const BlockAddress &BA)
Lower the specified BlockAddress to an MCExpr.
The address of a basic block.
Function * getFunction() const
Conditional or Unconditional Branch instruction.
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.
@ AddrDiscriminator_CtorsDtors
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
ConstantInt * getKey() const
The Key ID, an i32 constant.
Constant * getDeactivationSymbol() const
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.
A parsed version of the target data layout string in and methods for querying it.
void recordFaultingOp(FaultKind FaultTy, const MCSymbol *FaultingLabel, const MCSymbol *HandlerLabel)
void serializeToFaultMapSection()
const Constant * getAliasee() const
const Constant * getResolver() const
bool hasLocalLinkage() const
bool hasExternalWeakLinkage() const
Type * getValueType() const
LLVM_ABI 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, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
LLVM_ABI MCSymbol * createLinkerPrivateSymbol(const Twine &Name)
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate 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.
Wrapper class representing physical registers. Should be passed by value.
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
virtual void emitCFIBKeyFrame()
virtual void beginCOFFSymbolDef(const MCSymbol *Symbol)
Start emitting COFF symbol definition.
virtual bool popSection()
Restore the current and previous section from the section stack.
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 void emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc={})
Record a relocation described by the .reloc directive.
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 pushSection()
Save the current and previous section on the section stack.
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
MCSection * getCurrentSectionOnly() const
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.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
const MCSymbol * getAddSym() const
int64_t getConstant() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
CalledGlobalInfo tryGetCalledGlobal(const MachineInstr *MI) const
Tries to get the global and target flags for a call site, if the instruction is a call to a global.
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.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
ExprStubListTy getAuthGVStubList()
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.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static SectionKind getMetadata()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void push_back(const T &Elt)
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
StringRef - Represent a constant reference to a string, i.e.
constexpr 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.
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.
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.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
StringRef getVendorName(unsigned const Vendor)
@ 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 ==...
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
SymbolStorageClass
Storage class tells where and what the symbol represents.
@ IMAGE_SYM_CLASS_EXTERNAL
External symbol.
@ IMAGE_SYM_CLASS_STATIC
Static.
@ 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))
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ GNU_PROPERTY_AARCH64_FEATURE_1_BTI
@ GNU_PROPERTY_AARCH64_FEATURE_1_PAC
@ GNU_PROPERTY_AARCH64_FEATURE_1_GCS
@ S_REGULAR
S_REGULAR - Regular section.
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)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
FunctionAddr VTableAddr Value
LLVM_ABI std::optional< std::string > getArm64ECMangledFunctionName(StringRef Name)
Returns the ARM64EC mangled function name unless the input is already mangled.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
std::string utostr(uint64_t X, bool isNeg=false)
Target & getTheAArch64leTarget()
auto dyn_cast_or_null(const Y &Val)
Target & getTheAArch64_32Target()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Target & getTheARM64_32Target()
static MCRegister getXRegFromWReg(MCRegister Reg)
Target & getTheARM64Target()
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
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)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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_WeakAntiDep
.weak_anti_dep (COFF)
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...