80 cl::desc(
"Check pointer authentication auth/resign failures"),
83#define DEBUG_TYPE "asm-printer"
91 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
93 unsigned InstsEmitted;
95 bool EnableImportCallOptimization =
false;
97 SectionToImportedFunctionCalls;
102 AArch64AsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
104 MCInstLowering(OutContext, *
this), FM(*
this) {}
106 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
118 void emitStartOfAsmFile(
Module &M)
override;
123 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
124 const MCSymbol *BranchLabel)
const override;
126 void emitFunctionEntryLabel()
override;
147 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
149 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
150 HwasanMemaccessTuple;
151 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
154 void emitHwasanMemaccessSymbols(
Module &M);
161 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
169 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
176 std::optional<AArch64PACKey::ID> PACKey,
201 bool MayUseAddrAsScratch =
false);
220 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
227 void EmitToStreamer(
const MCInst &Inst) {
228 EmitToStreamer(*OutStreamer, Inst);
233 void emitFunctionHeaderComment()
override;
241 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
242 PSI = &PSIW->getPSI();
244 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
245 SDPI = &SDPIW->getStaticDataProfileInfo();
250 SetupMachineFunction(MF);
252 if (STI->isTargetCOFF()) {
288 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
293 void emitFunctionBodyEnd()
override;
296 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
297 void emitEndOfAsmFile(
Module &M)
override;
312 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
314 MInstToMCSymbol LOHInstToLabel;
316 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
317 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
337void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
338 const Triple &
TT =
TM.getTargetTriple();
340 if (
TT.isOSBinFormatCOFF()) {
341 emitCOFFFeatureSymbol(M);
342 emitCOFFReplaceableFunctionData(M);
344 if (
M.getModuleFlag(
"import-call-optimization"))
345 EnableImportCallOptimization =
true;
348 if (!
TT.isOSBinFormatELF())
353 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
356 unsigned BAFlags = 0;
357 unsigned GNUFlags = 0;
359 M.getModuleFlag(
"branch-target-enforcement"))) {
360 if (!BTE->isZero()) {
361 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
367 M.getModuleFlag(
"guarded-control-stack"))) {
368 if (!GCS->isZero()) {
369 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
375 M.getModuleFlag(
"sign-return-address"))) {
376 if (!Sign->isZero()) {
377 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
382 uint64_t PAuthABIPlatform = -1;
384 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
385 PAuthABIPlatform = PAP->getZExtValue();
388 uint64_t PAuthABIVersion = -1;
390 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
391 PAuthABIVersion = PAV->getZExtValue();
395 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
397 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
400void AArch64AsmPrinter::emitFunctionHeaderComment() {
401 const AArch64FunctionInfo *FI = MF->getInfo<AArch64FunctionInfo>();
403 if (OutlinerString != std::nullopt)
404 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
407void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
410 if (
F.hasFnAttribute(
"patchable-function-entry")) {
412 if (
F.getFnAttribute(
"patchable-function-entry")
414 .getAsInteger(10, Num))
420 emitSled(
MI, SledKind::FUNCTION_ENTER);
423void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
424 emitSled(
MI, SledKind::FUNCTION_EXIT);
427void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
428 emitSled(
MI, SledKind::TAIL_CALL);
431void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
432 static const int8_t NoopsInSledCount = 7;
453 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
454 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
455 OutStreamer->emitLabel(CurSled);
456 auto Target = OutContext.createTempSymbol();
461 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
463 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
464 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
466 OutStreamer->emitLabel(Target);
467 recordSled(CurSled,
MI, Kind, 2);
470void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
471 uint64_t PAuthABIPlatform,
472 uint64_t PAuthABIVersion,
473 AArch64TargetStreamer *TS) {
475 PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
476 PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
478 if (PAuthABIPlatform || PAuthABIVersion) {
482 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
483 AArch64BuildAttributes::SubsectionType::ULEB128);
487 PAuthABIPlatform,
"");
501 if (BTIValue || PACValue || GCSValue) {
505 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
506 AArch64BuildAttributes::SubsectionType::ULEB128);
534void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
536 auto &
O = *OutStreamer;
537 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
538 O.emitLabel(CurSled);
539 bool MachO =
TM.getTargetTriple().isOSBinFormatMachO();
541 OutContext.getOrCreateSymbol(
542 Twine(MachO ?
"_" :
"") +
543 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
546 O.AddComment(
"Begin XRay typed event");
547 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
548 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
554 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
558 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
559 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
560 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
561 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
562 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
566 O.AddComment(
"End XRay typed event");
567 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
574 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
576 O.AddComment(
"Begin XRay custom event");
577 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
578 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
584 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
585 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
586 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
587 O.AddComment(
"End XRay custom event");
588 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
595 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
599void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
601 assert(std::next(
MI.getIterator())->isCall() &&
602 "KCFI_CHECK not followed by a call instruction");
603 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
604 "KCFI_CHECK call target doesn't match call operand");
608 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
609 if (AddrReg == AArch64::XZR) {
613 emitMovXReg(AddrReg, AArch64::XZR);
619 for (
auto &
Reg : ScratchRegs) {
625 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
626 "Invalid scratch registers for KCFI_CHECK");
630 int64_t PrefixNops = 0;
633 .getFnAttribute(
"patchable-function-prefix")
635 .getAsInteger(10, PrefixNops);
638 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
639 .addReg(ScratchRegs[0])
641 .addImm(-(PrefixNops * 4 + 4)));
645 const int64_t
Type =
MI.getOperand(1).getImm();
646 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
647 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
650 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
651 .addReg(AArch64::WZR)
652 .addReg(ScratchRegs[0])
653 .addReg(ScratchRegs[1])
657 EmitToStreamer(*OutStreamer,
658 MCInstBuilder(AArch64::Bcc)
667 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
671 AddrIndex = AddrReg - AArch64::X0;
681 assert(AddrIndex < 31 && TypeIndex < 31);
683 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
684 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
685 OutStreamer->emitLabel(
Pass);
688void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
696 if (
Reg == AArch64::XZR)
700 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
702 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
703 uint32_t AccessInfo =
MI.getOperand(1).getImm();
705 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
707 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
708 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
710 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
711 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
714 if (!
TM.getTargetTriple().isOSBinFormatELF())
717 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
720 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
722 SymName +=
"_short_v2";
723 Sym = OutContext.getOrCreateSymbol(SymName);
726 EmitToStreamer(*OutStreamer,
727 MCInstBuilder(AArch64::BL)
731void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
732 if (HwasanMemaccessSymbols.empty())
735 const Triple &
TT =
TM.getTargetTriple();
737 std::unique_ptr<MCSubtargetInfo> STI(
738 TM.getTarget().createMCSubtargetInfo(TT,
"",
""));
739 assert(STI &&
"Unable to create subtarget info");
740 this->STI =
static_cast<const AArch64Subtarget *
>(&*STI);
743 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
745 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
747 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
749 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
752 for (
auto &
P : HwasanMemaccessSymbols) {
753 unsigned Reg = std::get<0>(
P.first);
754 bool IsShort = std::get<1>(
P.first);
755 uint32_t AccessInfo = std::get<2>(
P.first);
756 bool IsFixedShadow = std::get<3>(
P.first);
757 uint64_t FixedShadowOffset = std::get<4>(
P.first);
758 const MCSymbolRefExpr *HwasanTagMismatchRef =
759 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
762 bool HasMatchAllTag =
764 uint8_t MatchAllTag =
771 OutStreamer->switchSection(OutContext.getELFSection(
777 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
778 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
779 OutStreamer->emitLabel(Sym);
781 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
782 .addReg(AArch64::X16)
792 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
793 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
794 .addReg(AArch64::W16)
795 .addReg(AArch64::X17)
796 .addReg(AArch64::X16)
800 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
801 .addReg(AArch64::W16)
802 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
803 .addReg(AArch64::X16)
808 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
809 .addReg(AArch64::XZR)
810 .addReg(AArch64::X16)
813 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
814 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
817 HandleMismatchOrPartialSym, OutContext)));
818 MCSymbol *ReturnSym = OutContext.createTempSymbol();
819 OutStreamer->emitLabel(ReturnSym);
820 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
821 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
823 if (HasMatchAllTag) {
824 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
825 .addReg(AArch64::X17)
829 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
830 .addReg(AArch64::XZR)
831 .addReg(AArch64::X17)
835 MCInstBuilder(AArch64::Bcc)
841 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
842 .addReg(AArch64::WZR)
843 .addReg(AArch64::W16)
846 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
848 MCInstBuilder(AArch64::Bcc)
852 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
853 .addReg(AArch64::X17)
857 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
858 .addReg(AArch64::X17)
859 .addReg(AArch64::X17)
862 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
863 .addReg(AArch64::WZR)
864 .addReg(AArch64::W16)
865 .addReg(AArch64::W17)
868 MCInstBuilder(AArch64::Bcc)
872 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
873 .addReg(AArch64::X16)
876 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
877 .addReg(AArch64::W16)
878 .addReg(AArch64::X16)
881 MCInstBuilder(AArch64::SUBSXrs)
882 .addReg(AArch64::XZR)
883 .addReg(AArch64::X16)
887 MCInstBuilder(AArch64::Bcc)
891 OutStreamer->emitLabel(HandleMismatchSym);
894 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
900 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
906 if (
Reg != AArch64::X0)
907 emitMovXReg(AArch64::X0,
Reg);
914 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
919 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
920 .addReg(AArch64::X16)
924 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
925 .addReg(AArch64::X16)
926 .addReg(AArch64::X16)
930 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
938 const MCExpr *StubAuthPtrRef) {
941 OutStreamer.
emitValue(StubAuthPtrRef, 8);
944void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
945 emitHwasanMemaccessSymbols(M);
947 const Triple &
TT =
TM.getTargetTriple();
948 if (
TT.isOSBinFormatMachO()) {
950 MachineModuleInfoMachO &MMIMacho =
951 MMI->getObjFileInfo<MachineModuleInfoMachO>();
955 if (!Stubs.empty()) {
957 OutStreamer->switchSection(
960 emitAlignment(
Align(8));
962 for (
const auto &Stub : Stubs)
965 OutStreamer->addBlankLine();
973 OutStreamer->emitSubsectionsViaSymbols();
976 if (
TT.isOSBinFormatELF()) {
978 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
982 if (!Stubs.empty()) {
983 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
985 emitAlignment(
Align(8));
987 for (
const auto &Stub : Stubs)
990 OutStreamer->addBlankLine();
1001 M.getModuleFlag(
"ptrauth-elf-got"));
1002 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1003 for (
const GlobalValue &GV :
M.global_values())
1005 !GV.getName().starts_with(
"llvm."))
1006 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1015 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1016 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1019 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1020 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1031 for (
auto &[Section, CallsToImportedFuncs] :
1032 SectionToImportedFunctionCalls) {
1034 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1035 OutStreamer->emitInt32(SectionSize);
1036 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1037 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1039 OutStreamer->emitInt32(0x13);
1040 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1041 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1047void AArch64AsmPrinter::emitLOHs() {
1051 for (
const MachineInstr *
MI :
D.getArgs()) {
1052 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1053 assert(LabelIt != LOHInstToLabel.end() &&
1054 "Label hasn't been inserted for LOH related instruction");
1057 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1062void AArch64AsmPrinter::emitFunctionBodyEnd() {
1068MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1072 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1073 return OutContext.getOrCreateSymbol(
1074 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1075 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1080void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1082 const MachineOperand &MO =
MI->getOperand(OpNum);
1098 PrintSymbolOperand(MO, O);
1109bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1133bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1134 const TargetRegisterClass *RC,
1135 unsigned AltName, raw_ostream &O) {
1136 assert(MO.
isReg() &&
"Should only get here with a register!");
1146bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1147 const char *ExtraCode, raw_ostream &O) {
1148 const MachineOperand &MO =
MI->getOperand(OpNum);
1155 if (ExtraCode && ExtraCode[0]) {
1156 if (ExtraCode[1] != 0)
1159 switch (ExtraCode[0]) {
1167 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1180 const TargetRegisterClass *RC;
1181 switch (ExtraCode[0]) {
1183 RC = &AArch64::FPR8RegClass;
1186 RC = &AArch64::FPR16RegClass;
1189 RC = &AArch64::FPR32RegClass;
1192 RC = &AArch64::FPR64RegClass;
1195 RC = &AArch64::FPR128RegClass;
1198 RC = &AArch64::ZPRRegClass;
1203 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1224 unsigned AltName = AArch64::NoRegAltName;
1225 const TargetRegisterClass *RegClass;
1227 RegClass = &AArch64::ZPRRegClass;
1229 RegClass = &AArch64::PPRRegClass;
1231 RegClass = &AArch64::PNRRegClass;
1233 RegClass = &AArch64::FPR128RegClass;
1234 AltName = AArch64::vreg;
1238 return printAsmRegInClass(MO, RegClass, AltName, O);
1245bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1247 const char *ExtraCode,
1249 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1252 const MachineOperand &MO =
MI->getOperand(OpNum);
1253 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1258void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1260 unsigned NOps =
MI->getNumOperands();
1262 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1264 OS <<
MI->getDebugVariable()->getName();
1267 assert(
MI->isIndirectDebugValue());
1269 for (
unsigned I = 0,
E = std::distance(
MI->debug_operands().begin(),
1270 MI->debug_operands().end());
1281void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1282 ArrayRef<unsigned> JumpTableIndices) {
1284 if (JumpTableIndices.
empty())
1286 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1287 const auto &
F = MF->getFunction();
1290 MCSection *ReadOnlySec =
nullptr;
1291 if (
TM.Options.EnableStaticDataPartitioning) {
1297 OutStreamer->switchSection(ReadOnlySec);
1299 auto AFI = MF->getInfo<AArch64FunctionInfo>();
1300 for (
unsigned JTI : JumpTableIndices) {
1301 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1304 if (JTBBs.empty())
continue;
1306 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1308 OutStreamer->emitLabel(GetJTISymbol(JTI));
1313 for (
auto *JTBB : JTBBs) {
1314 const MCExpr *
Value =
1333AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1334 const MachineInstr *BranchInstr,
1335 const MCSymbol *BranchLabel)
const {
1336 const auto AFI = MF->getInfo<AArch64FunctionInfo>();
1339 switch (AFI->getJumpTableEntrySize(JTI)) {
1341 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1344 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1347 EntrySize = codeview::JumpTableEntrySize::Int32;
1352 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1355void AArch64AsmPrinter::emitFunctionEntryLabel() {
1356 const Triple &
TT =
TM.getTargetTriple();
1357 if (
TT.isOSBinFormatELF() &&
1358 (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall ||
1359 MF->getFunction().getCallingConv() ==
1360 CallingConv::AArch64_SVE_VectorCall ||
1361 MF->getInfo<AArch64FunctionInfo>()->isSVECC())) {
1363 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1369 if (
TT.isWindowsArm64EC() && !MF->getFunction().hasLocalLinkage()) {
1374 OutStreamer->emitAssignment(
1378 auto getSymbolFromMetadata = [&](StringRef
Name) {
1380 if (MDNode *Node = MF->getFunction().getMetadata(Name)) {
1382 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1388 MF->getFunction().getMetadata(
"arm64ec_unmangled_name", UnmangledNames);
1389 for (MDNode *Node : UnmangledNames) {
1391 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1392 if (std::optional<std::string> MangledName =
1395 MMI->getContext().getOrCreateSymbol(*MangledName);
1396 emitFunctionAlias(UnmangledSym, ECMangledSym);
1399 if (MCSymbol *ECMangledSym =
1400 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1401 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1405void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1406 const Constant *CV) {
1408 if (CPA->hasAddressDiscriminator() &&
1409 !CPA->hasSpecialAddressDiscriminator(
1412 "unexpected address discrimination value for ctors/dtors entry, only "
1413 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1422void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1423 const GlobalAlias &GA) {
1429 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1431 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1434 OutStreamer->beginCOFFSymbolDef(ExpSym);
1438 OutStreamer->endCOFFSymbolDef();
1440 OutStreamer->beginCOFFSymbolDef(Sym);
1444 OutStreamer->endCOFFSymbolDef();
1445 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1446 OutStreamer->emitAssignment(
1463void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1464 const llvm::MachineInstr &
MI) {
1465 Register DestReg =
MI.getOperand(0).getReg();
1466 Register ScratchReg =
MI.getOperand(1).getReg();
1469 Register TableReg =
MI.getOperand(2).getReg();
1470 Register EntryReg =
MI.getOperand(3).getReg();
1471 int JTIdx =
MI.getOperand(4).getIndex();
1477 MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1482 Label = MF->getContext().createTempSymbol();
1488 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1490 .addExpr(LabelExpr));
1495 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1496 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1497 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1502 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1503 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1507 .addImm(
Size == 1 ? 0 : 1));
1511 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1515 .addImm(
Size == 4 ? 0 : 2));
1518void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1519 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1520 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1522 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1523 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1539 MachineOperand JTOp =
MI.getOperand(0);
1543 "unsupported compressed jump table");
1545 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1549 uint64_t MaxTableEntry = NumTableEntries - 1;
1551 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1552 .addReg(AArch64::XZR)
1553 .addReg(AArch64::X16)
1554 .addImm(MaxTableEntry)
1557 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1562 if ((MaxTableEntry >>
Offset) == 0)
1564 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1567 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1568 .addReg(AArch64::XZR)
1569 .addReg(AArch64::X16)
1570 .addReg(AArch64::X17)
1576 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1577 .addReg(AArch64::X16)
1578 .addReg(AArch64::X16)
1579 .addReg(AArch64::XZR)
1583 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1584 MCOperand JTMCHi, JTMCLo;
1594 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1596 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1597 .addReg(AArch64::X17)
1598 .addReg(AArch64::X17)
1602 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1603 .addReg(AArch64::X16)
1604 .addReg(AArch64::X17)
1605 .addReg(AArch64::X16)
1609 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1616 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1618 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1619 .addReg(AArch64::X16)
1620 .addReg(AArch64::X17)
1621 .addReg(AArch64::X16)
1624 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1627void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1628 const llvm::MachineInstr &
MI) {
1629 unsigned Opcode =
MI.getOpcode();
1631 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1633 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1634 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1635 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1636 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1637 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1638 if (Opcode == AArch64::MOPSMemorySetPseudo)
1639 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1640 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1641 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1644 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1645 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1647 for (
auto Op :
Ops) {
1649 auto MCIB = MCInstBuilder(
Op);
1651 MCIB.addReg(
MI.getOperand(i++).getReg());
1652 MCIB.addReg(
MI.getOperand(i++).getReg());
1654 MCIB.addReg(
MI.getOperand(i++).getReg());
1656 MCIB.addReg(
MI.getOperand(i++).getReg());
1657 MCIB.addReg(
MI.getOperand(i++).getReg());
1658 MCIB.addReg(
MI.getOperand(i++).getReg());
1660 EmitToStreamer(OutStreamer, MCIB);
1664void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1665 const MachineInstr &
MI) {
1666 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1669 MCSymbol *MILabel = Ctx.createTempSymbol();
1673 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1676 const MachineBasicBlock &
MBB = *
MI.getParent();
1679 while (NumNOPBytes > 0) {
1680 if (MII ==
MBB.
end() || MII->isCall() ||
1681 MII->getOpcode() == AArch64::DBG_VALUE ||
1682 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1683 MII->getOpcode() == TargetOpcode::STACKMAP)
1690 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1691 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
1696void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1697 const MachineInstr &
MI) {
1699 MCSymbol *MILabel = Ctx.createTempSymbol();
1703 PatchPointOpers Opers(&
MI);
1705 int64_t CallTarget = Opers.getCallTarget().getImm();
1706 unsigned EncodedBytes = 0;
1708 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1709 "High 16 bits of call target should be zero.");
1710 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1713 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1714 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1715 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1716 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1719 unsigned NumBytes = Opers.getNumPatchBytes();
1720 assert(NumBytes >= EncodedBytes &&
1721 "Patchpoint can't request size less than the length of a call.");
1722 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1723 "Invalid number of NOP bytes requested!");
1724 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1725 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
1728void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1729 const MachineInstr &
MI) {
1730 StatepointOpers SOpers(&
MI);
1731 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1732 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1733 for (
unsigned i = 0; i < PatchBytes; i += 4)
1734 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
1737 const MachineOperand &CallTarget = SOpers.getCallTarget();
1738 MCOperand CallTargetMCOp;
1739 unsigned CallOpcode;
1740 switch (CallTarget.
getType()) {
1743 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1744 CallOpcode = AArch64::BL;
1748 CallOpcode = AArch64::BL;
1752 CallOpcode = AArch64::BLR;
1759 EmitToStreamer(OutStreamer,
1760 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1764 MCSymbol *MILabel = Ctx.createTempSymbol();
1769void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1778 unsigned OperandsBeginIdx = 4;
1781 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1788 MI.setOpcode(Opcode);
1793 for (
const MachineOperand &MO :
1796 lowerOperand(MO, Dest);
1797 MI.addOperand(Dest);
1805 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1807 .addReg(AArch64::XZR)
1812void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1813 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1814 EmitToStreamer(*OutStreamer,
1815 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1821void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1822 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1823 EmitToStreamer(*OutStreamer,
1824 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1831void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1832 Register DestReg =
MI.getOperand(0).getReg();
1833 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->
isNeonAvailable()) {
1834 if (STI->hasZeroCycleZeroingFPR64()) {
1837 if (AArch64::FPR16RegClass.
contains(DestReg))
1838 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1839 &AArch64::FPR64RegClass);
1840 else if (AArch64::FPR32RegClass.
contains(DestReg))
1841 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1842 &AArch64::FPR64RegClass);
1850 EmitToStreamer(*OutStreamer, MOVI);
1851 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1854 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1855 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1856 &AArch64::FPR128RegClass);
1857 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1858 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1859 &AArch64::FPR128RegClass);
1862 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1863 &AArch64::FPR128RegClass);
1870 EmitToStreamer(*OutStreamer, MOVI);
1872 emitFMov0AsFMov(
MI, DestReg);
1875 emitFMov0AsFMov(
MI, DestReg);
1879void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1882 switch (
MI.getOpcode()) {
1885 case AArch64::FMOVH0:
1886 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1887 if (!STI->hasFullFP16())
1888 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1892 case AArch64::FMOVS0:
1897 case AArch64::FMOVD0:
1903 EmitToStreamer(*OutStreamer, FMov);
1906Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc,
1909 bool MayUseAddrAsScratch) {
1910 assert(ScratchReg == AArch64::X16 || ScratchReg == AArch64::X17 ||
1913 if (AddrDisc == AArch64::NoRegister)
1914 AddrDisc = AArch64::XZR;
1922 if (AddrDisc == AArch64::XZR) {
1923 emitMOVZ(ScratchReg, Disc, 0);
1930 assert(MayUseAddrAsScratch || ScratchReg != AddrDisc);
1931 bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17 ||
1933 if (MayUseAddrAsScratch && AddrDiscIsSafe)
1934 ScratchReg = AddrDisc;
1936 emitMovXReg(ScratchReg, AddrDisc);
1938 emitMOVK(ScratchReg, Disc, 48);
1946void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
1949 const MCSymbol *OnFailure) {
1979 if (Method == AuthCheckMethod::None)
1981 if (Method == AuthCheckMethod::DummyLoad) {
1982 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
1986 assert(ShouldTrap && !OnFailure &&
"DummyLoad always traps on error");
1990 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
1991 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
1993 emitMovXReg(ScratchReg, TestedReg);
1995 if (Method == AuthCheckMethod::XPAC) {
1999 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2004 assert(TestedReg == AArch64::LR &&
2005 "XPACHint mode is only compatible with checking the LR register");
2007 "XPACHint mode is only compatible with I-keys");
2008 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2012 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2013 .addReg(AArch64::XZR)
2020 MCInstBuilder(AArch64::Bcc)
2023 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2025 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2032 MCInstBuilder(AArch64::TBZX)
2041 assert(!OnFailure &&
"Cannot specify OnFailure with ShouldTrap");
2044 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2058 case AuthCheckMethod::XPACHint:
2061 case AuthCheckMethod::XPAC:
2063 emitMovXReg(TestedReg, ScratchReg);
2070 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2076 MCInstBuilder(AArch64::B)
2090void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2095 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2102 "Neither x16 nor x17 is available as a scratch register");
2105 emitPtrauthCheckAuthenticatedValue(
2106 AArch64::LR, ScratchReg,
Key, LRCheckMethod,
2110void AArch64AsmPrinter::emitPtrauthAuthResign(
2112 const MachineOperand *AUTAddrDisc,
Register Scratch,
2113 std::optional<AArch64PACKey::ID> PACKey, uint64_t PACDisc,
2115 const bool IsAUTPAC = PACKey.has_value();
2129 bool ShouldCheck =
true;
2131 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
2136 ShouldCheck = ShouldTrap =
false;
2143 ShouldCheck = ShouldTrap =
false;
2150 ShouldCheck = ShouldTrap =
true;
2156 Register AUTDiscReg = emitPtrauthDiscriminator(
2157 AUTDisc, AUTAddrDisc->
getReg(), Scratch, AUTAddrDisc->
isKill());
2158 bool AUTZero = AUTDiscReg == AArch64::XZR;
2169 EmitToStreamer(*OutStreamer, AUTInst);
2172 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2178 if (IsAUTPAC && !ShouldTrap)
2179 EndSym = createTempSymbol(
"resign_end_");
2181 emitPtrauthCheckAuthenticatedValue(AUTVal, Scratch, AUTKey,
2182 AArch64PAuth::AuthCheckMethod::XPAC,
2183 ShouldTrap, EndSym);
2195 emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
2196 bool PACZero = PACDiscReg == AArch64::XZR;
2207 EmitToStreamer(*OutStreamer, PACInst);
2214void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2217 uint64_t Disc =
MI->getOperand(3).getImm();
2218 Register AddrDisc =
MI->getOperand(4).getReg();
2219 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2223 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2224 assert(ScratchReg != AddrDisc &&
2225 "Neither X16 nor X17 is available as a scratch register");
2229 Register DiscReg = emitPtrauthDiscriminator(
2230 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2231 bool IsZeroDisc = DiscReg == AArch64::XZR;
2242 EmitToStreamer(*OutStreamer, PACInst);
2245void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2246 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2247 unsigned BrTarget =
MI->getOperand(0).getReg();
2251 "Invalid auth call key");
2253 uint64_t Disc =
MI->getOperand(2).getImm();
2256 unsigned AddrDisc =
MI->getOperand(3).getReg();
2262 if (BrTarget == AddrDisc)
2279 bool AddrDiscIsImplicitDef =
2280 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2281 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2282 AddrDiscIsImplicitDef);
2283 bool IsZeroDisc = DiscReg == AArch64::XZR;
2288 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
2290 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
2293 Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
2295 Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
2303 EmitToStreamer(*OutStreamer, BRInst);
2307AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2308 MCContext &Ctx = OutContext;
2313 getDataLayout(),
Offset,
true);
2321 "cannot resolve target base/addend of ptrauth constant");
2339 "' out of range [0, " +
2347 "' out of range [0, 0xFFFF]");
2356void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2357 unsigned DstReg =
MI.getOperand(0).getReg();
2358 const MachineOperand &GAOp =
MI.getOperand(1);
2359 const uint64_t KeyC =
MI.getOperand(2).getImm();
2361 "key is out of range [0, AArch64PACKey::LAST]");
2363 const uint64_t Disc =
MI.getOperand(3).getImm();
2365 "constant discriminator is out of range [0, 0xffff]");
2374 if (
TM.getTargetTriple().isOSBinFormatELF()) {
2376 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2379 "non-zero offset for $auth_ptr$ stub slots is not supported");
2381 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2383 assert(
TM.getTargetTriple().isOSBinFormatMachO() &&
2384 "LOADauthptrstatic is implemented only for MachO/ELF");
2386 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2387 getObjFileLowering());
2390 "non-zero offset for $auth_ptr$ stub slots is not supported");
2392 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2395 MachineOperand StubMOHi =
2399 MCOperand StubMCHi, StubMCLo;
2406 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2408 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2414void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2415 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2416 const bool IsELFSignedGOT =
MI.getParent()
2418 ->getInfo<AArch64FunctionInfo>()
2419 ->hasELFSignedGOT();
2420 MachineOperand GAOp =
MI.getOperand(0);
2421 const uint64_t KeyC =
MI.getOperand(1).getImm();
2423 "key is out of range [0, AArch64PACKey::LAST]");
2425 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2426 const uint64_t Disc =
MI.getOperand(3).getImm();
2428 "constant discriminator is out of range [0, 0xffff]");
2475 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2476 MCOperand GAMCHi, GAMCLo;
2489 MCInstBuilder(AArch64::ADRP)
2490 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2494 if (IsELFSignedGOT) {
2495 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2496 .addReg(AArch64::X17)
2497 .addReg(AArch64::X17)
2501 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2502 .addReg(AArch64::X16)
2503 .addReg(AArch64::X17)
2512 EmitToStreamer(MCInstBuilder(AuthOpcode)
2513 .addReg(AArch64::X16)
2514 .addReg(AArch64::X16)
2515 .addReg(AArch64::X17));
2517 if (!STI->hasFPAC()) {
2521 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2522 AArch64PAuth::AuthCheckMethod::XPAC,
2527 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2528 .addReg(AArch64::X16)
2529 .addReg(AArch64::X16)
2533 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2534 .addReg(AArch64::X16)
2535 .addReg(AArch64::X16)
2542 const bool IsNeg =
Offset < 0;
2544 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2547 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2548 .addReg(AArch64::X16)
2549 .addReg(AArch64::X16)
2550 .addImm((AbsOffset >> BitPos) & 0xfff)
2554 const uint64_t UOffset =
Offset;
2555 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2556 .addReg(AArch64::X17)
2557 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
2559 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
2560 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2561 uint64_t Shifted = UOffset >> BitPos;
2563 return Shifted != 0;
2564 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2565 if (((Shifted >>
I) & 0xffff) != 0xffff)
2569 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2570 emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
2572 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2573 .addReg(AArch64::X16)
2574 .addReg(AArch64::X16)
2575 .addReg(AArch64::X17)
2580 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2583 .addReg(AArch64::X16)
2584 .addReg(AArch64::X16);
2585 if (DiscReg != AArch64::XZR)
2586 MIB.addReg(DiscReg);
2587 EmitToStreamer(MIB);
2590void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2592 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2593 const MachineOperand &GAMO =
MI.getOperand(1);
2600 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2601 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2602 .addReg(AuthResultReg)
2603 .addReg(AArch64::X17)
2606 MachineOperand GAHiOp(GAMO);
2607 MachineOperand GALoOp(GAMO);
2611 MCOperand GAMCHi, GAMCLo;
2616 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2618 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2619 .addReg(AArch64::X17)
2620 .addReg(AArch64::X17)
2624 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2625 .addReg(AuthResultReg)
2626 .addReg(AArch64::X17)
2633 UndefWeakSym = createTempSymbol(
"undef_weak");
2635 MCInstBuilder(AArch64::CBZX)
2636 .addReg(AuthResultReg)
2644 EmitToStreamer(MCInstBuilder(AuthOpcode)
2645 .addReg(AuthResultReg)
2646 .addReg(AuthResultReg)
2647 .addReg(AArch64::X17));
2652 if (!STI->hasFPAC()) {
2656 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2657 AArch64PAuth::AuthCheckMethod::XPAC,
2661 emitMovXReg(DstReg, AuthResultReg);
2666AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2670 if (std::optional<uint16_t> BADisc =
2678void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
2680 bool Is32Bit =
false;
2682 switch (
MI->getOpcode()) {
2685 case AArch64::CBWPrr:
2688 case AArch64::CBXPrr:
2691 case AArch64::CBWPri:
2695 case AArch64::CBXPri:
2702 bool NeedsRegSwap =
false;
2703 bool NeedsImmDec =
false;
2704 bool NeedsImmInc =
false;
2713 MCOpC = IsImm ? (Is32Bit ? AArch64::CBEQWri : AArch64::CBEQXri)
2714 : (Is32Bit ? AArch64::CBEQWrr : AArch64::CBEQXrr);
2717 MCOpC = IsImm ? (Is32Bit ? AArch64::CBNEWri : AArch64::CBNEXri)
2718 : (Is32Bit ? AArch64::CBNEWrr : AArch64::CBNEXrr);
2721 MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2722 : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2723 NeedsImmDec = IsImm;
2726 MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2727 : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2728 NeedsRegSwap = !IsImm;
2731 MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2732 : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2735 MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2736 : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2737 NeedsRegSwap = !IsImm;
2738 NeedsImmInc = IsImm;
2741 MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2742 : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2743 NeedsImmDec = IsImm;
2746 MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2747 : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2748 NeedsRegSwap = !IsImm;
2751 MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2752 : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2755 MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2756 : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2757 NeedsRegSwap = !IsImm;
2758 NeedsImmInc = IsImm;
2765 MCOperand Lhs, Rhs, Trgt;
2766 lowerOperand(
MI->getOperand(1), Lhs);
2767 lowerOperand(
MI->getOperand(2), Rhs);
2768 lowerOperand(
MI->getOperand(3), Trgt);
2772 assert(Lhs.
isReg() &&
"Expected register operand for CB");
2773 assert(Rhs.
isReg() &&
"Expected register operand for CB");
2776 }
else if (NeedsImmDec) {
2780 }
else if (NeedsImmInc) {
2790 "CB immediate operand out-of-bounds");
2793 EmitToStreamer(*OutStreamer, Inst);
2798#include "AArch64GenMCPseudoLowering.inc"
2800void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
2807void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
2808 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
2818 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
2819 EmitToStreamer(*OutStreamer, OutInst);
2823 if (
MI->getOpcode() == AArch64::ADRP) {
2824 for (
auto &Opd :
MI->operands()) {
2825 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
2826 "swift_async_extendedFramePointerFlags") {
2827 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
2834 MCSymbol *LOHLabel = createTempSymbol(
"loh");
2836 LOHInstToLabel[
MI] = LOHLabel;
2840 AArch64TargetStreamer *TS =
2843 switch (
MI->getOpcode()) {
2846 "Unhandled tail call instruction");
2848 case AArch64::HINT: {
2853 if (CurrentPatchableFunctionEntrySym &&
2854 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
2855 MI == &MF->front().front()) {
2856 int64_t
Imm =
MI->getOperand(0).getImm();
2857 if ((Imm & 32) && (Imm & 6)) {
2859 MCInstLowering.
Lower(
MI, Inst);
2860 EmitToStreamer(*OutStreamer, Inst);
2861 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
2862 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
2868 case AArch64::MOVMCSym: {
2869 Register DestReg =
MI->getOperand(0).getReg();
2870 const MachineOperand &MO_Sym =
MI->getOperand(1);
2871 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
2872 MCOperand Hi_MCSym, Lo_MCSym;
2885 EmitToStreamer(*OutStreamer, MovZ);
2893 EmitToStreamer(*OutStreamer, MovK);
2896 case AArch64::MOVIv2d_ns:
2904 if (STI->hasZeroCycleZeroingFPWorkaround() &&
2905 MI->getOperand(1).getImm() == 0) {
2907 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
2910 EmitToStreamer(*OutStreamer, TmpInst);
2915 case AArch64::DBG_VALUE:
2916 case AArch64::DBG_VALUE_LIST:
2918 SmallString<128> TmpStr;
2919 raw_svector_ostream OS(TmpStr);
2920 PrintDebugValueComment(
MI, OS);
2925 case AArch64::EMITBKEY: {
2927 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2928 ExceptionHandlingType != ExceptionHandling::ARM)
2931 if (getFunctionCFISectionType(*MF) == CFISection::None)
2938 case AArch64::EMITMTETAGGED: {
2940 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2941 ExceptionHandlingType != ExceptionHandling::ARM)
2944 if (getFunctionCFISectionType(*MF) != CFISection::None)
2949 case AArch64::AUTx16x17:
2950 emitPtrauthAuthResign(AArch64::X16,
2952 MI->getOperand(1).getImm(), &
MI->getOperand(2),
2953 AArch64::X17, std::nullopt, 0, 0);
2956 case AArch64::AUTxMxN:
2957 emitPtrauthAuthResign(
MI->getOperand(0).getReg(),
2959 MI->getOperand(4).getImm(), &
MI->getOperand(5),
2960 MI->getOperand(1).getReg(), std::nullopt, 0, 0);
2963 case AArch64::AUTPAC:
2964 emitPtrauthAuthResign(
2966 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
2968 MI->getOperand(4).getImm(),
MI->getOperand(5).getReg());
2972 emitPtrauthSign(
MI);
2975 case AArch64::LOADauthptrstatic:
2976 LowerLOADauthptrstatic(*
MI);
2979 case AArch64::LOADgotPAC:
2980 case AArch64::MOVaddrPAC:
2981 LowerMOVaddrPAC(*
MI);
2984 case AArch64::LOADgotAUTH:
2985 LowerLOADgotAUTH(*
MI);
2990 emitPtrauthBranch(
MI);
2996 case AArch64::AUTH_TCRETURN:
2997 case AArch64::AUTH_TCRETURN_BTI: {
2999 const uint64_t
Key =
MI->getOperand(2).getImm();
3001 "Invalid auth key for tail-call return");
3003 const uint64_t Disc =
MI->getOperand(3).getImm();
3006 Register AddrDisc =
MI->getOperand(4).getReg();
3008 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3010 emitPtrauthTailCallHardening(
MI);
3013 if (Callee == AddrDisc)
3020 bool AddrDiscIsImplicitDef =
3021 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3022 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3023 AddrDiscIsImplicitDef);
3025 const bool IsZero = DiscReg == AArch64::XZR;
3026 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
3027 {AArch64::BRAB, AArch64::BRABZ}};
3034 EmitToStreamer(*OutStreamer, TmpInst);
3038 case AArch64::TCRETURNri:
3039 case AArch64::TCRETURNrix16x17:
3040 case AArch64::TCRETURNrix17:
3041 case AArch64::TCRETURNrinotx16:
3042 case AArch64::TCRETURNriALL: {
3043 emitPtrauthTailCallHardening(
MI);
3045 recordIfImportCall(
MI);
3049 EmitToStreamer(*OutStreamer, TmpInst);
3052 case AArch64::TCRETURNdi: {
3053 emitPtrauthTailCallHardening(
MI);
3057 recordIfImportCall(
MI);
3061 EmitToStreamer(*OutStreamer, TmpInst);
3064 case AArch64::SpeculationBarrierISBDSBEndBB: {
3069 EmitToStreamer(*OutStreamer, TmpInstDSB);
3073 EmitToStreamer(*OutStreamer, TmpInstISB);
3076 case AArch64::SpeculationBarrierSBEndBB: {
3080 EmitToStreamer(*OutStreamer, TmpInstSB);
3083 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3090 const MachineOperand &MO_Sym =
MI->getOperand(0);
3091 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3092 MCOperand SymTLSDescLo12, SymTLSDesc;
3095 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3102 EmitToStreamer(*OutStreamer, Adrp);
3110 EmitToStreamer(*OutStreamer, Ldr);
3113 Add.setOpcode(AArch64::ADDXri);
3116 Add.addOperand(SymTLSDescLo12);
3118 EmitToStreamer(*OutStreamer,
Add);
3127 EmitToStreamer(*OutStreamer, Blraa);
3131 case AArch64::TLSDESC_CALLSEQ: {
3139 const MachineOperand &MO_Sym =
MI->getOperand(0);
3140 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3141 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3145 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3152 EmitToStreamer(*OutStreamer, Adrp);
3165 EmitToStreamer(*OutStreamer, Ldr);
3169 Add.setOpcode(AArch64::ADDWri);
3173 Add.setOpcode(AArch64::ADDXri);
3177 Add.addOperand(SymTLSDescLo12);
3179 EmitToStreamer(*OutStreamer,
Add);
3184 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3186 EmitToStreamer(*OutStreamer, TLSDescCall);
3194 EmitToStreamer(*OutStreamer, Blr);
3199 case AArch64::JumpTableDest32:
3200 case AArch64::JumpTableDest16:
3201 case AArch64::JumpTableDest8:
3202 LowerJumpTableDest(*OutStreamer, *
MI);
3205 case AArch64::BR_JumpTable:
3206 LowerHardenedBRJumpTable(*
MI);
3209 case AArch64::FMOVH0:
3210 case AArch64::FMOVS0:
3211 case AArch64::FMOVD0:
3215 case AArch64::MOPSMemoryCopyPseudo:
3216 case AArch64::MOPSMemoryMovePseudo:
3217 case AArch64::MOPSMemorySetPseudo:
3218 case AArch64::MOPSMemorySetTaggingPseudo:
3219 LowerMOPS(*OutStreamer, *
MI);
3222 case TargetOpcode::STACKMAP:
3223 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3225 case TargetOpcode::PATCHPOINT:
3226 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3228 case TargetOpcode::STATEPOINT:
3229 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3231 case TargetOpcode::FAULTING_OP:
3232 return LowerFAULTING_OP(*
MI);
3234 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3235 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3238 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3239 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3242 case TargetOpcode::PATCHABLE_TAIL_CALL:
3243 LowerPATCHABLE_TAIL_CALL(*
MI);
3245 case TargetOpcode::PATCHABLE_EVENT_CALL:
3246 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3247 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3248 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3250 case AArch64::KCFI_CHECK:
3251 LowerKCFI_CHECK(*
MI);
3254 case AArch64::HWASAN_CHECK_MEMACCESS:
3255 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3256 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3257 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3258 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3261 case AArch64::SEH_StackAlloc:
3265 case AArch64::SEH_SaveFPLR:
3269 case AArch64::SEH_SaveFPLR_X:
3270 assert(
MI->getOperand(0).getImm() < 0 &&
3271 "Pre increment SEH opcode must have a negative offset");
3275 case AArch64::SEH_SaveReg:
3277 MI->getOperand(1).getImm());
3280 case AArch64::SEH_SaveReg_X:
3281 assert(
MI->getOperand(1).getImm() < 0 &&
3282 "Pre increment SEH opcode must have a negative offset");
3284 -
MI->getOperand(1).getImm());
3287 case AArch64::SEH_SaveRegP:
3288 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3289 MI->getOperand(0).getImm() <= 28) {
3290 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3291 "Register paired with LR must be odd");
3293 MI->getOperand(2).getImm());
3296 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3297 "Non-consecutive registers not allowed for save_regp");
3299 MI->getOperand(2).getImm());
3302 case AArch64::SEH_SaveRegP_X:
3303 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3304 "Non-consecutive registers not allowed for save_regp_x");
3305 assert(
MI->getOperand(2).getImm() < 0 &&
3306 "Pre increment SEH opcode must have a negative offset");
3308 -
MI->getOperand(2).getImm());
3311 case AArch64::SEH_SaveFReg:
3313 MI->getOperand(1).getImm());
3316 case AArch64::SEH_SaveFReg_X:
3317 assert(
MI->getOperand(1).getImm() < 0 &&
3318 "Pre increment SEH opcode must have a negative offset");
3320 -
MI->getOperand(1).getImm());
3323 case AArch64::SEH_SaveFRegP:
3324 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3325 "Non-consecutive registers not allowed for save_regp");
3327 MI->getOperand(2).getImm());
3330 case AArch64::SEH_SaveFRegP_X:
3331 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3332 "Non-consecutive registers not allowed for save_regp_x");
3333 assert(
MI->getOperand(2).getImm() < 0 &&
3334 "Pre increment SEH opcode must have a negative offset");
3336 -
MI->getOperand(2).getImm());
3339 case AArch64::SEH_SetFP:
3343 case AArch64::SEH_AddFP:
3347 case AArch64::SEH_Nop:
3351 case AArch64::SEH_PrologEnd:
3355 case AArch64::SEH_EpilogStart:
3359 case AArch64::SEH_EpilogEnd:
3363 case AArch64::SEH_PACSignLR:
3367 case AArch64::SEH_SaveAnyRegQP:
3368 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3369 "Non-consecutive registers not allowed for save_any_reg");
3370 assert(
MI->getOperand(2).getImm() >= 0 &&
3371 "SaveAnyRegQP SEH opcode offset must be non-negative");
3372 assert(
MI->getOperand(2).getImm() <= 1008 &&
3373 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3375 MI->getOperand(2).getImm());
3378 case AArch64::SEH_SaveAnyRegQPX:
3379 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3380 "Non-consecutive registers not allowed for save_any_reg");
3381 assert(
MI->getOperand(2).getImm() < 0 &&
3382 "SaveAnyRegQPX SEH opcode offset must be negative");
3383 assert(
MI->getOperand(2).getImm() >= -1008 &&
3384 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3386 -
MI->getOperand(2).getImm());
3389 case AArch64::SEH_AllocZ:
3390 assert(
MI->getOperand(0).getImm() >= 0 &&
3391 "AllocZ SEH opcode offset must be non-negative");
3392 assert(
MI->getOperand(0).getImm() <= 255 &&
3393 "AllocZ SEH opcode offset must fit into 8 bits");
3397 case AArch64::SEH_SaveZReg:
3398 assert(
MI->getOperand(1).getImm() >= 0 &&
3399 "SaveZReg SEH opcode offset must be non-negative");
3400 assert(
MI->getOperand(1).getImm() <= 255 &&
3401 "SaveZReg SEH opcode offset must fit into 8 bits");
3403 MI->getOperand(1).getImm());
3406 case AArch64::SEH_SavePReg:
3407 assert(
MI->getOperand(1).getImm() >= 0 &&
3408 "SavePReg SEH opcode offset must be non-negative");
3409 assert(
MI->getOperand(1).getImm() <= 255 &&
3410 "SavePReg SEH opcode offset must fit into 8 bits");
3412 MI->getOperand(1).getImm());
3417 recordIfImportCall(
MI);
3419 MCInstLowering.
Lower(
MI, TmpInst);
3420 EmitToStreamer(*OutStreamer, TmpInst);
3423 case AArch64::CBWPri:
3424 case AArch64::CBXPri:
3425 case AArch64::CBWPrr:
3426 case AArch64::CBXPrr:
3427 emitCBPseudoExpansion(
MI);
3433 MCInstLowering.
Lower(
MI, TmpInst);
3434 EmitToStreamer(*OutStreamer, TmpInst);
3437void AArch64AsmPrinter::recordIfImportCall(
3438 const llvm::MachineInstr *BranchInst) {
3439 if (!EnableImportCallOptimization)
3443 if (GV && GV->hasDLLImportStorageClass()) {
3444 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3449 .push_back({CallSiteSymbol, CalledSymbol});
3453void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3454 MCSymbol *LazyPointer) {
3471 EmitToStreamer(Adrp);
3479 MCOperand SymPageOff;
3486 EmitToStreamer(Ldr);
3489 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3490 .addReg(AArch64::X16)
3491 .addReg(AArch64::X16)
3494 EmitToStreamer(MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3496 .addReg(AArch64::X16));
3499void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3500 const GlobalIFunc &GI,
3501 MCSymbol *LazyPointer) {
3533 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3534 .addReg(AArch64::SP)
3535 .addReg(AArch64::FP)
3536 .addReg(AArch64::LR)
3537 .addReg(AArch64::SP)
3540 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3541 .addReg(AArch64::FP)
3542 .addReg(AArch64::SP)
3546 for (
int I = 0;
I != 4; ++
I)
3547 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3548 .addReg(AArch64::SP)
3549 .addReg(AArch64::X1 + 2 *
I)
3550 .addReg(AArch64::X0 + 2 *
I)
3551 .addReg(AArch64::SP)
3554 for (
int I = 0;
I != 4; ++
I)
3555 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3556 .addReg(AArch64::SP)
3557 .addReg(AArch64::D1 + 2 *
I)
3558 .addReg(AArch64::D0 + 2 *
I)
3559 .addReg(AArch64::SP)
3563 MCInstBuilder(AArch64::BL)
3576 EmitToStreamer(Adrp);
3584 MCOperand SymPageOff;
3591 EmitToStreamer(Ldr);
3594 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3595 .addReg(AArch64::X0)
3596 .addReg(AArch64::X16)
3599 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3600 .addReg(AArch64::X16)
3601 .addReg(AArch64::X0)
3605 for (
int I = 3;
I != -1; --
I)
3606 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3607 .addReg(AArch64::SP)
3608 .addReg(AArch64::D1 + 2 *
I)
3609 .addReg(AArch64::D0 + 2 *
I)
3610 .addReg(AArch64::SP)
3613 for (
int I = 3;
I != -1; --
I)
3614 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3615 .addReg(AArch64::SP)
3616 .addReg(AArch64::X1 + 2 *
I)
3617 .addReg(AArch64::X0 + 2 *
I)
3618 .addReg(AArch64::SP)
3621 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3622 .addReg(AArch64::SP)
3623 .addReg(AArch64::FP)
3624 .addReg(AArch64::LR)
3625 .addReg(AArch64::SP)
3628 EmitToStreamer(MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3630 .addReg(AArch64::X16));
3633const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
3634 const Constant *BaseCV,
3644char AArch64AsmPrinter::ID = 0;
3647 "AArch64 Assembly Printer",
false,
false)
3651LLVMInitializeAArch64AsmPrinter() {
static cl::opt< PtrauthCheckMode > PtrauthAuthChecks("aarch64-ptrauth-auth-checks", cl::Hidden, cl::values(clEnumValN(Unchecked, "none", "don't test for failure"), clEnumValN(Poison, "poison", "poison on failure"), clEnumValN(Trap, "trap", "trap on failure")), cl::desc("Check pointer authentication auth/resign failures"), cl::init(Default))
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
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[]
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...
bool shouldSignReturnAddress(const MachineFunction &MF) const
const SetOfInstructions & getLOHRelated() const
unsigned getJumpTableEntrySize(int Idx) const
MCSymbol * getJumpTableEntryPCRelSymbol(int Idx) const
std::optional< std::string > getOutliningStyle() const
const MILOHContainer & getLOHContainer() const
void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym)
bool shouldSignWithBKey() const
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MCSymbol * GetGlobalValueSymbol(const GlobalValue *GV, unsigned TargetFlags) const
void Lower(const MachineInstr *MI, MCInst &OutMI) const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
const AArch64RegisterInfo * getRegisterInfo() const override
bool isNeonAvailable() const
Returns true if the target has NEON and the function at runtime is known to have NEON enabled (e....
const AArch64InstrInfo * getInstrInfo() const override
bool isTargetILP32() const
std::optional< uint16_t > getPtrAuthBlockAddressDiscriminatorIfEnabled(const Function &ParentFn) const
Compute the integer discriminator for a given BlockAddress constant, if blockaddress signing is enabl...
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
AArch64PAuth::AuthCheckMethod getAuthenticatedLRCheckMethod(const MachineFunction &MF) const
Choose a method of checking LR before performing a tail call.
virtual void emitARM64WinCFISaveRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset)
virtual void emitAttributesSubsection(StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, AArch64BuildAttributes::SubsectionType ParameterType)
Build attributes implementation.
virtual void emitARM64WinCFISavePReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPACSignLR()
virtual void 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()
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.
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)
Base class for the full range of assembler expressions which are needed for parsing.
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.
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 void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitCOFFSymbolType(int Type)
Emit the type of the symbol.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
virtual void endCOFFSymbolDef()
Marks the end of the symbol definition.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCFIMTETaggedFrame()
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
MCSection * getCurrentSectionOnly() const
void emitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ....
virtual void emitCOFFSymbolStorageClass(int StorageClass)
Emit the storage class of the symbol.
Generic base class for all target subtargets.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
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.
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_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.
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,...