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);
168 return Reg == AArch64::X16 ||
Reg == AArch64::X17;
176 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
180 const MCSymbol *OnFailure =
nullptr);
183 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
190 std::optional<AArch64PACKey::ID> PACKey,
196 bool emitDeactivationSymbolRelocation(
Value *DS);
223 bool MayClobberAddrDisc =
false);
241 const MCExpr *emitPAuthRelocationAsIRelative(
243 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
250 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
257 void EmitToStreamer(
const MCInst &Inst) {
258 EmitToStreamer(*OutStreamer, Inst);
263 void emitFunctionHeaderComment()
override;
271 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
272 PSI = &PSIW->getPSI();
274 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
275 SDPI = &SDPIW->getStaticDataProfileInfo();
280 SetupMachineFunction(MF);
282 if (STI->isTargetCOFF()) {
318 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
323 void emitFunctionBodyEnd()
override;
326 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
327 void emitEndOfAsmFile(
Module &M)
override;
347 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
349 MInstToMCSymbol LOHInstToLabel;
351 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
352 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
372void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
373 const Triple &
TT = TM.getTargetTriple();
375 if (
TT.isOSBinFormatCOFF()) {
376 emitCOFFFeatureSymbol(M);
377 emitCOFFReplaceableFunctionData(M);
379 if (
M.getModuleFlag(
"import-call-optimization"))
380 EnableImportCallOptimization =
true;
383 if (!
TT.isOSBinFormatELF())
388 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
391 unsigned BAFlags = 0;
392 unsigned GNUFlags = 0;
394 M.getModuleFlag(
"branch-target-enforcement"))) {
395 if (!BTE->isZero()) {
396 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
402 M.getModuleFlag(
"guarded-control-stack"))) {
403 if (!GCS->isZero()) {
404 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
410 M.getModuleFlag(
"sign-return-address"))) {
411 if (!Sign->isZero()) {
412 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
417 uint64_t PAuthABIPlatform = -1;
419 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
420 PAuthABIPlatform = PAP->getZExtValue();
423 uint64_t PAuthABIVersion = -1;
425 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
426 PAuthABIVersion = PAV->getZExtValue();
430 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
432 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
435void AArch64AsmPrinter::emitFunctionHeaderComment() {
436 const AArch64FunctionInfo *FI = MF->getInfo<AArch64FunctionInfo>();
438 if (OutlinerString != std::nullopt)
439 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
442void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
445 if (
F.hasFnAttribute(
"patchable-function-entry")) {
447 if (
F.getFnAttribute(
"patchable-function-entry")
449 .getAsInteger(10, Num))
455 emitSled(
MI, SledKind::FUNCTION_ENTER);
458void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
459 emitSled(
MI, SledKind::FUNCTION_EXIT);
462void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
463 emitSled(
MI, SledKind::TAIL_CALL);
466void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
467 static const int8_t NoopsInSledCount = 7;
488 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
489 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
490 OutStreamer->emitLabel(CurSled);
491 auto Target = OutContext.createTempSymbol();
496 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
498 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
499 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
501 OutStreamer->emitLabel(Target);
502 recordSled(CurSled,
MI, Kind, 2);
505void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
506 uint64_t PAuthABIPlatform,
507 uint64_t PAuthABIVersion,
508 AArch64TargetStreamer *TS) {
510 PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
511 PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
513 if (PAuthABIPlatform || PAuthABIVersion) {
517 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
518 AArch64BuildAttributes::SubsectionType::ULEB128);
522 PAuthABIPlatform,
"");
536 if (BTIValue || PACValue || GCSValue) {
540 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
541 AArch64BuildAttributes::SubsectionType::ULEB128);
569void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
571 auto &
O = *OutStreamer;
572 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
573 O.emitLabel(CurSled);
574 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
576 OutContext.getOrCreateSymbol(
577 Twine(MachO ?
"_" :
"") +
578 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
581 O.AddComment(
"Begin XRay typed event");
582 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
583 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
589 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
593 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
594 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
595 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
596 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
597 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
601 O.AddComment(
"End XRay typed event");
602 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
609 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
611 O.AddComment(
"Begin XRay custom event");
612 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
613 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
619 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
620 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
621 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
622 O.AddComment(
"End XRay custom event");
623 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
630 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
634void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
636 assert(std::next(
MI.getIterator())->isCall() &&
637 "KCFI_CHECK not followed by a call instruction");
638 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
639 "KCFI_CHECK call target doesn't match call operand");
643 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
644 if (AddrReg == AArch64::XZR) {
648 emitMovXReg(AddrReg, AArch64::XZR);
654 for (
auto &
Reg : ScratchRegs) {
660 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
661 "Invalid scratch registers for KCFI_CHECK");
665 int64_t PrefixNops = 0;
668 .getFnAttribute(
"patchable-function-prefix")
670 .getAsInteger(10, PrefixNops);
673 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
674 .addReg(ScratchRegs[0])
676 .addImm(-(PrefixNops * 4 + 4)));
680 const int64_t
Type =
MI.getOperand(1).getImm();
681 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
682 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
685 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
686 .addReg(AArch64::WZR)
687 .addReg(ScratchRegs[0])
688 .addReg(ScratchRegs[1])
692 EmitToStreamer(*OutStreamer,
693 MCInstBuilder(AArch64::Bcc)
702 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
706 AddrIndex = AddrReg - AArch64::X0;
716 assert(AddrIndex < 31 && TypeIndex < 31);
718 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
719 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
720 OutStreamer->emitLabel(
Pass);
723void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
731 if (
Reg == AArch64::XZR)
735 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
737 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
738 uint32_t AccessInfo =
MI.getOperand(1).getImm();
740 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
742 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
743 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
745 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
746 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
749 if (!TM.getTargetTriple().isOSBinFormatELF())
752 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
755 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
757 SymName +=
"_short_v2";
758 Sym = OutContext.getOrCreateSymbol(SymName);
761 EmitToStreamer(*OutStreamer,
762 MCInstBuilder(AArch64::BL)
766void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
767 if (HwasanMemaccessSymbols.empty())
770 const Triple &
TT = TM.getTargetTriple();
772 AArch64Subtarget STI(TT, TM.getTargetCPU(), TM.getTargetCPU(),
773 TM.getTargetFeatureString(), TM,
true);
777 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
779 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
781 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
783 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
786 for (
auto &
P : HwasanMemaccessSymbols) {
787 unsigned Reg = std::get<0>(
P.first);
788 bool IsShort = std::get<1>(
P.first);
789 uint32_t AccessInfo = std::get<2>(
P.first);
790 bool IsFixedShadow = std::get<3>(
P.first);
791 uint64_t FixedShadowOffset = std::get<4>(
P.first);
792 const MCSymbolRefExpr *HwasanTagMismatchRef =
793 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
796 bool HasMatchAllTag =
798 uint8_t MatchAllTag =
805 OutStreamer->switchSection(OutContext.getELFSection(
811 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
812 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
813 OutStreamer->emitLabel(Sym);
815 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
816 .addReg(AArch64::X16)
826 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
827 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
828 .addReg(AArch64::W16)
829 .addReg(AArch64::X17)
830 .addReg(AArch64::X16)
834 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
835 .addReg(AArch64::W16)
836 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
837 .addReg(AArch64::X16)
842 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
843 .addReg(AArch64::XZR)
844 .addReg(AArch64::X16)
847 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
848 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
851 HandleMismatchOrPartialSym, OutContext)));
852 MCSymbol *ReturnSym = OutContext.createTempSymbol();
853 OutStreamer->emitLabel(ReturnSym);
854 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
855 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
857 if (HasMatchAllTag) {
858 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
859 .addReg(AArch64::X17)
863 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
864 .addReg(AArch64::XZR)
865 .addReg(AArch64::X17)
869 MCInstBuilder(AArch64::Bcc)
875 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
876 .addReg(AArch64::WZR)
877 .addReg(AArch64::W16)
880 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
882 MCInstBuilder(AArch64::Bcc)
886 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
887 .addReg(AArch64::X17)
891 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
892 .addReg(AArch64::X17)
893 .addReg(AArch64::X17)
896 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
897 .addReg(AArch64::WZR)
898 .addReg(AArch64::W16)
899 .addReg(AArch64::W17)
902 MCInstBuilder(AArch64::Bcc)
906 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
907 .addReg(AArch64::X16)
910 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
911 .addReg(AArch64::W16)
912 .addReg(AArch64::X16)
915 MCInstBuilder(AArch64::SUBSXrs)
916 .addReg(AArch64::XZR)
917 .addReg(AArch64::X16)
921 MCInstBuilder(AArch64::Bcc)
925 OutStreamer->emitLabel(HandleMismatchSym);
928 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
934 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
940 if (
Reg != AArch64::X0)
941 emitMovXReg(AArch64::X0,
Reg);
948 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
953 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
954 .addReg(AArch64::X16)
958 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
959 .addReg(AArch64::X16)
960 .addReg(AArch64::X16)
964 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
972 const MCExpr *StubAuthPtrRef) {
975 OutStreamer.
emitValue(StubAuthPtrRef, 8);
978void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
979 emitHwasanMemaccessSymbols(M);
981 const Triple &
TT = TM.getTargetTriple();
982 if (
TT.isOSBinFormatMachO()) {
984 MachineModuleInfoMachO &MMIMacho =
985 MMI->getObjFileInfo<MachineModuleInfoMachO>();
989 if (!Stubs.empty()) {
991 OutStreamer->switchSection(
994 emitAlignment(
Align(8));
996 for (
const auto &Stub : Stubs)
999 OutStreamer->addBlankLine();
1007 OutStreamer->emitSubsectionsViaSymbols();
1010 if (
TT.isOSBinFormatELF()) {
1012 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1016 if (!Stubs.empty()) {
1017 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1019 emitAlignment(
Align(8));
1021 for (
const auto &Stub : Stubs)
1024 OutStreamer->addBlankLine();
1035 M.getModuleFlag(
"ptrauth-elf-got"));
1036 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1037 for (
const GlobalValue &GV :
M.global_values())
1039 !GV.getName().starts_with(
"llvm."))
1040 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1049 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1050 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1053 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1054 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1065 for (
auto &[Section, CallsToImportedFuncs] :
1066 SectionToImportedFunctionCalls) {
1068 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1069 OutStreamer->emitInt32(SectionSize);
1070 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1071 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1073 OutStreamer->emitInt32(0x13);
1074 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1075 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1081void AArch64AsmPrinter::emitLOHs() {
1085 for (
const MachineInstr *
MI :
D.getArgs()) {
1086 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1087 assert(LabelIt != LOHInstToLabel.end() &&
1088 "Label hasn't been inserted for LOH related instruction");
1091 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1096void AArch64AsmPrinter::emitFunctionBodyEnd() {
1102MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1106 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1107 return OutContext.getOrCreateSymbol(
1108 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1109 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1114void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1116 const MachineOperand &MO =
MI->getOperand(OpNum);
1132 PrintSymbolOperand(MO, O);
1143bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1167bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1168 const TargetRegisterClass *RC,
1169 unsigned AltName, raw_ostream &O) {
1170 assert(MO.
isReg() &&
"Should only get here with a register!");
1180bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1181 const char *ExtraCode, raw_ostream &O) {
1182 const MachineOperand &MO =
MI->getOperand(OpNum);
1189 if (ExtraCode && ExtraCode[0]) {
1190 if (ExtraCode[1] != 0)
1193 switch (ExtraCode[0]) {
1201 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1214 const TargetRegisterClass *RC;
1215 switch (ExtraCode[0]) {
1217 RC = &AArch64::FPR8RegClass;
1220 RC = &AArch64::FPR16RegClass;
1223 RC = &AArch64::FPR32RegClass;
1226 RC = &AArch64::FPR64RegClass;
1229 RC = &AArch64::FPR128RegClass;
1232 RC = &AArch64::ZPRRegClass;
1237 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1258 unsigned AltName = AArch64::NoRegAltName;
1259 const TargetRegisterClass *RegClass;
1261 RegClass = &AArch64::ZPRRegClass;
1263 RegClass = &AArch64::PPRRegClass;
1265 RegClass = &AArch64::PNRRegClass;
1267 RegClass = &AArch64::FPR128RegClass;
1268 AltName = AArch64::vreg;
1272 return printAsmRegInClass(MO, RegClass, AltName, O);
1279bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1281 const char *ExtraCode,
1283 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1286 const MachineOperand &MO =
MI->getOperand(OpNum);
1287 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1292void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1294 unsigned NOps =
MI->getNumOperands();
1296 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1298 OS <<
MI->getDebugVariable()->getName();
1301 assert(
MI->isIndirectDebugValue());
1313void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1314 ArrayRef<unsigned> JumpTableIndices) {
1316 if (JumpTableIndices.
empty())
1318 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1319 const auto &
F = MF->getFunction();
1322 MCSection *ReadOnlySec =
nullptr;
1323 if (TM.Options.EnableStaticDataPartitioning) {
1329 OutStreamer->switchSection(ReadOnlySec);
1331 auto AFI = MF->getInfo<AArch64FunctionInfo>();
1332 for (
unsigned JTI : JumpTableIndices) {
1333 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1336 if (JTBBs.empty())
continue;
1338 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1340 OutStreamer->emitLabel(GetJTISymbol(JTI));
1345 for (
auto *JTBB : JTBBs) {
1346 const MCExpr *
Value =
1365AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1366 const MachineInstr *BranchInstr,
1367 const MCSymbol *BranchLabel)
const {
1368 const auto AFI = MF->getInfo<AArch64FunctionInfo>();
1371 switch (AFI->getJumpTableEntrySize(JTI)) {
1373 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1376 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1379 EntrySize = codeview::JumpTableEntrySize::Int32;
1384 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1387void AArch64AsmPrinter::emitFunctionEntryLabel() {
1388 const Triple &
TT = TM.getTargetTriple();
1389 if (
TT.isOSBinFormatELF() &&
1390 (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall ||
1391 MF->getFunction().getCallingConv() ==
1392 CallingConv::AArch64_SVE_VectorCall ||
1393 MF->getInfo<AArch64FunctionInfo>()->isSVECC())) {
1395 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1401 if (
TT.isWindowsArm64EC() && !MF->getFunction().hasLocalLinkage()) {
1406 OutStreamer->emitAssignment(
1410 auto getSymbolFromMetadata = [&](StringRef
Name) {
1412 if (MDNode *Node = MF->getFunction().getMetadata(Name)) {
1414 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1420 MF->getFunction().getMetadata(
"arm64ec_unmangled_name", UnmangledNames);
1421 for (MDNode *Node : UnmangledNames) {
1423 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1424 if (std::optional<std::string> MangledName =
1427 MMI->getContext().getOrCreateSymbol(*MangledName);
1428 emitFunctionAlias(UnmangledSym, ECMangledSym);
1431 if (MCSymbol *ECMangledSym =
1432 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1433 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1437void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1438 const Constant *CV) {
1440 if (CPA->hasAddressDiscriminator() &&
1441 !CPA->hasSpecialAddressDiscriminator(
1444 "unexpected address discrimination value for ctors/dtors entry, only "
1445 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1454void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1455 const GlobalAlias &GA) {
1461 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1463 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1466 OutStreamer->beginCOFFSymbolDef(ExpSym);
1470 OutStreamer->endCOFFSymbolDef();
1472 OutStreamer->beginCOFFSymbolDef(Sym);
1476 OutStreamer->endCOFFSymbolDef();
1477 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1478 OutStreamer->emitAssignment(
1495void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1496 const llvm::MachineInstr &
MI) {
1497 Register DestReg =
MI.getOperand(0).getReg();
1498 Register ScratchReg =
MI.getOperand(1).getReg();
1501 Register TableReg =
MI.getOperand(2).getReg();
1502 Register EntryReg =
MI.getOperand(3).getReg();
1503 int JTIdx =
MI.getOperand(4).getIndex();
1509 MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1514 Label = MF->getContext().createTempSymbol();
1520 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1522 .addExpr(LabelExpr));
1527 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1528 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1529 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1534 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1535 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1539 .addImm(
Size == 1 ? 0 : 1));
1543 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1547 .addImm(
Size == 4 ? 0 : 2));
1550void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1551 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1552 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1554 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1555 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1571 MachineOperand JTOp =
MI.getOperand(0);
1575 "unsupported compressed jump table");
1577 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1581 uint64_t MaxTableEntry = NumTableEntries - 1;
1583 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1584 .addReg(AArch64::XZR)
1585 .addReg(AArch64::X16)
1586 .addImm(MaxTableEntry)
1589 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1594 if ((MaxTableEntry >>
Offset) == 0)
1596 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1599 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1600 .addReg(AArch64::XZR)
1601 .addReg(AArch64::X16)
1602 .addReg(AArch64::X17)
1608 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1609 .addReg(AArch64::X16)
1610 .addReg(AArch64::X16)
1611 .addReg(AArch64::XZR)
1615 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1616 MCOperand JTMCHi, JTMCLo;
1626 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1628 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1629 .addReg(AArch64::X17)
1630 .addReg(AArch64::X17)
1634 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1635 .addReg(AArch64::X16)
1636 .addReg(AArch64::X17)
1637 .addReg(AArch64::X16)
1641 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1648 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1650 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1651 .addReg(AArch64::X16)
1652 .addReg(AArch64::X17)
1653 .addReg(AArch64::X16)
1656 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1659void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1660 const llvm::MachineInstr &
MI) {
1661 unsigned Opcode =
MI.getOpcode();
1663 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1665 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1666 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1667 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1668 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1669 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1670 if (Opcode == AArch64::MOPSMemorySetPseudo)
1671 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1672 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1673 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1676 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1677 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1679 for (
auto Op :
Ops) {
1681 auto MCIB = MCInstBuilder(
Op);
1683 MCIB.addReg(
MI.getOperand(i++).getReg());
1684 MCIB.addReg(
MI.getOperand(i++).getReg());
1686 MCIB.addReg(
MI.getOperand(i++).getReg());
1688 MCIB.addReg(
MI.getOperand(i++).getReg());
1689 MCIB.addReg(
MI.getOperand(i++).getReg());
1690 MCIB.addReg(
MI.getOperand(i++).getReg());
1692 EmitToStreamer(OutStreamer, MCIB);
1696void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1697 const MachineInstr &
MI) {
1698 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1701 MCSymbol *MILabel = Ctx.createTempSymbol();
1705 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1708 const MachineBasicBlock &
MBB = *
MI.getParent();
1711 while (NumNOPBytes > 0) {
1712 if (MII ==
MBB.
end() || MII->isCall() ||
1713 MII->getOpcode() == AArch64::DBG_VALUE ||
1714 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1715 MII->getOpcode() == TargetOpcode::STACKMAP)
1722 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1723 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1728void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1729 const MachineInstr &
MI) {
1731 MCSymbol *MILabel = Ctx.createTempSymbol();
1735 PatchPointOpers Opers(&
MI);
1737 int64_t CallTarget = Opers.getCallTarget().getImm();
1738 unsigned EncodedBytes = 0;
1740 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1741 "High 16 bits of call target should be zero.");
1742 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1745 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1746 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1747 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1748 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1751 unsigned NumBytes = Opers.getNumPatchBytes();
1752 assert(NumBytes >= EncodedBytes &&
1753 "Patchpoint can't request size less than the length of a call.");
1754 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1755 "Invalid number of NOP bytes requested!");
1756 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1757 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1760void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1761 const MachineInstr &
MI) {
1762 StatepointOpers SOpers(&
MI);
1763 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1764 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1765 for (
unsigned i = 0; i < PatchBytes; i += 4)
1766 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1769 const MachineOperand &CallTarget = SOpers.getCallTarget();
1770 MCOperand CallTargetMCOp;
1771 unsigned CallOpcode;
1772 switch (CallTarget.
getType()) {
1775 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1776 CallOpcode = AArch64::BL;
1780 CallOpcode = AArch64::BL;
1784 CallOpcode = AArch64::BLR;
1791 EmitToStreamer(OutStreamer,
1792 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1796 MCSymbol *MILabel = Ctx.createTempSymbol();
1801void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1810 unsigned OperandsBeginIdx = 4;
1813 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1820 MI.setOpcode(Opcode);
1825 for (
const MachineOperand &MO :
1828 lowerOperand(MO, Dest);
1829 MI.addOperand(Dest);
1837 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1839 .addReg(AArch64::XZR)
1844void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1845 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1846 EmitToStreamer(*OutStreamer,
1847 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1853void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1854 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1855 EmitToStreamer(*OutStreamer,
1856 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1865 bool IsZeroDisc = Disc == AArch64::XZR;
1877 EmitToStreamer(AUTInst);
1882 bool IsZeroDisc = Disc == AArch64::XZR;
1894 EmitToStreamer(PACInst);
1899 bool IsZeroDisc = Disc == AArch64::XZR;
1909 EmitToStreamer(Inst);
1912void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1913 Register DestReg =
MI.getOperand(0).getReg();
1914 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->
isNeonAvailable()) {
1915 if (STI->hasZeroCycleZeroingFPR64()) {
1918 if (AArch64::FPR16RegClass.
contains(DestReg))
1919 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1920 &AArch64::FPR64RegClass);
1921 else if (AArch64::FPR32RegClass.
contains(DestReg))
1922 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1923 &AArch64::FPR64RegClass);
1931 EmitToStreamer(*OutStreamer, MOVI);
1932 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1935 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1936 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1937 &AArch64::FPR128RegClass);
1938 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1939 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1940 &AArch64::FPR128RegClass);
1943 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1944 &AArch64::FPR128RegClass);
1951 EmitToStreamer(*OutStreamer, MOVI);
1953 emitFMov0AsFMov(
MI, DestReg);
1956 emitFMov0AsFMov(
MI, DestReg);
1960void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1963 switch (
MI.getOpcode()) {
1966 case AArch64::FMOVH0:
1967 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1968 if (!STI->hasFullFP16())
1969 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1973 case AArch64::FMOVS0:
1978 case AArch64::FMOVD0:
1984 EmitToStreamer(*OutStreamer, FMov);
1987Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint64_t Disc,
1990 bool MayClobberAddrDisc) {
1991 assert(isPtrauthRegSafe(ScratchReg) &&
1992 "Safe scratch register must be provided by the caller");
1996 if (AddrDisc == AArch64::NoRegister)
1997 AddrDisc = AArch64::XZR;
2005 if (AddrDisc == AArch64::XZR) {
2006 emitMOVZ(ScratchReg, Disc, 0);
2013 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2014 ScratchReg = AddrDisc;
2016 emitMovXReg(ScratchReg, AddrDisc);
2017 assert(ScratchReg != AddrDisc &&
2018 "Forbidden to clobber AddrDisc, but have to");
2021 emitMOVK(ScratchReg, Disc, 48);
2035void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2067 if (Method == AuthCheckMethod::None)
2069 if (Method == AuthCheckMethod::DummyLoad) {
2070 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2074 assert(!OnFailure &&
"DummyLoad always traps on error");
2078 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2079 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2081 emitMovXReg(ScratchReg, TestedReg);
2083 if (Method == AuthCheckMethod::XPAC) {
2087 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2092 assert(TestedReg == AArch64::LR &&
2093 "XPACHint mode is only compatible with checking the LR register");
2095 "XPACHint mode is only compatible with I-keys");
2096 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2100 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2101 .addReg(AArch64::XZR)
2108 MCInstBuilder(AArch64::Bcc)
2111 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2113 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2120 MCInstBuilder(AArch64::TBZX)
2131 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2145 case AuthCheckMethod::XPACHint:
2148 case AuthCheckMethod::XPAC:
2150 emitMovXReg(TestedReg, ScratchReg);
2157 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2162 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2174void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2179 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2186 "Neither x16 nor x17 is available as a scratch register");
2189 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2193bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2199 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2202 MCSymbol *Dot = OutContext.createTempSymbol();
2207 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2213void AArch64AsmPrinter::emitPtrauthAuthResign(
2215 const MachineOperand *AUTAddrDisc,
Register Scratch,
2216 std::optional<AArch64PACKey::ID> PACKey, uint64_t PACDisc,
2218 const bool IsAUTPAC = PACKey.has_value();
2232 bool ShouldCheck =
true;
2234 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
2239 ShouldCheck = ShouldTrap =
false;
2246 ShouldCheck = ShouldTrap =
false;
2253 ShouldCheck = ShouldTrap =
true;
2258 Register AUTDiscReg = emitPtrauthDiscriminator(
2259 AUTDisc, AUTAddrDisc->
getReg(), Scratch, AUTAddrDisc->
isKill());
2261 if (!emitDeactivationSymbolRelocation(DS))
2262 emitAUT(AUTKey, AUTVal, AUTDiscReg);
2265 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2271 if (IsAUTPAC && !ShouldTrap)
2272 EndSym = createTempSymbol(
"resign_end_");
2274 emitPtrauthCheckAuthenticatedValue(
2275 AUTVal, Scratch, AUTKey, AArch64PAuth::AuthCheckMethod::XPAC, EndSym);
2285 Register PACDiscReg = emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
2286 emitPAC(*PACKey, AUTVal, PACDiscReg);
2293void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2296 uint64_t Disc =
MI->getOperand(3).getImm();
2297 Register AddrDisc =
MI->getOperand(4).getReg();
2298 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2302 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2303 assert(ScratchReg != AddrDisc &&
2304 "Neither X16 nor X17 is available as a scratch register");
2307 Register DiscReg = emitPtrauthDiscriminator(
2308 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2310 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2313 emitPAC(
Key, Val, DiscReg);
2316void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2317 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2318 unsigned BrTarget =
MI->getOperand(0).getReg();
2321 uint64_t Disc =
MI->getOperand(2).getImm();
2323 unsigned AddrDisc =
MI->getOperand(3).getReg();
2329 if (BrTarget == AddrDisc)
2346 bool AddrDiscIsImplicitDef =
2347 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2348 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2349 AddrDiscIsImplicitDef);
2350 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2353void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2356 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2357 const bool IsNeg = Addend < 0;
2359 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2362 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2365 .addImm((AbsOffset >> BitPos) & 0xfff)
2369 const uint64_t UAddend = Addend;
2370 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2372 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2374 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2375 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2376 uint64_t Shifted = UAddend >> BitPos;
2378 return Shifted != 0;
2379 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2380 if (((Shifted >>
I) & 0xffff) != 0xffff)
2384 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2385 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2387 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2396void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2397 MCRegister Tmp,
bool DSOLocal,
2398 const MCSubtargetInfo &STI) {
2404 MCInstBuilder(AArch64::ADRP)
2408 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2418 MCInstBuilder(AArch64::ADRP)
2423 MCInstBuilder(AArch64::LDRXui)
2434 if (!TT.isOSBinFormatELF())
2438 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2439 TT.isOSDragonFly() || TT.isOSNetBSD();
2493const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2495 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2496 const Triple &
TT = TM.getTargetTriple();
2506 AArch64Subtarget STI(TT, TM.getTargetCPU(), TM.getTargetCPU(),
2507 TM.getTargetFeatureString(), TM,
true);
2514 const MCSymbolELF *Group =
2529 .addReg(AArch64::X0)
2534 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, STI);
2536 if (HasAddressDiversity) {
2541 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2545 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2547 "' out of range [0, 0xFFFF]");
2549 emitMOVZ(AArch64::X1, Disc, 0);
2556 auto *PrePACInstExpr =
2568 const MCSymbolRefExpr *EmuPACRef =
2570 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2577 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), STI);
2585AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2586 MCContext &Ctx = OutContext;
2591 getDataLayout(),
Offset,
true);
2609 const MCExpr *DSExpr =
nullptr;
2621 "' out of range [0, " +
2629 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2631 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2636 "' out of range [0, 0xFFFF]");
2642 "expressions on this target");
2649void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2650 unsigned DstReg =
MI.getOperand(0).getReg();
2651 const MachineOperand &GAOp =
MI.getOperand(1);
2652 const uint64_t KeyC =
MI.getOperand(2).getImm();
2654 "key is out of range [0, AArch64PACKey::LAST]");
2656 const uint64_t Disc =
MI.getOperand(3).getImm();
2658 "constant discriminator is out of range [0, 0xffff]");
2667 if (TM.getTargetTriple().isOSBinFormatELF()) {
2669 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2672 "non-zero offset for $auth_ptr$ stub slots is not supported");
2674 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2676 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2677 "LOADauthptrstatic is implemented only for MachO/ELF");
2679 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2680 getObjFileLowering());
2683 "non-zero offset for $auth_ptr$ stub slots is not supported");
2685 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2688 MachineOperand StubMOHi =
2692 MCOperand StubMCHi, StubMCLo;
2699 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2701 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2707void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2708 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2709 const bool IsELFSignedGOT =
MI.getParent()
2711 ->getInfo<AArch64FunctionInfo>()
2712 ->hasELFSignedGOT();
2713 MachineOperand GAOp =
MI.getOperand(0);
2714 const uint64_t KeyC =
MI.getOperand(1).getImm();
2716 "key is out of range [0, AArch64PACKey::LAST]");
2718 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2719 const uint64_t Disc =
MI.getOperand(3).getImm();
2766 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2767 MCOperand GAMCHi, GAMCLo;
2780 MCInstBuilder(AArch64::ADRP)
2781 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2785 if (IsELFSignedGOT) {
2786 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2787 .addReg(AArch64::X17)
2788 .addReg(AArch64::X17)
2792 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2793 .addReg(AArch64::X16)
2794 .addReg(AArch64::X17)
2802 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2804 if (!STI->hasFPAC())
2805 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2806 AArch64PAuth::AuthCheckMethod::XPAC);
2808 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2809 .addReg(AArch64::X16)
2810 .addReg(AArch64::X16)
2814 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2815 .addReg(AArch64::X16)
2816 .addReg(AArch64::X16)
2821 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2822 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2824 emitPAC(
Key, AArch64::X16, DiscReg);
2827void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2829 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2830 const MachineOperand &GAMO =
MI.getOperand(1);
2837 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2838 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2839 .addReg(AuthResultReg)
2840 .addReg(AArch64::X17)
2843 MachineOperand GAHiOp(GAMO);
2844 MachineOperand GALoOp(GAMO);
2848 MCOperand GAMCHi, GAMCLo;
2853 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2855 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2856 .addReg(AArch64::X17)
2857 .addReg(AArch64::X17)
2861 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2862 .addReg(AuthResultReg)
2863 .addReg(AArch64::X17)
2870 UndefWeakSym = createTempSymbol(
"undef_weak");
2872 MCInstBuilder(AArch64::CBZX)
2873 .addReg(AuthResultReg)
2881 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2886 if (!STI->hasFPAC()) {
2887 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2888 AArch64PAuth::AuthCheckMethod::XPAC);
2890 emitMovXReg(DstReg, AuthResultReg);
2895AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2899 if (std::optional<uint16_t> BADisc =
2900 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2907void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
2911 switch (
MI->getOpcode()) {
2914 case AArch64::CBBAssertExt:
2918 case AArch64::CBHAssertExt:
2922 case AArch64::CBWPrr:
2925 case AArch64::CBXPrr:
2928 case AArch64::CBWPri:
2932 case AArch64::CBXPri:
2940 bool NeedsRegSwap =
false;
2941 bool NeedsImmDec =
false;
2942 bool NeedsImmInc =
false;
2944#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
2946 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
2948 ? AArch64::CBB##RegCond##Wrr \
2949 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
2950 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
2951 : AArch64::CB##RegCond##Xrr))))
2967 NeedsImmDec = IsImm;
2971 NeedsRegSwap = !IsImm;
2978 NeedsRegSwap = !IsImm;
2979 NeedsImmInc = IsImm;
2983 NeedsImmDec = IsImm;
2987 NeedsRegSwap = !IsImm;
2994 NeedsRegSwap = !IsImm;
2995 NeedsImmInc = IsImm;
3003 MCOperand Lhs, Rhs, Trgt;
3004 lowerOperand(
MI->getOperand(1), Lhs);
3005 lowerOperand(
MI->getOperand(2), Rhs);
3006 lowerOperand(
MI->getOperand(3), Trgt);
3010 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3011 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3014 }
else if (NeedsImmDec) {
3018 }
else if (NeedsImmInc) {
3028 "CB immediate operand out-of-bounds");
3031 EmitToStreamer(*OutStreamer, Inst);
3036#include "AArch64GenMCPseudoLowering.inc"
3038void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3045void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3046 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3051 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3056 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3057 EmitToStreamer(*OutStreamer, OutInst);
3061 if (
MI->getOpcode() == AArch64::ADRP) {
3062 for (
auto &Opd :
MI->operands()) {
3063 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3064 "swift_async_extendedFramePointerFlags") {
3065 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3072 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3074 LOHInstToLabel[
MI] = LOHLabel;
3078 AArch64TargetStreamer *TS =
3081 switch (
MI->getOpcode()) {
3084 "Unhandled tail call instruction");
3086 case AArch64::HINT: {
3091 if (CurrentPatchableFunctionEntrySym &&
3092 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3093 MI == &MF->front().front()) {
3094 int64_t
Imm =
MI->getOperand(0).getImm();
3095 if ((Imm & 32) && (Imm & 6)) {
3097 MCInstLowering.
Lower(
MI, Inst);
3098 EmitToStreamer(*OutStreamer, Inst);
3099 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3100 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3106 case AArch64::MOVMCSym: {
3107 Register DestReg =
MI->getOperand(0).getReg();
3108 const MachineOperand &MO_Sym =
MI->getOperand(1);
3109 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3110 MCOperand Hi_MCSym, Lo_MCSym;
3123 EmitToStreamer(*OutStreamer, MovZ);
3131 EmitToStreamer(*OutStreamer, MovK);
3134 case AArch64::MOVIv2d_ns:
3142 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3143 MI->getOperand(1).getImm() == 0) {
3145 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3148 EmitToStreamer(*OutStreamer, TmpInst);
3153 case AArch64::DBG_VALUE:
3154 case AArch64::DBG_VALUE_LIST:
3156 SmallString<128> TmpStr;
3157 raw_svector_ostream OS(TmpStr);
3158 PrintDebugValueComment(
MI, OS);
3163 case AArch64::EMITBKEY: {
3165 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3166 ExceptionHandlingType != ExceptionHandling::ARM)
3169 if (getFunctionCFISectionType(*MF) == CFISection::None)
3176 case AArch64::EMITMTETAGGED: {
3178 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3179 ExceptionHandlingType != ExceptionHandling::ARM)
3182 if (getFunctionCFISectionType(*MF) != CFISection::None)
3187 case AArch64::AUTx16x17:
3188 emitPtrauthAuthResign(
3190 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3191 std::nullopt, 0, 0,
MI->getDeactivationSymbol());
3194 case AArch64::AUTxMxN:
3195 emitPtrauthAuthResign(
MI->getOperand(0).getReg(),
3197 MI->getOperand(4).getImm(), &
MI->getOperand(5),
3198 MI->getOperand(1).getReg(), std::nullopt, 0, 0,
3199 MI->getDeactivationSymbol());
3202 case AArch64::AUTPAC:
3203 emitPtrauthAuthResign(
3205 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3207 MI->getOperand(4).getImm(),
MI->getOperand(5).getReg(),
3208 MI->getDeactivationSymbol());
3212 emitPtrauthSign(
MI);
3215 case AArch64::LOADauthptrstatic:
3216 LowerLOADauthptrstatic(*
MI);
3219 case AArch64::LOADgotPAC:
3220 case AArch64::MOVaddrPAC:
3221 LowerMOVaddrPAC(*
MI);
3224 case AArch64::LOADgotAUTH:
3225 LowerLOADgotAUTH(*
MI);
3230 emitPtrauthBranch(
MI);
3236 case AArch64::AUTH_TCRETURN:
3237 case AArch64::AUTH_TCRETURN_BTI: {
3240 const uint64_t Disc =
MI->getOperand(3).getImm();
3242 Register AddrDisc =
MI->getOperand(4).getReg();
3244 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3246 emitPtrauthTailCallHardening(
MI);
3249 if (Callee == AddrDisc)
3256 bool AddrDiscIsImplicitDef =
3257 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3258 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3259 AddrDiscIsImplicitDef);
3260 emitBLRA(
false,
Key, Callee, DiscReg);
3264 case AArch64::TCRETURNri:
3265 case AArch64::TCRETURNrix16x17:
3266 case AArch64::TCRETURNrix17:
3267 case AArch64::TCRETURNrinotx16:
3268 case AArch64::TCRETURNriALL: {
3269 emitPtrauthTailCallHardening(
MI);
3271 recordIfImportCall(
MI);
3275 EmitToStreamer(*OutStreamer, TmpInst);
3278 case AArch64::TCRETURNdi: {
3279 emitPtrauthTailCallHardening(
MI);
3283 recordIfImportCall(
MI);
3287 EmitToStreamer(*OutStreamer, TmpInst);
3290 case AArch64::SpeculationBarrierISBDSBEndBB: {
3295 EmitToStreamer(*OutStreamer, TmpInstDSB);
3299 EmitToStreamer(*OutStreamer, TmpInstISB);
3302 case AArch64::SpeculationBarrierSBEndBB: {
3306 EmitToStreamer(*OutStreamer, TmpInstSB);
3309 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3316 const MachineOperand &MO_Sym =
MI->getOperand(0);
3317 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3318 MCOperand SymTLSDescLo12, SymTLSDesc;
3321 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3328 EmitToStreamer(*OutStreamer, Adrp);
3336 EmitToStreamer(*OutStreamer, Ldr);
3339 Add.setOpcode(AArch64::ADDXri);
3342 Add.addOperand(SymTLSDescLo12);
3344 EmitToStreamer(*OutStreamer,
Add);
3353 EmitToStreamer(*OutStreamer, Blraa);
3357 case AArch64::TLSDESC_CALLSEQ: {
3365 const MachineOperand &MO_Sym =
MI->getOperand(0);
3366 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3367 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3371 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3378 EmitToStreamer(*OutStreamer, Adrp);
3381 if (STI->isTargetILP32()) {
3391 EmitToStreamer(*OutStreamer, Ldr);
3394 if (STI->isTargetILP32()) {
3395 Add.setOpcode(AArch64::ADDWri);
3399 Add.setOpcode(AArch64::ADDXri);
3403 Add.addOperand(SymTLSDescLo12);
3405 EmitToStreamer(*OutStreamer,
Add);
3410 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3412 EmitToStreamer(*OutStreamer, TLSDescCall);
3420 EmitToStreamer(*OutStreamer, Blr);
3425 case AArch64::JumpTableDest32:
3426 case AArch64::JumpTableDest16:
3427 case AArch64::JumpTableDest8:
3428 LowerJumpTableDest(*OutStreamer, *
MI);
3431 case AArch64::BR_JumpTable:
3432 LowerHardenedBRJumpTable(*
MI);
3435 case AArch64::FMOVH0:
3436 case AArch64::FMOVS0:
3437 case AArch64::FMOVD0:
3441 case AArch64::MOPSMemoryCopyPseudo:
3442 case AArch64::MOPSMemoryMovePseudo:
3443 case AArch64::MOPSMemorySetPseudo:
3444 case AArch64::MOPSMemorySetTaggingPseudo:
3445 LowerMOPS(*OutStreamer, *
MI);
3448 case TargetOpcode::STACKMAP:
3449 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3451 case TargetOpcode::PATCHPOINT:
3452 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3454 case TargetOpcode::STATEPOINT:
3455 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3457 case TargetOpcode::FAULTING_OP:
3458 return LowerFAULTING_OP(*
MI);
3460 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3461 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3464 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3465 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3468 case TargetOpcode::PATCHABLE_TAIL_CALL:
3469 LowerPATCHABLE_TAIL_CALL(*
MI);
3471 case TargetOpcode::PATCHABLE_EVENT_CALL:
3472 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3473 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3474 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3476 case AArch64::KCFI_CHECK:
3477 LowerKCFI_CHECK(*
MI);
3480 case AArch64::HWASAN_CHECK_MEMACCESS:
3481 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3482 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3483 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3484 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3487 case AArch64::SEH_StackAlloc:
3491 case AArch64::SEH_SaveFPLR:
3495 case AArch64::SEH_SaveFPLR_X:
3496 assert(
MI->getOperand(0).getImm() < 0 &&
3497 "Pre increment SEH opcode must have a negative offset");
3501 case AArch64::SEH_SaveReg:
3503 MI->getOperand(1).getImm());
3506 case AArch64::SEH_SaveReg_X:
3507 assert(
MI->getOperand(1).getImm() < 0 &&
3508 "Pre increment SEH opcode must have a negative offset");
3510 -
MI->getOperand(1).getImm());
3513 case AArch64::SEH_SaveRegP:
3514 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3515 MI->getOperand(0).getImm() <= 28) {
3516 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3517 "Register paired with LR must be odd");
3519 MI->getOperand(2).getImm());
3522 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3523 "Non-consecutive registers not allowed for save_regp");
3525 MI->getOperand(2).getImm());
3528 case AArch64::SEH_SaveRegP_X:
3529 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3530 "Non-consecutive registers not allowed for save_regp_x");
3531 assert(
MI->getOperand(2).getImm() < 0 &&
3532 "Pre increment SEH opcode must have a negative offset");
3534 -
MI->getOperand(2).getImm());
3537 case AArch64::SEH_SaveFReg:
3539 MI->getOperand(1).getImm());
3542 case AArch64::SEH_SaveFReg_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_SaveFRegP:
3550 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3551 "Non-consecutive registers not allowed for save_regp");
3553 MI->getOperand(2).getImm());
3556 case AArch64::SEH_SaveFRegP_X:
3557 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3558 "Non-consecutive registers not allowed for save_regp_x");
3559 assert(
MI->getOperand(2).getImm() < 0 &&
3560 "Pre increment SEH opcode must have a negative offset");
3562 -
MI->getOperand(2).getImm());
3565 case AArch64::SEH_SetFP:
3569 case AArch64::SEH_AddFP:
3573 case AArch64::SEH_Nop:
3577 case AArch64::SEH_PrologEnd:
3581 case AArch64::SEH_EpilogStart:
3585 case AArch64::SEH_EpilogEnd:
3589 case AArch64::SEH_PACSignLR:
3593 case AArch64::SEH_SaveAnyRegI:
3594 assert(
MI->getOperand(1).getImm() <= 1008 &&
3595 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3597 MI->getOperand(1).getImm());
3600 case AArch64::SEH_SaveAnyRegIP:
3601 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3602 "Non-consecutive registers not allowed for save_any_reg");
3603 assert(
MI->getOperand(2).getImm() <= 1008 &&
3604 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3606 MI->getOperand(2).getImm());
3609 case AArch64::SEH_SaveAnyRegQP:
3610 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3611 "Non-consecutive registers not allowed for save_any_reg");
3612 assert(
MI->getOperand(2).getImm() >= 0 &&
3613 "SaveAnyRegQP SEH opcode offset must be non-negative");
3614 assert(
MI->getOperand(2).getImm() <= 1008 &&
3615 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3617 MI->getOperand(2).getImm());
3620 case AArch64::SEH_SaveAnyRegQPX:
3621 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3622 "Non-consecutive registers not allowed for save_any_reg");
3623 assert(
MI->getOperand(2).getImm() < 0 &&
3624 "SaveAnyRegQPX SEH opcode offset must be negative");
3625 assert(
MI->getOperand(2).getImm() >= -1008 &&
3626 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3628 -
MI->getOperand(2).getImm());
3631 case AArch64::SEH_AllocZ:
3632 assert(
MI->getOperand(0).getImm() >= 0 &&
3633 "AllocZ SEH opcode offset must be non-negative");
3634 assert(
MI->getOperand(0).getImm() <= 255 &&
3635 "AllocZ SEH opcode offset must fit into 8 bits");
3639 case AArch64::SEH_SaveZReg:
3640 assert(
MI->getOperand(1).getImm() >= 0 &&
3641 "SaveZReg SEH opcode offset must be non-negative");
3642 assert(
MI->getOperand(1).getImm() <= 255 &&
3643 "SaveZReg SEH opcode offset must fit into 8 bits");
3645 MI->getOperand(1).getImm());
3648 case AArch64::SEH_SavePReg:
3649 assert(
MI->getOperand(1).getImm() >= 0 &&
3650 "SavePReg SEH opcode offset must be non-negative");
3651 assert(
MI->getOperand(1).getImm() <= 255 &&
3652 "SavePReg SEH opcode offset must fit into 8 bits");
3654 MI->getOperand(1).getImm());
3659 recordIfImportCall(
MI);
3661 MCInstLowering.
Lower(
MI, TmpInst);
3662 EmitToStreamer(*OutStreamer, TmpInst);
3665 case AArch64::CBWPri:
3666 case AArch64::CBXPri:
3667 case AArch64::CBBAssertExt:
3668 case AArch64::CBHAssertExt:
3669 case AArch64::CBWPrr:
3670 case AArch64::CBXPrr:
3671 emitCBPseudoExpansion(
MI);
3675 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3680 MCInstLowering.
Lower(
MI, TmpInst);
3681 EmitToStreamer(*OutStreamer, TmpInst);
3684void AArch64AsmPrinter::recordIfImportCall(
3685 const llvm::MachineInstr *BranchInst) {
3686 if (!EnableImportCallOptimization)
3690 if (GV && GV->hasDLLImportStorageClass()) {
3691 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3696 .push_back({CallSiteSymbol, CalledSymbol});
3700void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3701 MCSymbol *LazyPointer) {
3718 EmitToStreamer(Adrp);
3726 MCOperand SymPageOff;
3733 EmitToStreamer(Ldr);
3736 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3737 .addReg(AArch64::X16)
3738 .addReg(AArch64::X16)
3741 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3743 .addReg(AArch64::X16));
3746void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3747 const GlobalIFunc &GI,
3748 MCSymbol *LazyPointer) {
3780 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3781 .addReg(AArch64::SP)
3782 .addReg(AArch64::FP)
3783 .addReg(AArch64::LR)
3784 .addReg(AArch64::SP)
3787 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3788 .addReg(AArch64::FP)
3789 .addReg(AArch64::SP)
3793 for (
int I = 0;
I != 4; ++
I)
3794 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3795 .addReg(AArch64::SP)
3796 .addReg(AArch64::X1 + 2 *
I)
3797 .addReg(AArch64::X0 + 2 *
I)
3798 .addReg(AArch64::SP)
3801 for (
int I = 0;
I != 4; ++
I)
3802 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3803 .addReg(AArch64::SP)
3804 .addReg(AArch64::D1 + 2 *
I)
3805 .addReg(AArch64::D0 + 2 *
I)
3806 .addReg(AArch64::SP)
3810 MCInstBuilder(AArch64::BL)
3823 EmitToStreamer(Adrp);
3831 MCOperand SymPageOff;
3838 EmitToStreamer(Ldr);
3841 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3842 .addReg(AArch64::X0)
3843 .addReg(AArch64::X16)
3846 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3847 .addReg(AArch64::X16)
3848 .addReg(AArch64::X0)
3852 for (
int I = 3;
I != -1; --
I)
3853 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3854 .addReg(AArch64::SP)
3855 .addReg(AArch64::D1 + 2 *
I)
3856 .addReg(AArch64::D0 + 2 *
I)
3857 .addReg(AArch64::SP)
3860 for (
int I = 3;
I != -1; --
I)
3861 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3862 .addReg(AArch64::SP)
3863 .addReg(AArch64::X1 + 2 *
I)
3864 .addReg(AArch64::X0 + 2 *
I)
3865 .addReg(AArch64::SP)
3868 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3869 .addReg(AArch64::SP)
3870 .addReg(AArch64::FP)
3871 .addReg(AArch64::LR)
3872 .addReg(AArch64::SP)
3875 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3877 .addReg(AArch64::X16));
3880const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
3881 const Constant *BaseCV,
3891char AArch64AsmPrinter::ID = 0;
3894 "AArch64 Assembly Printer",
false,
false)
3898LLVMInitializeAArch64AsmPrinter() {
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 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.
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....
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.
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 constexpr unsigned NonUniqueID
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.
const FeatureBitset & getFeatureBits() const
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)
static unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K, bool Zero)
Return B(L)RA opcode to be used for an authenticated branch or call using the given key,...
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,...