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);
226 const MCExpr *emitPAuthRelocationAsIRelative(
228 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
235 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
242 void EmitToStreamer(
const MCInst &Inst) {
243 EmitToStreamer(*OutStreamer, Inst);
248 void emitFunctionHeaderComment()
override;
256 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
257 PSI = &PSIW->getPSI();
259 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
260 SDPI = &SDPIW->getStaticDataProfileInfo();
265 SetupMachineFunction(MF);
267 if (STI->isTargetCOFF()) {
303 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
308 void emitFunctionBodyEnd()
override;
311 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
312 void emitEndOfAsmFile(
Module &M)
override;
327 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
329 MInstToMCSymbol LOHInstToLabel;
331 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
332 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
352void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
353 const Triple &
TT = TM.getTargetTriple();
355 if (
TT.isOSBinFormatCOFF()) {
356 emitCOFFFeatureSymbol(M);
357 emitCOFFReplaceableFunctionData(M);
359 if (
M.getModuleFlag(
"import-call-optimization"))
360 EnableImportCallOptimization =
true;
363 if (!
TT.isOSBinFormatELF())
368 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
371 unsigned BAFlags = 0;
372 unsigned GNUFlags = 0;
374 M.getModuleFlag(
"branch-target-enforcement"))) {
375 if (!BTE->isZero()) {
376 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
382 M.getModuleFlag(
"guarded-control-stack"))) {
383 if (!GCS->isZero()) {
384 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
390 M.getModuleFlag(
"sign-return-address"))) {
391 if (!Sign->isZero()) {
392 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
397 uint64_t PAuthABIPlatform = -1;
399 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
400 PAuthABIPlatform = PAP->getZExtValue();
403 uint64_t PAuthABIVersion = -1;
405 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
406 PAuthABIVersion = PAV->getZExtValue();
410 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
412 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
415void AArch64AsmPrinter::emitFunctionHeaderComment() {
416 const AArch64FunctionInfo *FI = MF->getInfo<AArch64FunctionInfo>();
418 if (OutlinerString != std::nullopt)
419 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
422void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
425 if (
F.hasFnAttribute(
"patchable-function-entry")) {
427 if (
F.getFnAttribute(
"patchable-function-entry")
429 .getAsInteger(10, Num))
435 emitSled(
MI, SledKind::FUNCTION_ENTER);
438void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
439 emitSled(
MI, SledKind::FUNCTION_EXIT);
442void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
443 emitSled(
MI, SledKind::TAIL_CALL);
446void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
447 static const int8_t NoopsInSledCount = 7;
468 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
469 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
470 OutStreamer->emitLabel(CurSled);
471 auto Target = OutContext.createTempSymbol();
476 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
478 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
479 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
481 OutStreamer->emitLabel(Target);
482 recordSled(CurSled,
MI, Kind, 2);
485void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
486 uint64_t PAuthABIPlatform,
487 uint64_t PAuthABIVersion,
488 AArch64TargetStreamer *TS) {
490 PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
491 PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
493 if (PAuthABIPlatform || PAuthABIVersion) {
497 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
498 AArch64BuildAttributes::SubsectionType::ULEB128);
502 PAuthABIPlatform,
"");
516 if (BTIValue || PACValue || GCSValue) {
520 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
521 AArch64BuildAttributes::SubsectionType::ULEB128);
549void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
551 auto &
O = *OutStreamer;
552 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
553 O.emitLabel(CurSled);
554 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
556 OutContext.getOrCreateSymbol(
557 Twine(MachO ?
"_" :
"") +
558 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
561 O.AddComment(
"Begin XRay typed event");
562 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
563 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
569 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
573 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
574 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
575 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
576 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
577 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
581 O.AddComment(
"End XRay typed event");
582 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
589 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
591 O.AddComment(
"Begin XRay custom event");
592 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
593 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
599 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
600 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
601 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
602 O.AddComment(
"End XRay custom event");
603 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
610 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
614void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
616 assert(std::next(
MI.getIterator())->isCall() &&
617 "KCFI_CHECK not followed by a call instruction");
618 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
619 "KCFI_CHECK call target doesn't match call operand");
623 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
624 if (AddrReg == AArch64::XZR) {
628 emitMovXReg(AddrReg, AArch64::XZR);
634 for (
auto &
Reg : ScratchRegs) {
640 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
641 "Invalid scratch registers for KCFI_CHECK");
645 int64_t PrefixNops = 0;
648 .getFnAttribute(
"patchable-function-prefix")
650 .getAsInteger(10, PrefixNops);
653 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
654 .addReg(ScratchRegs[0])
656 .addImm(-(PrefixNops * 4 + 4)));
660 const int64_t
Type =
MI.getOperand(1).getImm();
661 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
662 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
665 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
666 .addReg(AArch64::WZR)
667 .addReg(ScratchRegs[0])
668 .addReg(ScratchRegs[1])
672 EmitToStreamer(*OutStreamer,
673 MCInstBuilder(AArch64::Bcc)
682 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
686 AddrIndex = AddrReg - AArch64::X0;
696 assert(AddrIndex < 31 && TypeIndex < 31);
698 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
699 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
700 OutStreamer->emitLabel(
Pass);
703void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
711 if (
Reg == AArch64::XZR)
715 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
717 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
718 uint32_t AccessInfo =
MI.getOperand(1).getImm();
720 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
722 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
723 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
725 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
726 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
729 if (!TM.getTargetTriple().isOSBinFormatELF())
732 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
735 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
737 SymName +=
"_short_v2";
738 Sym = OutContext.getOrCreateSymbol(SymName);
741 EmitToStreamer(*OutStreamer,
742 MCInstBuilder(AArch64::BL)
746void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
747 if (HwasanMemaccessSymbols.empty())
750 const Triple &
TT = TM.getTargetTriple();
752 std::unique_ptr<MCSubtargetInfo> STI(
753 TM.getTarget().createMCSubtargetInfo(TT,
"",
""));
754 assert(STI &&
"Unable to create subtarget info");
755 this->STI =
static_cast<const AArch64Subtarget *
>(&*STI);
758 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
760 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
762 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
764 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
767 for (
auto &
P : HwasanMemaccessSymbols) {
768 unsigned Reg = std::get<0>(
P.first);
769 bool IsShort = std::get<1>(
P.first);
770 uint32_t AccessInfo = std::get<2>(
P.first);
771 bool IsFixedShadow = std::get<3>(
P.first);
772 uint64_t FixedShadowOffset = std::get<4>(
P.first);
773 const MCSymbolRefExpr *HwasanTagMismatchRef =
774 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
777 bool HasMatchAllTag =
779 uint8_t MatchAllTag =
786 OutStreamer->switchSection(OutContext.getELFSection(
792 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
793 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
794 OutStreamer->emitLabel(Sym);
796 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
797 .addReg(AArch64::X16)
807 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
808 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
809 .addReg(AArch64::W16)
810 .addReg(AArch64::X17)
811 .addReg(AArch64::X16)
815 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
816 .addReg(AArch64::W16)
817 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
818 .addReg(AArch64::X16)
823 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
824 .addReg(AArch64::XZR)
825 .addReg(AArch64::X16)
828 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
829 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
832 HandleMismatchOrPartialSym, OutContext)));
833 MCSymbol *ReturnSym = OutContext.createTempSymbol();
834 OutStreamer->emitLabel(ReturnSym);
835 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
836 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
838 if (HasMatchAllTag) {
839 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
840 .addReg(AArch64::X17)
844 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
845 .addReg(AArch64::XZR)
846 .addReg(AArch64::X17)
850 MCInstBuilder(AArch64::Bcc)
856 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
857 .addReg(AArch64::WZR)
858 .addReg(AArch64::W16)
861 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
863 MCInstBuilder(AArch64::Bcc)
867 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
868 .addReg(AArch64::X17)
872 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
873 .addReg(AArch64::X17)
874 .addReg(AArch64::X17)
877 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
878 .addReg(AArch64::WZR)
879 .addReg(AArch64::W16)
880 .addReg(AArch64::W17)
883 MCInstBuilder(AArch64::Bcc)
887 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
888 .addReg(AArch64::X16)
891 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
892 .addReg(AArch64::W16)
893 .addReg(AArch64::X16)
896 MCInstBuilder(AArch64::SUBSXrs)
897 .addReg(AArch64::XZR)
898 .addReg(AArch64::X16)
902 MCInstBuilder(AArch64::Bcc)
906 OutStreamer->emitLabel(HandleMismatchSym);
909 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
915 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
921 if (
Reg != AArch64::X0)
922 emitMovXReg(AArch64::X0,
Reg);
929 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
934 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
935 .addReg(AArch64::X16)
939 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
940 .addReg(AArch64::X16)
941 .addReg(AArch64::X16)
945 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
953 const MCExpr *StubAuthPtrRef) {
956 OutStreamer.
emitValue(StubAuthPtrRef, 8);
959void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
960 emitHwasanMemaccessSymbols(M);
962 const Triple &
TT = TM.getTargetTriple();
963 if (
TT.isOSBinFormatMachO()) {
965 MachineModuleInfoMachO &MMIMacho =
966 MMI->getObjFileInfo<MachineModuleInfoMachO>();
970 if (!Stubs.empty()) {
972 OutStreamer->switchSection(
975 emitAlignment(
Align(8));
977 for (
const auto &Stub : Stubs)
980 OutStreamer->addBlankLine();
988 OutStreamer->emitSubsectionsViaSymbols();
991 if (
TT.isOSBinFormatELF()) {
993 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
997 if (!Stubs.empty()) {
998 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1000 emitAlignment(
Align(8));
1002 for (
const auto &Stub : Stubs)
1005 OutStreamer->addBlankLine();
1016 M.getModuleFlag(
"ptrauth-elf-got"));
1017 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1018 for (
const GlobalValue &GV :
M.global_values())
1020 !GV.getName().starts_with(
"llvm."))
1021 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1030 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1031 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1034 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1035 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1046 for (
auto &[Section, CallsToImportedFuncs] :
1047 SectionToImportedFunctionCalls) {
1049 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1050 OutStreamer->emitInt32(SectionSize);
1051 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1052 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1054 OutStreamer->emitInt32(0x13);
1055 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1056 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1062void AArch64AsmPrinter::emitLOHs() {
1066 for (
const MachineInstr *
MI :
D.getArgs()) {
1067 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1068 assert(LabelIt != LOHInstToLabel.end() &&
1069 "Label hasn't been inserted for LOH related instruction");
1072 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1077void AArch64AsmPrinter::emitFunctionBodyEnd() {
1083MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1087 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1088 return OutContext.getOrCreateSymbol(
1089 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1090 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1095void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1097 const MachineOperand &MO =
MI->getOperand(OpNum);
1113 PrintSymbolOperand(MO, O);
1124bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1148bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1149 const TargetRegisterClass *RC,
1150 unsigned AltName, raw_ostream &O) {
1151 assert(MO.
isReg() &&
"Should only get here with a register!");
1161bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1162 const char *ExtraCode, raw_ostream &O) {
1163 const MachineOperand &MO =
MI->getOperand(OpNum);
1170 if (ExtraCode && ExtraCode[0]) {
1171 if (ExtraCode[1] != 0)
1174 switch (ExtraCode[0]) {
1182 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1195 const TargetRegisterClass *RC;
1196 switch (ExtraCode[0]) {
1198 RC = &AArch64::FPR8RegClass;
1201 RC = &AArch64::FPR16RegClass;
1204 RC = &AArch64::FPR32RegClass;
1207 RC = &AArch64::FPR64RegClass;
1210 RC = &AArch64::FPR128RegClass;
1213 RC = &AArch64::ZPRRegClass;
1218 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1239 unsigned AltName = AArch64::NoRegAltName;
1240 const TargetRegisterClass *RegClass;
1242 RegClass = &AArch64::ZPRRegClass;
1244 RegClass = &AArch64::PPRRegClass;
1246 RegClass = &AArch64::PNRRegClass;
1248 RegClass = &AArch64::FPR128RegClass;
1249 AltName = AArch64::vreg;
1253 return printAsmRegInClass(MO, RegClass, AltName, O);
1260bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1262 const char *ExtraCode,
1264 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1267 const MachineOperand &MO =
MI->getOperand(OpNum);
1268 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1273void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1275 unsigned NOps =
MI->getNumOperands();
1277 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1279 OS <<
MI->getDebugVariable()->getName();
1282 assert(
MI->isIndirectDebugValue());
1294void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1295 ArrayRef<unsigned> JumpTableIndices) {
1297 if (JumpTableIndices.
empty())
1299 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1300 const auto &
F = MF->getFunction();
1303 MCSection *ReadOnlySec =
nullptr;
1304 if (TM.Options.EnableStaticDataPartitioning) {
1310 OutStreamer->switchSection(ReadOnlySec);
1312 auto AFI = MF->getInfo<AArch64FunctionInfo>();
1313 for (
unsigned JTI : JumpTableIndices) {
1314 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1317 if (JTBBs.empty())
continue;
1319 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1321 OutStreamer->emitLabel(GetJTISymbol(JTI));
1326 for (
auto *JTBB : JTBBs) {
1327 const MCExpr *
Value =
1346AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1347 const MachineInstr *BranchInstr,
1348 const MCSymbol *BranchLabel)
const {
1349 const auto AFI = MF->getInfo<AArch64FunctionInfo>();
1352 switch (AFI->getJumpTableEntrySize(JTI)) {
1354 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1357 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1360 EntrySize = codeview::JumpTableEntrySize::Int32;
1365 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1368void AArch64AsmPrinter::emitFunctionEntryLabel() {
1369 const Triple &
TT = TM.getTargetTriple();
1370 if (
TT.isOSBinFormatELF() &&
1371 (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall ||
1372 MF->getFunction().getCallingConv() ==
1373 CallingConv::AArch64_SVE_VectorCall ||
1374 MF->getInfo<AArch64FunctionInfo>()->isSVECC())) {
1376 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1382 if (
TT.isWindowsArm64EC() && !MF->getFunction().hasLocalLinkage()) {
1387 OutStreamer->emitAssignment(
1391 auto getSymbolFromMetadata = [&](StringRef
Name) {
1393 if (MDNode *Node = MF->getFunction().getMetadata(Name)) {
1395 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1401 MF->getFunction().getMetadata(
"arm64ec_unmangled_name", UnmangledNames);
1402 for (MDNode *Node : UnmangledNames) {
1404 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1405 if (std::optional<std::string> MangledName =
1408 MMI->getContext().getOrCreateSymbol(*MangledName);
1409 emitFunctionAlias(UnmangledSym, ECMangledSym);
1412 if (MCSymbol *ECMangledSym =
1413 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1414 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1418void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1419 const Constant *CV) {
1421 if (CPA->hasAddressDiscriminator() &&
1422 !CPA->hasSpecialAddressDiscriminator(
1425 "unexpected address discrimination value for ctors/dtors entry, only "
1426 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1435void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1436 const GlobalAlias &GA) {
1442 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1444 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1447 OutStreamer->beginCOFFSymbolDef(ExpSym);
1451 OutStreamer->endCOFFSymbolDef();
1453 OutStreamer->beginCOFFSymbolDef(Sym);
1457 OutStreamer->endCOFFSymbolDef();
1458 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1459 OutStreamer->emitAssignment(
1476void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1477 const llvm::MachineInstr &
MI) {
1478 Register DestReg =
MI.getOperand(0).getReg();
1479 Register ScratchReg =
MI.getOperand(1).getReg();
1482 Register TableReg =
MI.getOperand(2).getReg();
1483 Register EntryReg =
MI.getOperand(3).getReg();
1484 int JTIdx =
MI.getOperand(4).getIndex();
1490 MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1495 Label = MF->getContext().createTempSymbol();
1501 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1503 .addExpr(LabelExpr));
1508 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1509 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1510 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1515 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1516 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1520 .addImm(
Size == 1 ? 0 : 1));
1524 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1528 .addImm(
Size == 4 ? 0 : 2));
1531void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1532 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1533 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1535 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1536 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1552 MachineOperand JTOp =
MI.getOperand(0);
1556 "unsupported compressed jump table");
1558 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1562 uint64_t MaxTableEntry = NumTableEntries - 1;
1564 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1565 .addReg(AArch64::XZR)
1566 .addReg(AArch64::X16)
1567 .addImm(MaxTableEntry)
1570 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1575 if ((MaxTableEntry >>
Offset) == 0)
1577 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1580 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1581 .addReg(AArch64::XZR)
1582 .addReg(AArch64::X16)
1583 .addReg(AArch64::X17)
1589 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1590 .addReg(AArch64::X16)
1591 .addReg(AArch64::X16)
1592 .addReg(AArch64::XZR)
1596 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1597 MCOperand JTMCHi, JTMCLo;
1607 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1609 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1610 .addReg(AArch64::X17)
1611 .addReg(AArch64::X17)
1615 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1616 .addReg(AArch64::X16)
1617 .addReg(AArch64::X17)
1618 .addReg(AArch64::X16)
1622 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1629 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1631 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1632 .addReg(AArch64::X16)
1633 .addReg(AArch64::X17)
1634 .addReg(AArch64::X16)
1637 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1640void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1641 const llvm::MachineInstr &
MI) {
1642 unsigned Opcode =
MI.getOpcode();
1644 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1646 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1647 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1648 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1649 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1650 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1651 if (Opcode == AArch64::MOPSMemorySetPseudo)
1652 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1653 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1654 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1657 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1658 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1660 for (
auto Op :
Ops) {
1662 auto MCIB = MCInstBuilder(
Op);
1664 MCIB.addReg(
MI.getOperand(i++).getReg());
1665 MCIB.addReg(
MI.getOperand(i++).getReg());
1667 MCIB.addReg(
MI.getOperand(i++).getReg());
1669 MCIB.addReg(
MI.getOperand(i++).getReg());
1670 MCIB.addReg(
MI.getOperand(i++).getReg());
1671 MCIB.addReg(
MI.getOperand(i++).getReg());
1673 EmitToStreamer(OutStreamer, MCIB);
1677void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1678 const MachineInstr &
MI) {
1679 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1682 MCSymbol *MILabel = Ctx.createTempSymbol();
1686 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1689 const MachineBasicBlock &
MBB = *
MI.getParent();
1692 while (NumNOPBytes > 0) {
1693 if (MII ==
MBB.
end() || MII->isCall() ||
1694 MII->getOpcode() == AArch64::DBG_VALUE ||
1695 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1696 MII->getOpcode() == TargetOpcode::STACKMAP)
1703 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1704 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1709void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1710 const MachineInstr &
MI) {
1712 MCSymbol *MILabel = Ctx.createTempSymbol();
1716 PatchPointOpers Opers(&
MI);
1718 int64_t CallTarget = Opers.getCallTarget().getImm();
1719 unsigned EncodedBytes = 0;
1721 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1722 "High 16 bits of call target should be zero.");
1723 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1726 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1727 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1728 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1729 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1732 unsigned NumBytes = Opers.getNumPatchBytes();
1733 assert(NumBytes >= EncodedBytes &&
1734 "Patchpoint can't request size less than the length of a call.");
1735 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1736 "Invalid number of NOP bytes requested!");
1737 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1738 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1741void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1742 const MachineInstr &
MI) {
1743 StatepointOpers SOpers(&
MI);
1744 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1745 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1746 for (
unsigned i = 0; i < PatchBytes; i += 4)
1747 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1750 const MachineOperand &CallTarget = SOpers.getCallTarget();
1751 MCOperand CallTargetMCOp;
1752 unsigned CallOpcode;
1753 switch (CallTarget.
getType()) {
1756 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1757 CallOpcode = AArch64::BL;
1761 CallOpcode = AArch64::BL;
1765 CallOpcode = AArch64::BLR;
1772 EmitToStreamer(OutStreamer,
1773 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1777 MCSymbol *MILabel = Ctx.createTempSymbol();
1782void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1791 unsigned OperandsBeginIdx = 4;
1794 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1801 MI.setOpcode(Opcode);
1806 for (
const MachineOperand &MO :
1809 lowerOperand(MO, Dest);
1810 MI.addOperand(Dest);
1818 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1820 .addReg(AArch64::XZR)
1825void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1826 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1827 EmitToStreamer(*OutStreamer,
1828 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1834void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1835 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1836 EmitToStreamer(*OutStreamer,
1837 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1844void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1845 Register DestReg =
MI.getOperand(0).getReg();
1846 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->
isNeonAvailable()) {
1847 if (STI->hasZeroCycleZeroingFPR64()) {
1850 if (AArch64::FPR16RegClass.
contains(DestReg))
1851 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1852 &AArch64::FPR64RegClass);
1853 else if (AArch64::FPR32RegClass.
contains(DestReg))
1854 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1855 &AArch64::FPR64RegClass);
1863 EmitToStreamer(*OutStreamer, MOVI);
1864 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1867 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1868 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1869 &AArch64::FPR128RegClass);
1870 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1871 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1872 &AArch64::FPR128RegClass);
1875 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1876 &AArch64::FPR128RegClass);
1883 EmitToStreamer(*OutStreamer, MOVI);
1885 emitFMov0AsFMov(
MI, DestReg);
1888 emitFMov0AsFMov(
MI, DestReg);
1892void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1895 switch (
MI.getOpcode()) {
1898 case AArch64::FMOVH0:
1899 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1900 if (!STI->hasFullFP16())
1901 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1905 case AArch64::FMOVS0:
1910 case AArch64::FMOVD0:
1916 EmitToStreamer(*OutStreamer, FMov);
1919Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc,
1922 bool MayUseAddrAsScratch) {
1923 assert(ScratchReg == AArch64::X16 || ScratchReg == AArch64::X17 ||
1926 if (AddrDisc == AArch64::NoRegister)
1927 AddrDisc = AArch64::XZR;
1935 if (AddrDisc == AArch64::XZR) {
1936 emitMOVZ(ScratchReg, Disc, 0);
1943 assert(MayUseAddrAsScratch || ScratchReg != AddrDisc);
1944 bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17 ||
1946 if (MayUseAddrAsScratch && AddrDiscIsSafe)
1947 ScratchReg = AddrDisc;
1949 emitMovXReg(ScratchReg, AddrDisc);
1951 emitMOVK(ScratchReg, Disc, 48);
1965void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
1997 if (Method == AuthCheckMethod::None)
1999 if (Method == AuthCheckMethod::DummyLoad) {
2000 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2004 assert(!OnFailure &&
"DummyLoad always traps on error");
2008 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2009 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2011 emitMovXReg(ScratchReg, TestedReg);
2013 if (Method == AuthCheckMethod::XPAC) {
2017 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2022 assert(TestedReg == AArch64::LR &&
2023 "XPACHint mode is only compatible with checking the LR register");
2025 "XPACHint mode is only compatible with I-keys");
2026 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2030 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2031 .addReg(AArch64::XZR)
2038 MCInstBuilder(AArch64::Bcc)
2041 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2043 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2050 MCInstBuilder(AArch64::TBZX)
2061 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2075 case AuthCheckMethod::XPACHint:
2078 case AuthCheckMethod::XPAC:
2080 emitMovXReg(TestedReg, ScratchReg);
2087 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2092 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2104void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2109 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2116 "Neither x16 nor x17 is available as a scratch register");
2119 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2123bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2129 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2132 MCSymbol *Dot = OutContext.createTempSymbol();
2137 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2143void AArch64AsmPrinter::emitPtrauthAuthResign(
2145 const MachineOperand *AUTAddrDisc,
Register Scratch,
2146 std::optional<AArch64PACKey::ID> PACKey, uint64_t PACDisc,
2148 const bool IsAUTPAC = PACKey.has_value();
2162 bool ShouldCheck =
true;
2164 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
2169 ShouldCheck = ShouldTrap =
false;
2176 ShouldCheck = ShouldTrap =
false;
2183 ShouldCheck = ShouldTrap =
true;
2189 Register AUTDiscReg = emitPtrauthDiscriminator(
2190 AUTDisc, AUTAddrDisc->
getReg(), Scratch, AUTAddrDisc->
isKill());
2191 bool AUTZero = AUTDiscReg == AArch64::XZR;
2194 if (!emitDeactivationSymbolRelocation(DS)) {
2203 EmitToStreamer(*OutStreamer, AUTInst);
2207 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2213 if (IsAUTPAC && !ShouldTrap)
2214 EndSym = createTempSymbol(
"resign_end_");
2216 emitPtrauthCheckAuthenticatedValue(
2217 AUTVal, Scratch, AUTKey, AArch64PAuth::AuthCheckMethod::XPAC, EndSym);
2229 emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
2230 bool PACZero = PACDiscReg == AArch64::XZR;
2241 EmitToStreamer(*OutStreamer, PACInst);
2248void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2251 uint64_t Disc =
MI->getOperand(3).getImm();
2252 Register AddrDisc =
MI->getOperand(4).getReg();
2253 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2257 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2258 assert(ScratchReg != AddrDisc &&
2259 "Neither X16 nor X17 is available as a scratch register");
2263 Register DiscReg = emitPtrauthDiscriminator(
2264 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2265 bool IsZeroDisc = DiscReg == AArch64::XZR;
2268 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2279 EmitToStreamer(*OutStreamer, PACInst);
2282void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2283 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2284 unsigned BrTarget =
MI->getOperand(0).getReg();
2288 "Invalid auth call key");
2290 uint64_t Disc =
MI->getOperand(2).getImm();
2293 unsigned AddrDisc =
MI->getOperand(3).getReg();
2299 if (BrTarget == AddrDisc)
2316 bool AddrDiscIsImplicitDef =
2317 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2318 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2319 AddrDiscIsImplicitDef);
2320 bool IsZeroDisc = DiscReg == AArch64::XZR;
2325 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
2327 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
2330 Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
2332 Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
2340 EmitToStreamer(*OutStreamer, BRInst);
2343void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2346 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2347 const bool IsNeg = Addend < 0;
2349 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2352 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2355 .addImm((AbsOffset >> BitPos) & 0xfff)
2359 const uint64_t UAddend = Addend;
2360 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2362 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2364 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2365 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2366 uint64_t Shifted = UAddend >> BitPos;
2368 return Shifted != 0;
2369 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2370 if (((Shifted >>
I) & 0xffff) != 0xffff)
2374 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2375 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2377 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2386void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2387 MCRegister Tmp,
bool DSOLocal,
2388 const MCSubtargetInfo &STI) {
2394 MCInstBuilder(AArch64::ADRP)
2398 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2408 MCInstBuilder(AArch64::ADRP)
2413 MCInstBuilder(AArch64::LDRXui)
2426 if (TT.isOSGlibc() || TT.isMusl())
2438 if (!TT.isOSBinFormatELF())
2499const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2501 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2502 const Triple &
TT = TM.getTargetTriple();
2514 std::unique_ptr<MCSubtargetInfo> STI(
2515 TM.getTarget().createMCSubtargetInfo(TT,
"",
""));
2516 assert(STI &&
"Unable to create subtarget info");
2517 this->STI =
static_cast<const AArch64Subtarget *
>(&*STI);
2523 const MCSymbolELF *Group =
2538 .addReg(AArch64::X0)
2543 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2545 if (HasAddressDiversity) {
2550 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2554 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2556 "' out of range [0, 0xFFFF]");
2558 emitMOVZ(AArch64::X1, Disc, 0);
2565 auto *PrePACInstExpr =
2577 const MCSymbolRefExpr *EmuPACRef =
2579 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2586 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2594AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2595 MCContext &Ctx = OutContext;
2600 getDataLayout(),
Offset,
true);
2618 const MCExpr *DSExpr =
nullptr;
2630 "' out of range [0, " +
2638 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2640 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2645 "' out of range [0, 0xFFFF]");
2651 "expressions on this target");
2658void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2659 unsigned DstReg =
MI.getOperand(0).getReg();
2660 const MachineOperand &GAOp =
MI.getOperand(1);
2661 const uint64_t KeyC =
MI.getOperand(2).getImm();
2663 "key is out of range [0, AArch64PACKey::LAST]");
2665 const uint64_t Disc =
MI.getOperand(3).getImm();
2667 "constant discriminator is out of range [0, 0xffff]");
2676 if (TM.getTargetTriple().isOSBinFormatELF()) {
2678 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2681 "non-zero offset for $auth_ptr$ stub slots is not supported");
2683 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2685 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2686 "LOADauthptrstatic is implemented only for MachO/ELF");
2688 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2689 getObjFileLowering());
2692 "non-zero offset for $auth_ptr$ stub slots is not supported");
2694 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2697 MachineOperand StubMOHi =
2701 MCOperand StubMCHi, StubMCLo;
2708 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2710 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2716void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2717 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2718 const bool IsELFSignedGOT =
MI.getParent()
2720 ->getInfo<AArch64FunctionInfo>()
2721 ->hasELFSignedGOT();
2722 MachineOperand GAOp =
MI.getOperand(0);
2723 const uint64_t KeyC =
MI.getOperand(1).getImm();
2725 "key is out of range [0, AArch64PACKey::LAST]");
2727 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2728 const uint64_t Disc =
MI.getOperand(3).getImm();
2730 "constant discriminator is out of range [0, 0xffff]");
2777 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2778 MCOperand GAMCHi, GAMCLo;
2791 MCInstBuilder(AArch64::ADRP)
2792 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2796 if (IsELFSignedGOT) {
2797 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2798 .addReg(AArch64::X17)
2799 .addReg(AArch64::X17)
2803 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2804 .addReg(AArch64::X16)
2805 .addReg(AArch64::X17)
2814 EmitToStreamer(MCInstBuilder(AuthOpcode)
2815 .addReg(AArch64::X16)
2816 .addReg(AArch64::X16)
2817 .addReg(AArch64::X17));
2819 if (!STI->hasFPAC()) {
2823 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2824 AArch64PAuth::AuthCheckMethod::XPAC);
2827 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2828 .addReg(AArch64::X16)
2829 .addReg(AArch64::X16)
2833 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2834 .addReg(AArch64::X16)
2835 .addReg(AArch64::X16)
2840 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2841 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2844 .addReg(AArch64::X16)
2845 .addReg(AArch64::X16);
2846 if (DiscReg != AArch64::XZR)
2847 MIB.addReg(DiscReg);
2848 EmitToStreamer(MIB);
2851void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2853 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2854 const MachineOperand &GAMO =
MI.getOperand(1);
2861 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2862 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2863 .addReg(AuthResultReg)
2864 .addReg(AArch64::X17)
2867 MachineOperand GAHiOp(GAMO);
2868 MachineOperand GALoOp(GAMO);
2872 MCOperand GAMCHi, GAMCLo;
2877 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2879 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2880 .addReg(AArch64::X17)
2881 .addReg(AArch64::X17)
2885 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2886 .addReg(AuthResultReg)
2887 .addReg(AArch64::X17)
2894 UndefWeakSym = createTempSymbol(
"undef_weak");
2896 MCInstBuilder(AArch64::CBZX)
2897 .addReg(AuthResultReg)
2905 EmitToStreamer(MCInstBuilder(AuthOpcode)
2906 .addReg(AuthResultReg)
2907 .addReg(AuthResultReg)
2908 .addReg(AArch64::X17));
2913 if (!STI->hasFPAC()) {
2917 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2918 AArch64PAuth::AuthCheckMethod::XPAC);
2920 emitMovXReg(DstReg, AuthResultReg);
2925AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2929 if (std::optional<uint16_t> BADisc =
2930 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2937void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
2941 switch (
MI->getOpcode()) {
2944 case AArch64::CBBAssertExt:
2948 case AArch64::CBHAssertExt:
2952 case AArch64::CBWPrr:
2955 case AArch64::CBXPrr:
2958 case AArch64::CBWPri:
2962 case AArch64::CBXPri:
2970 bool NeedsRegSwap =
false;
2971 bool NeedsImmDec =
false;
2972 bool NeedsImmInc =
false;
2974#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
2976 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
2978 ? AArch64::CBB##RegCond##Wrr \
2979 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
2980 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
2981 : AArch64::CB##RegCond##Xrr))))
2997 NeedsImmDec = IsImm;
3001 NeedsRegSwap = !IsImm;
3008 NeedsRegSwap = !IsImm;
3009 NeedsImmInc = IsImm;
3013 NeedsImmDec = IsImm;
3017 NeedsRegSwap = !IsImm;
3024 NeedsRegSwap = !IsImm;
3025 NeedsImmInc = IsImm;
3033 MCOperand Lhs, Rhs, Trgt;
3034 lowerOperand(
MI->getOperand(1), Lhs);
3035 lowerOperand(
MI->getOperand(2), Rhs);
3036 lowerOperand(
MI->getOperand(3), Trgt);
3040 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3041 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3044 }
else if (NeedsImmDec) {
3048 }
else if (NeedsImmInc) {
3058 "CB immediate operand out-of-bounds");
3061 EmitToStreamer(*OutStreamer, Inst);
3066#include "AArch64GenMCPseudoLowering.inc"
3068void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3075void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3076 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3081 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3086 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3087 EmitToStreamer(*OutStreamer, OutInst);
3091 if (
MI->getOpcode() == AArch64::ADRP) {
3092 for (
auto &Opd :
MI->operands()) {
3093 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3094 "swift_async_extendedFramePointerFlags") {
3095 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3102 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3104 LOHInstToLabel[
MI] = LOHLabel;
3108 AArch64TargetStreamer *TS =
3111 switch (
MI->getOpcode()) {
3114 "Unhandled tail call instruction");
3116 case AArch64::HINT: {
3121 if (CurrentPatchableFunctionEntrySym &&
3122 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3123 MI == &MF->front().front()) {
3124 int64_t
Imm =
MI->getOperand(0).getImm();
3125 if ((Imm & 32) && (Imm & 6)) {
3127 MCInstLowering.
Lower(
MI, Inst);
3128 EmitToStreamer(*OutStreamer, Inst);
3129 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3130 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3136 case AArch64::MOVMCSym: {
3137 Register DestReg =
MI->getOperand(0).getReg();
3138 const MachineOperand &MO_Sym =
MI->getOperand(1);
3139 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3140 MCOperand Hi_MCSym, Lo_MCSym;
3153 EmitToStreamer(*OutStreamer, MovZ);
3161 EmitToStreamer(*OutStreamer, MovK);
3164 case AArch64::MOVIv2d_ns:
3172 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3173 MI->getOperand(1).getImm() == 0) {
3175 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3178 EmitToStreamer(*OutStreamer, TmpInst);
3183 case AArch64::DBG_VALUE:
3184 case AArch64::DBG_VALUE_LIST:
3186 SmallString<128> TmpStr;
3187 raw_svector_ostream OS(TmpStr);
3188 PrintDebugValueComment(
MI, OS);
3193 case AArch64::EMITBKEY: {
3195 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3196 ExceptionHandlingType != ExceptionHandling::ARM)
3199 if (getFunctionCFISectionType(*MF) == CFISection::None)
3206 case AArch64::EMITMTETAGGED: {
3208 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3209 ExceptionHandlingType != ExceptionHandling::ARM)
3212 if (getFunctionCFISectionType(*MF) != CFISection::None)
3217 case AArch64::AUTx16x17:
3218 emitPtrauthAuthResign(
3220 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3221 std::nullopt, 0, 0,
MI->getDeactivationSymbol());
3224 case AArch64::AUTxMxN:
3225 emitPtrauthAuthResign(
MI->getOperand(0).getReg(),
3227 MI->getOperand(4).getImm(), &
MI->getOperand(5),
3228 MI->getOperand(1).getReg(), std::nullopt, 0, 0,
3229 MI->getDeactivationSymbol());
3232 case AArch64::AUTPAC:
3233 emitPtrauthAuthResign(
3235 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3237 MI->getOperand(4).getImm(),
MI->getOperand(5).getReg(),
3238 MI->getDeactivationSymbol());
3242 emitPtrauthSign(
MI);
3245 case AArch64::LOADauthptrstatic:
3246 LowerLOADauthptrstatic(*
MI);
3249 case AArch64::LOADgotPAC:
3250 case AArch64::MOVaddrPAC:
3251 LowerMOVaddrPAC(*
MI);
3254 case AArch64::LOADgotAUTH:
3255 LowerLOADgotAUTH(*
MI);
3260 emitPtrauthBranch(
MI);
3266 case AArch64::AUTH_TCRETURN:
3267 case AArch64::AUTH_TCRETURN_BTI: {
3269 const uint64_t
Key =
MI->getOperand(2).getImm();
3271 "Invalid auth key for tail-call return");
3273 const uint64_t Disc =
MI->getOperand(3).getImm();
3276 Register AddrDisc =
MI->getOperand(4).getReg();
3278 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3280 emitPtrauthTailCallHardening(
MI);
3283 if (Callee == AddrDisc)
3290 bool AddrDiscIsImplicitDef =
3291 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3292 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3293 AddrDiscIsImplicitDef);
3295 const bool IsZero = DiscReg == AArch64::XZR;
3296 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
3297 {AArch64::BRAB, AArch64::BRABZ}};
3304 EmitToStreamer(*OutStreamer, TmpInst);
3308 case AArch64::TCRETURNri:
3309 case AArch64::TCRETURNrix16x17:
3310 case AArch64::TCRETURNrix17:
3311 case AArch64::TCRETURNrinotx16:
3312 case AArch64::TCRETURNriALL: {
3313 emitPtrauthTailCallHardening(
MI);
3315 recordIfImportCall(
MI);
3319 EmitToStreamer(*OutStreamer, TmpInst);
3322 case AArch64::TCRETURNdi: {
3323 emitPtrauthTailCallHardening(
MI);
3327 recordIfImportCall(
MI);
3331 EmitToStreamer(*OutStreamer, TmpInst);
3334 case AArch64::SpeculationBarrierISBDSBEndBB: {
3339 EmitToStreamer(*OutStreamer, TmpInstDSB);
3343 EmitToStreamer(*OutStreamer, TmpInstISB);
3346 case AArch64::SpeculationBarrierSBEndBB: {
3350 EmitToStreamer(*OutStreamer, TmpInstSB);
3353 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3360 const MachineOperand &MO_Sym =
MI->getOperand(0);
3361 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3362 MCOperand SymTLSDescLo12, SymTLSDesc;
3365 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3372 EmitToStreamer(*OutStreamer, Adrp);
3380 EmitToStreamer(*OutStreamer, Ldr);
3383 Add.setOpcode(AArch64::ADDXri);
3386 Add.addOperand(SymTLSDescLo12);
3388 EmitToStreamer(*OutStreamer,
Add);
3397 EmitToStreamer(*OutStreamer, Blraa);
3401 case AArch64::TLSDESC_CALLSEQ: {
3409 const MachineOperand &MO_Sym =
MI->getOperand(0);
3410 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3411 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3415 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3422 EmitToStreamer(*OutStreamer, Adrp);
3425 if (STI->isTargetILP32()) {
3435 EmitToStreamer(*OutStreamer, Ldr);
3438 if (STI->isTargetILP32()) {
3439 Add.setOpcode(AArch64::ADDWri);
3443 Add.setOpcode(AArch64::ADDXri);
3447 Add.addOperand(SymTLSDescLo12);
3449 EmitToStreamer(*OutStreamer,
Add);
3454 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3456 EmitToStreamer(*OutStreamer, TLSDescCall);
3464 EmitToStreamer(*OutStreamer, Blr);
3469 case AArch64::JumpTableDest32:
3470 case AArch64::JumpTableDest16:
3471 case AArch64::JumpTableDest8:
3472 LowerJumpTableDest(*OutStreamer, *
MI);
3475 case AArch64::BR_JumpTable:
3476 LowerHardenedBRJumpTable(*
MI);
3479 case AArch64::FMOVH0:
3480 case AArch64::FMOVS0:
3481 case AArch64::FMOVD0:
3485 case AArch64::MOPSMemoryCopyPseudo:
3486 case AArch64::MOPSMemoryMovePseudo:
3487 case AArch64::MOPSMemorySetPseudo:
3488 case AArch64::MOPSMemorySetTaggingPseudo:
3489 LowerMOPS(*OutStreamer, *
MI);
3492 case TargetOpcode::STACKMAP:
3493 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3495 case TargetOpcode::PATCHPOINT:
3496 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3498 case TargetOpcode::STATEPOINT:
3499 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3501 case TargetOpcode::FAULTING_OP:
3502 return LowerFAULTING_OP(*
MI);
3504 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3505 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3508 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3509 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3512 case TargetOpcode::PATCHABLE_TAIL_CALL:
3513 LowerPATCHABLE_TAIL_CALL(*
MI);
3515 case TargetOpcode::PATCHABLE_EVENT_CALL:
3516 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3517 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3518 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3520 case AArch64::KCFI_CHECK:
3521 LowerKCFI_CHECK(*
MI);
3524 case AArch64::HWASAN_CHECK_MEMACCESS:
3525 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3526 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3527 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3528 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3531 case AArch64::SEH_StackAlloc:
3535 case AArch64::SEH_SaveFPLR:
3539 case AArch64::SEH_SaveFPLR_X:
3540 assert(
MI->getOperand(0).getImm() < 0 &&
3541 "Pre increment SEH opcode must have a negative offset");
3545 case AArch64::SEH_SaveReg:
3547 MI->getOperand(1).getImm());
3550 case AArch64::SEH_SaveReg_X:
3551 assert(
MI->getOperand(1).getImm() < 0 &&
3552 "Pre increment SEH opcode must have a negative offset");
3554 -
MI->getOperand(1).getImm());
3557 case AArch64::SEH_SaveRegP:
3558 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3559 MI->getOperand(0).getImm() <= 28) {
3560 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3561 "Register paired with LR must be odd");
3563 MI->getOperand(2).getImm());
3566 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3567 "Non-consecutive registers not allowed for save_regp");
3569 MI->getOperand(2).getImm());
3572 case AArch64::SEH_SaveRegP_X:
3573 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3574 "Non-consecutive registers not allowed for save_regp_x");
3575 assert(
MI->getOperand(2).getImm() < 0 &&
3576 "Pre increment SEH opcode must have a negative offset");
3578 -
MI->getOperand(2).getImm());
3581 case AArch64::SEH_SaveFReg:
3583 MI->getOperand(1).getImm());
3586 case AArch64::SEH_SaveFReg_X:
3587 assert(
MI->getOperand(1).getImm() < 0 &&
3588 "Pre increment SEH opcode must have a negative offset");
3590 -
MI->getOperand(1).getImm());
3593 case AArch64::SEH_SaveFRegP:
3594 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3595 "Non-consecutive registers not allowed for save_regp");
3597 MI->getOperand(2).getImm());
3600 case AArch64::SEH_SaveFRegP_X:
3601 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3602 "Non-consecutive registers not allowed for save_regp_x");
3603 assert(
MI->getOperand(2).getImm() < 0 &&
3604 "Pre increment SEH opcode must have a negative offset");
3606 -
MI->getOperand(2).getImm());
3609 case AArch64::SEH_SetFP:
3613 case AArch64::SEH_AddFP:
3617 case AArch64::SEH_Nop:
3621 case AArch64::SEH_PrologEnd:
3625 case AArch64::SEH_EpilogStart:
3629 case AArch64::SEH_EpilogEnd:
3633 case AArch64::SEH_PACSignLR:
3637 case AArch64::SEH_SaveAnyRegI:
3638 assert(
MI->getOperand(1).getImm() <= 1008 &&
3639 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3641 MI->getOperand(1).getImm());
3644 case AArch64::SEH_SaveAnyRegIP:
3645 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3646 "Non-consecutive registers not allowed for save_any_reg");
3647 assert(
MI->getOperand(2).getImm() <= 1008 &&
3648 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3650 MI->getOperand(2).getImm());
3653 case AArch64::SEH_SaveAnyRegQP:
3654 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3655 "Non-consecutive registers not allowed for save_any_reg");
3656 assert(
MI->getOperand(2).getImm() >= 0 &&
3657 "SaveAnyRegQP SEH opcode offset must be non-negative");
3658 assert(
MI->getOperand(2).getImm() <= 1008 &&
3659 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3661 MI->getOperand(2).getImm());
3664 case AArch64::SEH_SaveAnyRegQPX:
3665 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3666 "Non-consecutive registers not allowed for save_any_reg");
3667 assert(
MI->getOperand(2).getImm() < 0 &&
3668 "SaveAnyRegQPX SEH opcode offset must be negative");
3669 assert(
MI->getOperand(2).getImm() >= -1008 &&
3670 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3672 -
MI->getOperand(2).getImm());
3675 case AArch64::SEH_AllocZ:
3676 assert(
MI->getOperand(0).getImm() >= 0 &&
3677 "AllocZ SEH opcode offset must be non-negative");
3678 assert(
MI->getOperand(0).getImm() <= 255 &&
3679 "AllocZ SEH opcode offset must fit into 8 bits");
3683 case AArch64::SEH_SaveZReg:
3684 assert(
MI->getOperand(1).getImm() >= 0 &&
3685 "SaveZReg SEH opcode offset must be non-negative");
3686 assert(
MI->getOperand(1).getImm() <= 255 &&
3687 "SaveZReg SEH opcode offset must fit into 8 bits");
3689 MI->getOperand(1).getImm());
3692 case AArch64::SEH_SavePReg:
3693 assert(
MI->getOperand(1).getImm() >= 0 &&
3694 "SavePReg SEH opcode offset must be non-negative");
3695 assert(
MI->getOperand(1).getImm() <= 255 &&
3696 "SavePReg SEH opcode offset must fit into 8 bits");
3698 MI->getOperand(1).getImm());
3703 recordIfImportCall(
MI);
3705 MCInstLowering.
Lower(
MI, TmpInst);
3706 EmitToStreamer(*OutStreamer, TmpInst);
3709 case AArch64::CBWPri:
3710 case AArch64::CBXPri:
3711 case AArch64::CBBAssertExt:
3712 case AArch64::CBHAssertExt:
3713 case AArch64::CBWPrr:
3714 case AArch64::CBXPrr:
3715 emitCBPseudoExpansion(
MI);
3719 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3724 MCInstLowering.
Lower(
MI, TmpInst);
3725 EmitToStreamer(*OutStreamer, TmpInst);
3728void AArch64AsmPrinter::recordIfImportCall(
3729 const llvm::MachineInstr *BranchInst) {
3730 if (!EnableImportCallOptimization)
3734 if (GV && GV->hasDLLImportStorageClass()) {
3735 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3740 .push_back({CallSiteSymbol, CalledSymbol});
3744void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3745 MCSymbol *LazyPointer) {
3762 EmitToStreamer(Adrp);
3770 MCOperand SymPageOff;
3777 EmitToStreamer(Ldr);
3780 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3781 .addReg(AArch64::X16)
3782 .addReg(AArch64::X16)
3785 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3787 .addReg(AArch64::X16));
3790void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3791 const GlobalIFunc &GI,
3792 MCSymbol *LazyPointer) {
3824 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3825 .addReg(AArch64::SP)
3826 .addReg(AArch64::FP)
3827 .addReg(AArch64::LR)
3828 .addReg(AArch64::SP)
3831 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3832 .addReg(AArch64::FP)
3833 .addReg(AArch64::SP)
3837 for (
int I = 0;
I != 4; ++
I)
3838 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3839 .addReg(AArch64::SP)
3840 .addReg(AArch64::X1 + 2 *
I)
3841 .addReg(AArch64::X0 + 2 *
I)
3842 .addReg(AArch64::SP)
3845 for (
int I = 0;
I != 4; ++
I)
3846 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3847 .addReg(AArch64::SP)
3848 .addReg(AArch64::D1 + 2 *
I)
3849 .addReg(AArch64::D0 + 2 *
I)
3850 .addReg(AArch64::SP)
3854 MCInstBuilder(AArch64::BL)
3867 EmitToStreamer(Adrp);
3875 MCOperand SymPageOff;
3882 EmitToStreamer(Ldr);
3885 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3886 .addReg(AArch64::X0)
3887 .addReg(AArch64::X16)
3890 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3891 .addReg(AArch64::X16)
3892 .addReg(AArch64::X0)
3896 for (
int I = 3;
I != -1; --
I)
3897 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3898 .addReg(AArch64::SP)
3899 .addReg(AArch64::D1 + 2 *
I)
3900 .addReg(AArch64::D0 + 2 *
I)
3901 .addReg(AArch64::SP)
3904 for (
int I = 3;
I != -1; --
I)
3905 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3906 .addReg(AArch64::SP)
3907 .addReg(AArch64::X1 + 2 *
I)
3908 .addReg(AArch64::X0 + 2 *
I)
3909 .addReg(AArch64::SP)
3912 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3913 .addReg(AArch64::SP)
3914 .addReg(AArch64::FP)
3915 .addReg(AArch64::LR)
3916 .addReg(AArch64::SP)
3919 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3921 .addReg(AArch64::X16));
3924const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
3925 const Constant *BaseCV,
3935char AArch64AsmPrinter::ID = 0;
3938 "AArch64 Assembly Printer",
false,
false)
3942LLVMInitializeAArch64AsmPrinter() {
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 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.
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)
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,...