80#define DEBUG_TYPE "AArch64AsmPrinter"
85 "Number of zero-cycle FPR zeroing instructions expanded from "
86 "canonical pseudo instructions");
94 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
95 bool PtrauthInitFini =
false;
96 bool PtrauthInitFiniAddressDisc =
false;
98 unsigned InstsEmitted;
100 bool EnableImportCallOptimization =
false;
102 SectionToImportedFunctionCalls;
103 unsigned PAuthIFuncNextUniqueID = 1;
110 MCInstLowering(OutContext, *this), FM(*this) {}
112 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
116 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const {
117 return MCInstLowering.lowerOperand(MO, MCOp);
120 const MCExpr *lowerConstantPtrAuth(
const ConstantPtrAuth &CPA)
override;
122 const MCExpr *lowerBlockAddressConstant(
const BlockAddress &BA)
override;
124 void emitStartOfAsmFile(
Module &M)
override;
125 void emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
126 ArrayRef<unsigned> JumpTableIndices)
override;
129 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
130 const MCSymbol *BranchLabel)
const override;
132 void emitFunctionEntryLabel()
override;
134 void emitXXStructor(
const DataLayout &
DL,
const Constant *CV)
override;
136 void LowerJumpTableDest(MCStreamer &OutStreamer,
const MachineInstr &
MI);
138 void LowerHardenedBRJumpTable(
const MachineInstr &
MI);
140 void LowerMOPS(MCStreamer &OutStreamer,
const MachineInstr &
MI);
142 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
143 const MachineInstr &
MI);
144 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
145 const MachineInstr &
MI);
146 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
147 const MachineInstr &
MI);
148 void LowerFAULTING_OP(
const MachineInstr &
MI);
150 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI);
151 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI);
152 void LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI);
153 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
155 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
156 HwasanMemaccessTuple;
157 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
158 void LowerKCFI_CHECK(
const MachineInstr &
MI);
159 void LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI);
160 void emitHwasanMemaccessSymbols(
Module &M);
162 void emitSled(
const MachineInstr &
MI, SledKind Kind);
170 if (STI->isX16X17Safer())
171 return Reg == AArch64::X16 ||
Reg == AArch64::X17;
177 void emitPtrauthBranch(
const MachineInstr *
MI);
179 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
183 const MCSymbol *OnFailure =
nullptr);
186 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
188 struct PtrAuthSchema {
190 const MachineOperand &AddrDiscOp);
197 bool AddrDiscIsKilled;
200 bool addrDiscIsKilledAndNoneOf(std::initializer_list<Register> Regs) {
218 PtrAuthSchema AuthSchema,
219 std::optional<PtrAuthSchema> SignSchema,
220 std::optional<int64_t> Addend,
Value *DS);
225 bool emitDeactivationSymbolRelocation(
Value *DS);
228 void emitPtrauthSign(
const MachineInstr *
MI);
252 bool MayClobberAddrDisc =
false);
255 void LowerLOADauthptrstatic(
const MachineInstr &
MI);
259 void LowerMOVaddrPAC(
const MachineInstr &
MI);
264 void LowerLOADgotAUTH(
const MachineInstr &
MI);
266 void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
267 void emitAddress(MCRegister
Reg,
const MCExpr *Expr, MCRegister Tmp,
268 bool DSOLocal,
const MCSubtargetInfo &STI);
270 const MCExpr *emitPAuthRelocationAsIRelative(
272 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
276 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
279 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
280 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
283 void emitCBPseudoExpansion(
const MachineInstr *
MI);
286 void emitAtomicHintPseudoExpansion(
const MachineInstr *
MI);
287 void emitAtomicHintPseudoExpansionRO(
const MachineInstr *
MI);
288 void emitAtomicHintPseudoExpansionImm(
const MachineInstr *
MI);
291 void emitAtomicFetchHintPseudoExpansion(
const MachineInstr *
MI);
293 void EmitToStreamer(MCStreamer &S,
const MCInst &Inst);
294 void EmitToStreamer(
const MCInst &Inst) {
295 EmitToStreamer(*OutStreamer, Inst);
300 void emitFunctionHeaderComment()
override;
302 void getAnalysisUsage(AnalysisUsage &AU)
const override {
308 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
309 PSI = &PSIW->getPSI();
311 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
312 SDPI = &SDPIW->getStaticDataProfileInfo();
314 AArch64FI = MF.
getInfo<AArch64FunctionInfo>();
317 SetupMachineFunction(MF);
319 if (STI->isTargetCOFF()) {
326 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
327 OutStreamer->emitCOFFSymbolStorageClass(Scl);
328 OutStreamer->emitCOFFSymbolType(
Type);
329 OutStreamer->endCOFFSymbolDef();
343 const Constant *BaseCV =
nullptr,
347 void printOperand(
const MachineInstr *
MI,
unsigned OpNum, raw_ostream &O);
349 bool printAsmRegInClass(
const MachineOperand &MO,
353 bool PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
354 const char *ExtraCode, raw_ostream &O)
override;
355 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
356 const char *ExtraCode, raw_ostream &O)
override;
358 void PrintDebugValueComment(
const MachineInstr *
MI, raw_ostream &OS);
360 void emitFunctionBodyEnd()
override;
361 void emitGlobalAlias(
const Module &M,
const GlobalAlias &GA)
override;
363 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
364 void emitEndOfAsmFile(
Module &M)
override;
366 AArch64FunctionInfo *AArch64FI =
nullptr;
381 void emitFMov0(
const MachineInstr &
MI);
382 void emitFMov0AsFMov(
const MachineInstr &
MI,
Register DestReg);
384 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
386 MInstToMCSymbol LOHInstToLabel;
388 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
389 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
392 const MCSubtargetInfo *getIFuncMCSubtargetInfo()
const override {
396 void emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
397 MCSymbol *LazyPointer)
override;
398 void emitMachOIFuncStubHelperBody(
Module &M,
const GlobalIFunc &GI,
399 MCSymbol *LazyPointer)
override;
404 void recordIfImportCall(
const MachineInstr *BranchInst);
411 Metadata *Flag = M.getModuleFlag(Name);
416 assert((
Value == 0 ||
Value == 1) &&
"Boolean flag is expected, if present");
420void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
421 const Triple &
TT =
M.getTargetTriple();
423 if (
TT.isOSBinFormatCOFF()) {
424 emitCOFFFeatureSymbol(M);
425 emitCOFFReplaceableFunctionData(M);
427 if (
M.getModuleFlag(
"import-call-optimization"))
428 EnableImportCallOptimization =
true;
433 M,
"ptrauth-init-fini-address-discrimination");
435 if (!
TT.isOSBinFormatELF())
440 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
443 unsigned BAFlags = 0;
444 unsigned GNUFlags = 0;
446 M.getModuleFlag(
"branch-target-enforcement"))) {
447 if (!BTE->isZero()) {
448 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
454 M.getModuleFlag(
"guarded-control-stack"))) {
455 if (!GCS->isZero()) {
456 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
462 M.getModuleFlag(
"sign-return-address"))) {
463 if (!Sign->isZero()) {
464 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
471 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
472 PAuthABIPlatform = PAP->getZExtValue();
477 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
478 PAuthABIVersion = PAV->getZExtValue();
486 PAuthABIVersion == 0) {
492 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
494 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
497void AArch64AsmPrinter::emitFunctionHeaderComment() {
498 const AArch64FunctionInfo *FI = MF->
getInfo<AArch64FunctionInfo>();
500 if (OutlinerString != std::nullopt)
501 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
504void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
507 if (
F.hasFnAttribute(
"patchable-function-entry")) {
509 if (
F.getFnAttribute(
"patchable-function-entry")
511 .getAsInteger(10, Num))
517 emitSled(
MI, SledKind::FUNCTION_ENTER);
520void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
521 emitSled(
MI, SledKind::FUNCTION_EXIT);
524void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
525 emitSled(
MI, SledKind::TAIL_CALL);
528void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
529 static const int8_t NoopsInSledCount = 7;
550 OutStreamer->emitCodeAlignment(
Align(4), getSubtargetInfo());
551 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
552 OutStreamer->emitLabel(CurSled);
553 auto Target = OutContext.createTempSymbol();
558 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
560 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
561 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
563 OutStreamer->emitLabel(Target);
564 recordSled(CurSled,
MI, Kind, 2);
567void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
570 AArch64TargetStreamer *TS) {
572 PAuthABIPlatform = (
uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
573 PAuthABIVersion = (
uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
575 if (PAuthABIPlatform || PAuthABIVersion) {
579 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
580 AArch64BuildAttributes::SubsectionType::ULEB128);
584 PAuthABIPlatform,
"");
598 if (BTIValue || PACValue || GCSValue) {
602 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
603 AArch64BuildAttributes::SubsectionType::ULEB128);
631void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
633 auto &
O = *OutStreamer;
634 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
635 O.emitLabel(CurSled);
636 bool MachO = MMI->getModule()->getTargetTriple().isOSBinFormatMachO();
638 OutContext.getOrCreateSymbol(
639 Twine(MachO ?
"_" :
"") +
640 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
643 O.AddComment(
"Begin XRay typed event");
644 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
645 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
651 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
655 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
656 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
657 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
658 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
659 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
663 O.AddComment(
"End XRay typed event");
664 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
671 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
673 O.AddComment(
"Begin XRay custom event");
674 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
675 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
681 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
682 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
683 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
684 O.AddComment(
"End XRay custom event");
685 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
692 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
696void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
698 assert(std::next(
MI.getIterator())->isCall() &&
699 "KCFI_CHECK not followed by a call instruction");
700 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
701 "KCFI_CHECK call target doesn't match call operand");
705 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
706 if (AddrReg == AArch64::XZR) {
710 emitMovXReg(AddrReg, AArch64::XZR);
716 for (
auto &
Reg : ScratchRegs) {
722 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
723 "Invalid scratch registers for KCFI_CHECK");
728 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
729 "patchable-function-prefix");
732 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
733 .addReg(ScratchRegs[0])
735 .addImm(-(PrefixNops * 4 + 4)));
739 const int64_t
Type =
MI.getOperand(1).getImm();
740 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
741 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
744 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
745 .addReg(AArch64::WZR)
746 .addReg(ScratchRegs[0])
747 .addReg(ScratchRegs[1])
751 EmitToStreamer(*OutStreamer,
752 MCInstBuilder(AArch64::Bcc)
761 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
765 AddrIndex = AddrReg - AArch64::X0;
775 assert(AddrIndex < 31 && TypeIndex < 31);
777 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
778 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
779 OutStreamer->emitLabel(
Pass);
782void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
790 if (
Reg == AArch64::XZR)
794 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
796 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
797 uint32_t AccessInfo =
MI.getOperand(1).getImm();
799 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
801 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
802 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
804 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
805 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
808 if (!TM.getTargetTriple().isOSBinFormatELF())
811 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
814 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
816 SymName +=
"_short_v2";
817 Sym = OutContext.getOrCreateSymbol(SymName);
820 EmitToStreamer(*OutStreamer,
821 MCInstBuilder(AArch64::BL)
825void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
826 if (HwasanMemaccessSymbols.empty())
829 const Triple &
TT =
M.getTargetTriple();
833 auto STI = std::make_unique<AArch64Subtarget>(
834 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
836 this->STI = STI.get();
839 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
841 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
843 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
845 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
848 for (
auto &
P : HwasanMemaccessSymbols) {
849 unsigned Reg = std::get<0>(
P.first);
850 bool IsShort = std::get<1>(
P.first);
851 uint32_t AccessInfo = std::get<2>(
P.first);
852 bool IsFixedShadow = std::get<3>(
P.first);
853 uint64_t FixedShadowOffset = std::get<4>(
P.first);
854 const MCSymbolRefExpr *HwasanTagMismatchRef =
855 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
858 bool HasMatchAllTag =
860 uint8_t MatchAllTag =
867 OutStreamer->switchSection(OutContext.getELFSection(
873 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
874 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
875 OutStreamer->emitLabel(Sym);
877 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
878 .addReg(AArch64::X16)
888 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
889 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
890 .addReg(AArch64::W16)
891 .addReg(AArch64::X17)
892 .addReg(AArch64::X16)
896 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
897 .addReg(AArch64::W16)
898 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
899 .addReg(AArch64::X16)
904 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
905 .addReg(AArch64::XZR)
906 .addReg(AArch64::X16)
909 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
910 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
913 HandleMismatchOrPartialSym, OutContext)));
914 MCSymbol *ReturnSym = OutContext.createTempSymbol();
915 OutStreamer->emitLabel(ReturnSym);
916 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
917 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
919 if (HasMatchAllTag) {
920 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
921 .addReg(AArch64::X17)
925 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
926 .addReg(AArch64::XZR)
927 .addReg(AArch64::X17)
931 MCInstBuilder(AArch64::Bcc)
937 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
938 .addReg(AArch64::WZR)
939 .addReg(AArch64::W16)
942 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
944 MCInstBuilder(AArch64::Bcc)
948 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
949 .addReg(AArch64::X17)
953 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
954 .addReg(AArch64::X17)
955 .addReg(AArch64::X17)
958 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
959 .addReg(AArch64::WZR)
960 .addReg(AArch64::W16)
961 .addReg(AArch64::W17)
964 MCInstBuilder(AArch64::Bcc)
968 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
969 .addReg(AArch64::X16)
972 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
973 .addReg(AArch64::W16)
974 .addReg(AArch64::X16)
977 MCInstBuilder(AArch64::SUBSXrs)
978 .addReg(AArch64::XZR)
979 .addReg(AArch64::X16)
983 MCInstBuilder(AArch64::Bcc)
987 OutStreamer->emitLabel(HandleMismatchSym);
990 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
996 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
1002 if (
Reg != AArch64::X0)
1003 emitMovXReg(AArch64::X0,
Reg);
1006 if (CompileKernel) {
1010 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
1015 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
1016 .addReg(AArch64::X16)
1020 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
1021 .addReg(AArch64::X16)
1022 .addReg(AArch64::X16)
1026 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1029 this->STI =
nullptr;
1034 const MCExpr *StubAuthPtrRef) {
1037 OutStreamer.
emitValue(StubAuthPtrRef, 8);
1040void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
1041 emitHwasanMemaccessSymbols(M);
1043 const Triple &
TT =
M.getTargetTriple();
1044 if (
TT.isOSBinFormatMachO()) {
1046 MachineModuleInfoMachO &MMIMacho =
1047 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1051 if (!Stubs.empty()) {
1053 OutStreamer->switchSection(
1056 emitAlignment(
Align(8));
1058 for (
const auto &Stub : Stubs)
1061 OutStreamer->addBlankLine();
1069 OutStreamer->emitSubsectionsViaSymbols();
1072 if (
TT.isOSBinFormatELF()) {
1074 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1078 if (!Stubs.empty()) {
1079 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1081 emitAlignment(
Align(8));
1083 for (
const auto &Stub : Stubs)
1086 OutStreamer->addBlankLine();
1097 M.getModuleFlag(
"ptrauth-elf-got"));
1098 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1099 for (
const GlobalValue &GV :
M.global_values())
1101 !GV.getName().starts_with(
"llvm."))
1102 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1111 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1112 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1115 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1116 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1127 for (
auto &[Section, CallsToImportedFuncs] :
1128 SectionToImportedFunctionCalls) {
1130 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1131 OutStreamer->emitInt32(SectionSize);
1132 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1133 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1135 OutStreamer->emitInt32(0x13);
1136 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1137 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1143void AArch64AsmPrinter::emitLOHs() {
1147 for (
const MachineInstr *
MI :
D.getArgs()) {
1148 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1149 assert(LabelIt != LOHInstToLabel.end() &&
1150 "Label hasn't been inserted for LOH related instruction");
1153 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1158void AArch64AsmPrinter::emitFunctionBodyEnd() {
1164MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1168 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1169 return OutContext.getOrCreateSymbol(
1170 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1171 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1176void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1178 const MachineOperand &MO =
MI->getOperand(OpNum);
1194 PrintSymbolOperand(MO, O);
1205bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1229bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1231 unsigned AltName, raw_ostream &O) {
1232 assert(MO.
isReg() &&
"Should only get here with a register!");
1233 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1242bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1243 const char *ExtraCode, raw_ostream &O) {
1244 const MachineOperand &MO =
MI->getOperand(OpNum);
1251 if (ExtraCode && ExtraCode[0]) {
1252 if (ExtraCode[1] != 0)
1255 switch (ExtraCode[0]) {
1263 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1277 switch (ExtraCode[0]) {
1279 RC = &AArch64::FPR8RegClass;
1282 RC = &AArch64::FPR16RegClass;
1285 RC = &AArch64::FPR32RegClass;
1288 RC = &AArch64::FPR64RegClass;
1291 RC = &AArch64::FPR128RegClass;
1294 RC = &AArch64::ZPRRegClass;
1299 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1320 unsigned AltName = AArch64::NoRegAltName;
1323 RegClass = &AArch64::ZPRRegClass;
1325 RegClass = &AArch64::PPRRegClass;
1327 RegClass = &AArch64::PNRRegClass;
1329 RegClass = &AArch64::FPR128RegClass;
1330 AltName = AArch64::vreg;
1334 return printAsmRegInClass(MO, RegClass, AltName, O);
1341bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1343 const char *ExtraCode,
1345 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1348 const MachineOperand &MO =
MI->getOperand(OpNum);
1349 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1354void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1356 unsigned NOps =
MI->getNumOperands();
1358 OS <<
'\t' << MAI.getCommentString() <<
"DEBUG_VALUE: ";
1360 OS <<
MI->getDebugVariable()->getName();
1363 assert(
MI->isIndirectDebugValue());
1375void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1376 ArrayRef<unsigned> JumpTableIndices) {
1378 if (JumpTableIndices.
empty())
1380 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1384 MCSection *ReadOnlySec =
nullptr;
1385 if (TM.Options.EnableStaticDataPartitioning) {
1391 OutStreamer->switchSection(ReadOnlySec);
1393 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1394 for (
unsigned JTI : JumpTableIndices) {
1395 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1398 if (JTBBs.empty())
continue;
1400 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1402 OutStreamer->emitLabel(GetJTISymbol(JTI));
1407 for (
auto *JTBB : JTBBs) {
1408 const MCExpr *
Value =
1427AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1428 const MachineInstr *BranchInstr,
1429 const MCSymbol *BranchLabel)
const {
1430 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1433 switch (AFI->getJumpTableEntrySize(JTI)) {
1435 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1438 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1441 EntrySize = codeview::JumpTableEntrySize::Int32;
1446 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1449void AArch64AsmPrinter::emitFunctionEntryLabel() {
1450 const Triple &
TT = TM.getTargetTriple();
1451 if (
TT.isOSBinFormatELF() &&
1454 CallingConv::AArch64_SVE_VectorCall ||
1455 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1457 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1468 OutStreamer->emitAssignment(
1472 auto getSymbolFromMetadata = [&](StringRef
Name) {
1476 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1483 for (MDNode *Node : UnmangledNames) {
1485 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1486 if (std::optional<std::string> MangledName =
1489 MMI->getContext().getOrCreateSymbol(*MangledName);
1490 emitFunctionAlias(UnmangledSym, ECMangledSym);
1493 if (MCSymbol *ECMangledSym =
1494 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1495 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1499void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1500 const Constant *CV) {
1503 "ctors/dtors are to be signed by asm printer");
1505 if (PtrauthInitFini) {
1511 ConstantInt *IntDisc = ConstantInt::get(
1515 if (PtrauthInitFiniAddressDisc) {
1529void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1530 const GlobalAlias &GA) {
1536 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1538 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1541 OutStreamer->beginCOFFSymbolDef(ExpSym);
1545 OutStreamer->endCOFFSymbolDef();
1547 OutStreamer->beginCOFFSymbolDef(Sym);
1551 OutStreamer->endCOFFSymbolDef();
1552 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1553 OutStreamer->emitAssignment(
1570void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1571 const llvm::MachineInstr &
MI) {
1572 Register DestReg =
MI.getOperand(0).getReg();
1573 Register ScratchReg =
MI.getOperand(1).getReg();
1575 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1576 Register TableReg =
MI.getOperand(2).getReg();
1577 Register EntryReg =
MI.getOperand(3).getReg();
1578 int JTIdx =
MI.getOperand(4).getIndex();
1584 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1595 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1597 .addExpr(LabelExpr));
1602 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1603 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1604 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1609 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1610 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1614 .addImm(
Size == 1 ? 0 : 1));
1618 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1622 .addImm(
Size == 4 ? 0 : 2));
1625void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1627 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1629 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1630 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1646 MachineOperand JTOp =
MI.getOperand(0);
1650 "unsupported compressed jump table");
1652 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1656 uint64_t MaxTableEntry = NumTableEntries - 1;
1658 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1659 .addReg(AArch64::XZR)
1660 .addReg(AArch64::X16)
1661 .addImm(MaxTableEntry)
1664 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1669 if ((MaxTableEntry >>
Offset) == 0)
1671 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1674 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1675 .addReg(AArch64::XZR)
1676 .addReg(AArch64::X16)
1677 .addReg(AArch64::X17)
1683 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1684 .addReg(AArch64::X16)
1685 .addReg(AArch64::X16)
1686 .addReg(AArch64::XZR)
1690 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1691 MCOperand JTMCHi, JTMCLo;
1701 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1703 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1704 .addReg(AArch64::X17)
1705 .addReg(AArch64::X17)
1709 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1710 .addReg(AArch64::X16)
1711 .addReg(AArch64::X17)
1712 .addReg(AArch64::X16)
1723 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1725 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1726 .addReg(AArch64::X16)
1727 .addReg(AArch64::X17)
1728 .addReg(AArch64::X16)
1731 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1734void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1735 const llvm::MachineInstr &
MI) {
1736 unsigned Opcode =
MI.getOpcode();
1738 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1740 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1741 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1742 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1743 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1744 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1745 if (Opcode == AArch64::MOPSMemorySetPseudo)
1746 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1747 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1748 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1751 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1752 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1754 for (
auto Op :
Ops) {
1756 auto MCIB = MCInstBuilder(
Op);
1758 MCIB.addReg(
MI.getOperand(i++).getReg());
1759 MCIB.addReg(
MI.getOperand(i++).getReg());
1761 MCIB.addReg(
MI.getOperand(i++).getReg());
1763 MCIB.addReg(
MI.getOperand(i++).getReg());
1764 MCIB.addReg(
MI.getOperand(i++).getReg());
1765 MCIB.addReg(
MI.getOperand(i++).getReg());
1767 EmitToStreamer(OutStreamer, MCIB);
1771void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1772 const MachineInstr &
MI) {
1773 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1776 MCSymbol *MILabel = Ctx.createTempSymbol();
1780 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1786 while (NumNOPBytes > 0) {
1787 if (MII ==
MBB.
end() || MII->isCall() ||
1788 MII->getOpcode() == AArch64::DBG_VALUE ||
1789 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1790 MII->getOpcode() == TargetOpcode::STACKMAP)
1797 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1798 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1803void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1804 const MachineInstr &
MI) {
1806 MCSymbol *MILabel = Ctx.createTempSymbol();
1810 PatchPointOpers Opers(&
MI);
1812 int64_t CallTarget = Opers.getCallTarget().getImm();
1813 unsigned EncodedBytes = 0;
1815 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1816 "High 16 bits of call target should be zero.");
1817 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1820 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1821 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1822 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1823 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1826 unsigned NumBytes = Opers.getNumPatchBytes();
1827 assert(NumBytes >= EncodedBytes &&
1828 "Patchpoint can't request size less than the length of a call.");
1829 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1830 "Invalid number of NOP bytes requested!");
1831 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1832 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1835void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1836 const MachineInstr &
MI) {
1837 StatepointOpers SOpers(&
MI);
1838 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1839 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1840 for (
unsigned i = 0; i < PatchBytes; i += 4)
1841 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1844 const MachineOperand &CallTarget = SOpers.getCallTarget();
1845 MCOperand CallTargetMCOp;
1846 unsigned CallOpcode;
1847 switch (CallTarget.
getType()) {
1850 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1851 CallOpcode = AArch64::BL;
1855 CallOpcode = AArch64::BL;
1859 CallOpcode = AArch64::BLR;
1866 EmitToStreamer(OutStreamer,
1867 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1871 MCSymbol *MILabel = Ctx.createTempSymbol();
1876void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1885 unsigned OperandsBeginIdx = 4;
1888 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1895 MI.setOpcode(Opcode);
1900 for (
const MachineOperand &MO :
1903 lowerOperand(MO, Dest);
1904 MI.addOperand(Dest);
1912 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1914 .addReg(AArch64::XZR)
1920 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1921 EmitToStreamer(*OutStreamer,
1922 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1929 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1930 EmitToStreamer(*OutStreamer,
1931 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1940 bool IsZeroDisc = Disc == AArch64::XZR;
1952 EmitToStreamer(AUTInst);
1957 bool IsZeroDisc = Disc == AArch64::XZR;
1969 EmitToStreamer(PACInst);
1974 bool IsZeroDisc = Disc == AArch64::XZR;
1984 EmitToStreamer(Inst);
1987void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1988 Register DestReg =
MI.getOperand(0).getReg();
1989 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1990 if (STI->hasZeroCycleZeroingFPR64()) {
1992 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1993 if (AArch64::FPR16RegClass.
contains(DestReg))
1994 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1995 &AArch64::FPR64RegClass);
1996 else if (AArch64::FPR32RegClass.
contains(DestReg))
1997 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1998 &AArch64::FPR64RegClass);
2006 EmitToStreamer(*OutStreamer, MOVI);
2007 ++NumZCZeroingInstrsFPR;
2008 }
else if (STI->hasZeroCycleZeroingFPR128()) {
2010 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2011 if (AArch64::FPR16RegClass.
contains(DestReg)) {
2012 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2013 &AArch64::FPR128RegClass);
2014 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
2015 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2016 &AArch64::FPR128RegClass);
2019 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
2020 &AArch64::FPR128RegClass);
2027 EmitToStreamer(*OutStreamer, MOVI);
2028 ++NumZCZeroingInstrsFPR;
2030 emitFMov0AsFMov(
MI, DestReg);
2033 emitFMov0AsFMov(
MI, DestReg);
2037void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
2040 switch (
MI.getOpcode()) {
2043 case AArch64::FMOVH0:
2044 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
2045 if (!STI->hasFullFP16())
2046 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
2050 case AArch64::FMOVS0:
2055 case AArch64::FMOVD0:
2061 EmitToStreamer(*OutStreamer, FMov);
2067 bool MayClobberAddrDisc) {
2068 assert(isPtrauthRegSafe(ScratchReg) &&
2069 "Safe scratch register must be provided by the caller");
2074 AddrDisc = AArch64::XZR;
2082 if (AddrDisc == AArch64::XZR) {
2083 emitMOVZ(ScratchReg, Disc, 0);
2090 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2091 ScratchReg = AddrDisc;
2093 emitMovXReg(ScratchReg, AddrDisc);
2094 assert(ScratchReg != AddrDisc &&
2095 "Forbidden to clobber AddrDisc, but have to");
2098 emitMOVK(ScratchReg, Disc, 48);
2112void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2144 if (Method == AuthCheckMethod::None)
2146 if (Method == AuthCheckMethod::DummyLoad) {
2147 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2151 assert(!OnFailure &&
"DummyLoad always traps on error");
2155 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2156 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2158 emitMovXReg(ScratchReg, TestedReg);
2160 if (Method == AuthCheckMethod::XPAC) {
2164 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2169 assert(TestedReg == AArch64::LR &&
2170 "XPACHint mode is only compatible with checking the LR register");
2172 "XPACHint mode is only compatible with I-keys");
2173 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2177 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2178 .addReg(AArch64::XZR)
2185 MCInstBuilder(AArch64::Bcc)
2188 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2190 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2197 MCInstBuilder(AArch64::TBZX)
2208 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2222 case AuthCheckMethod::XPACHint:
2225 case AuthCheckMethod::XPAC:
2227 emitMovXReg(TestedReg, ScratchReg);
2234 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2239 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2251void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2255 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2256 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2259 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2263 "Neither x16 nor x17 is available as a scratch register");
2266 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2270bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2276 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2279 MCSymbol *Dot = OutContext.createTempSymbol();
2284 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2290AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateImmReg(
2292 PtrAuthSchema Schema;
2294 Schema.IntDisc = IntDisc;
2295 Schema.AddrDisc = AddrDiscOp.
getReg();
2296 Schema.AddrDiscIsKilled = AddrDiscOp.
isKill();
2301AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateRegReg(
2303 assert(PCDisc.
isValid() &&
"Use CreateImmReg for non-PC schemas");
2304 PtrAuthSchema Schema;
2307 Schema.AddrDisc = AddrDisc;
2308 Schema.AddrDiscIsKilled =
false;
2309 Schema.PCDisc = PCDisc;
2313void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2318 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2328 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2330 MCInstBuilder(AArch64::ADDXri)
2333 .addImm((Addend >> BitPos) & 0xfff)
2339 emitMOVZ(Scratch, Addend & 0xffff, 0);
2346 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2353 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2359 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2370 if (std::optional<PtrauthCheckMode>
Mode =
2377 return PtrauthCheckMode::Unchecked;
2380 return ShouldTrap ? PtrauthCheckMode::Trap : PtrauthCheckMode::Poison;
2411void AArch64AsmPrinter::emitPtrauthAuthResign(
2413 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2416 const bool IsAuthWithPC = AuthSchema.PCDisc.isValid();
2417 assert(!SignSchema || !SignSchema->PCDisc.isValid());
2419 Register SignAddrDiscOrNone = SignSchema ? SignSchema->AddrDisc :
Register();
2425 assert(Pointer == AArch64::X17 && Scratch == AArch64::X16 &&
2426 "AUTPCPAC must use x17/x16 as Pointer/Scratch");
2428 assert(AuthSchema.AddrDisc == AArch64::X16 &&
2429 "AUTPCPAC requires address discriminator in X16");
2431 assert(AuthSchema.PCDisc == AArch64::X15 &&
2432 "AUTPCPAC requires PC discriminator in X15");
2434 assert(AuthSchema.IntDisc == 0 &&
"AUTPCPAC does not support IntDisc");
2438 "AUTPCPAC only supports AUT-ing with IA/IB");
2440 if (!emitDeactivationSymbolRelocation(DS)) {
2442 ? AArch64::AUTIB171615
2443 : AArch64::AUTIA171615;
2444 EmitToStreamer(MCInstBuilder(AutOpc));
2454 Register AUTDiscReg = emitPtrauthDiscriminator(
2455 AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2456 AuthSchema.addrDiscIsKilledAndNoneOf({Pointer, SignAddrDiscOrNone}));
2457 if (!emitDeactivationSymbolRelocation(DS))
2458 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2463 auto EmitCheck = [&](
MCSymbol *OnFailure =
nullptr) {
2464 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2465 AArch64PAuth::AuthCheckMethod::XPAC,
2469 auto EmitResignOnSuccess = [&]() {
2470 if (Addend.has_value())
2471 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2473 assert(Pointer != SignSchema->AddrDisc &&
"Pointer is early-clobbered");
2475 emitPtrauthDiscriminator(SignSchema->IntDisc, SignSchema->AddrDisc,
2476 Scratch, SignSchema->AddrDiscIsKilled);
2477 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2483 if (CheckMode == PtrauthCheckMode::Trap)
2489 switch (CheckMode) {
2490 case PtrauthCheckMode::Unchecked:
2491 EmitResignOnSuccess();
2493 case PtrauthCheckMode::Trap:
2495 EmitResignOnSuccess();
2497 case PtrauthCheckMode::Poison:
2498 MCSymbol *OnFailure = createTempSymbol(
"resign_end_");
2499 EmitCheck(OnFailure);
2500 EmitResignOnSuccess();
2506void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2510 Register AddrDisc =
MI->getOperand(4).getReg();
2511 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2515 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2516 assert(ScratchReg != AddrDisc &&
2517 "Neither X16 nor X17 is available as a scratch register");
2520 Register DiscReg = emitPtrauthDiscriminator(
2521 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2523 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2526 emitPAC(
Key, Val, DiscReg);
2529void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2530 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2531 unsigned BrTarget =
MI->getOperand(0).getReg();
2536 unsigned AddrDisc =
MI->getOperand(3).getReg();
2542 if (BrTarget == AddrDisc)
2559 bool AddrDiscIsImplicitDef =
2560 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2561 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2562 AddrDiscIsImplicitDef);
2563 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2566void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2570 const bool IsNeg = Addend < 0;
2572 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2575 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2578 .addImm((AbsOffset >> BitPos) & 0xfff)
2583 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2585 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2587 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2588 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2589 uint64_t Shifted = UAddend >> BitPos;
2591 return Shifted != 0;
2592 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2593 if (((Shifted >>
I) & 0xffff) != 0xffff)
2597 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2598 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2600 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2609void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2610 MCRegister Tmp,
bool DSOLocal,
2611 const MCSubtargetInfo &STI) {
2617 MCInstBuilder(AArch64::ADRP)
2621 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2631 MCInstBuilder(AArch64::ADRP)
2636 MCInstBuilder(AArch64::LDRXui)
2647 if (!TT.isOSBinFormatELF())
2651 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2652 TT.isOSDragonFly() || TT.isOSNetBSD();
2706const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2708 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2709 const Triple &
TT = TM.getTargetTriple();
2721 auto STI = std::make_unique<AArch64Subtarget>(
2722 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2724 this->STI = STI.get();
2730 const MCSymbolELF *Group =
2745 .addReg(AArch64::X0)
2750 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2752 if (HasAddressDiversity) {
2757 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2761 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2763 "' out of range [0, 0xFFFF]");
2765 emitMOVZ(AArch64::X1, Disc, 0);
2772 auto *PrePACInstExpr =
2784 const MCSymbolRefExpr *EmuPACRef =
2786 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2793 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2802AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2803 MCContext &Ctx = OutContext;
2808 getDataLayout(),
Offset,
true);
2828 const MCExpr *DSExpr =
nullptr;
2840 "' out of range [0, " +
2848 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2850 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2855 "' out of range [0, 0xFFFF]");
2861 "expressions on this target");
2868void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2869 unsigned DstReg =
MI.getOperand(0).getReg();
2870 const MachineOperand &GAOp =
MI.getOperand(1);
2871 const uint64_t KeyC =
MI.getOperand(2).getImm();
2873 "key is out of range [0, AArch64PACKey::LAST]");
2875 const uint64_t Disc =
MI.getOperand(3).getImm();
2877 "constant discriminator is out of range [0, 0xffff]");
2886 if (TM.getTargetTriple().isOSBinFormatELF()) {
2888 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2891 "non-zero offset for $auth_ptr$ stub slots is not supported");
2893 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2895 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2896 "LOADauthptrstatic is implemented only for MachO/ELF");
2898 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2899 getObjFileLowering());
2902 "non-zero offset for $auth_ptr$ stub slots is not supported");
2904 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2907 MachineOperand StubMOHi =
2911 MCOperand StubMCHi, StubMCLo;
2918 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2920 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2926void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2927 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2928 const bool IsELFSignedGOT =
MI.getParent()
2930 ->getInfo<AArch64FunctionInfo>()
2931 ->hasELFSignedGOT();
2932 MachineOperand GAOp =
MI.getOperand(0);
2933 const uint64_t KeyC =
MI.getOperand(1).getImm();
2935 "key is out of range [0, AArch64PACKey::LAST]");
2937 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2938 const uint64_t Disc =
MI.getOperand(3).getImm();
2985 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2986 MCOperand GAMCHi, GAMCLo;
2999 MCInstBuilder(AArch64::ADRP)
3000 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
3004 if (IsELFSignedGOT) {
3005 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3006 .addReg(AArch64::X17)
3007 .addReg(AArch64::X17)
3011 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3012 .addReg(AArch64::X16)
3013 .addReg(AArch64::X17)
3021 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
3023 if (!STI->hasFPAC())
3024 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
3025 AArch64PAuth::AuthCheckMethod::XPAC);
3027 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3028 .addReg(AArch64::X16)
3029 .addReg(AArch64::X16)
3033 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3034 .addReg(AArch64::X16)
3035 .addReg(AArch64::X16)
3040 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
3041 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
3043 emitPAC(
Key, AArch64::X16, DiscReg);
3046void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
3048 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
3049 const MachineOperand &GAMO =
MI.getOperand(1);
3056 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
3057 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3058 .addReg(AuthResultReg)
3059 .addReg(AArch64::X17)
3062 MachineOperand GAHiOp(GAMO);
3063 MachineOperand GALoOp(GAMO);
3067 MCOperand GAMCHi, GAMCLo;
3072 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
3074 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3075 .addReg(AArch64::X17)
3076 .addReg(AArch64::X17)
3080 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3081 .addReg(AuthResultReg)
3082 .addReg(AArch64::X17)
3089 UndefWeakSym = createTempSymbol(
"undef_weak");
3091 MCInstBuilder(AArch64::CBZX)
3092 .addReg(AuthResultReg)
3100 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
3105 if (!STI->hasFPAC()) {
3106 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
3107 AArch64PAuth::AuthCheckMethod::XPAC);
3109 emitMovXReg(DstReg, AuthResultReg);
3114AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
3118 if (std::optional<uint16_t> BADisc =
3119 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3126void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3130 switch (
MI->getOpcode()) {
3133 case AArch64::CBBAssertExt:
3137 case AArch64::CBHAssertExt:
3141 case AArch64::CBWPrr:
3144 case AArch64::CBXPrr:
3147 case AArch64::CBWPri:
3151 case AArch64::CBXPri:
3159 bool NeedsRegSwap =
false;
3160 bool NeedsImmDec =
false;
3161 bool NeedsImmInc =
false;
3163#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3165 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3167 ? AArch64::CBB##RegCond##Wrr \
3168 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3169 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3170 : AArch64::CB##RegCond##Xrr))))
3186 NeedsImmDec = IsImm;
3190 NeedsRegSwap = !IsImm;
3197 NeedsRegSwap = !IsImm;
3198 NeedsImmInc = IsImm;
3202 NeedsImmDec = IsImm;
3206 NeedsRegSwap = !IsImm;
3213 NeedsRegSwap = !IsImm;
3214 NeedsImmInc = IsImm;
3222 MCOperand Lhs, Rhs, Trgt;
3223 lowerOperand(
MI->getOperand(1), Lhs);
3224 lowerOperand(
MI->getOperand(2), Rhs);
3225 lowerOperand(
MI->getOperand(3), Trgt);
3229 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3230 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3233 }
else if (NeedsImmDec) {
3237 }
else if (NeedsImmInc) {
3247 "CB immediate operand out-of-bounds");
3250 EmitToStreamer(*OutStreamer, Inst);
3253void AArch64AsmPrinter::emitAtomicHintPseudoExpansion(
const MachineInstr *
MI) {
3256 unsigned Relaxed =
MI->getOperand(2).getImm();
3257 assert(
Relaxed < 2 &&
"Atomic hint relaxed immediate out-of-bounds");
3258 switch (
MI->getOpcode()) {
3259 case AArch64::ATOMIC_STORE_HINT_B:
3260 StOpc =
Relaxed ? AArch64::STRBBui : AArch64::STLRB;
3262 case AArch64::ATOMIC_STORE_HINT_H:
3263 StOpc =
Relaxed ? AArch64::STRHHui : AArch64::STLRH;
3265 case AArch64::ATOMIC_STORE_HINT_W:
3266 StOpc =
Relaxed ? AArch64::STRWui : AArch64::STLRW;
3268 case AArch64::ATOMIC_STORE_HINT_X:
3269 StOpc =
Relaxed ? AArch64::STRXui : AArch64::STLRX;
3276 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(3).getImm()));
3279 Store.setOpcode(StOpc);
3282 Store.setFlags(
MI->getFlags());
3285 EmitToStreamer(*OutStreamer,
Store);
3288void AArch64AsmPrinter::emitAtomicHintPseudoExpansionRO(
3289 const MachineInstr *
MI) {
3291 assert(
MI->getOperand(5).getImm() == 1 &&
3292 "Atomic store addressing mode only supports relaxed stores");
3294 switch (
MI->getOpcode()) {
3295 case AArch64::ATOMIC_STORE_HINT_BroW:
3296 StOpc = AArch64::STRBBroW;
3298 case AArch64::ATOMIC_STORE_HINT_HroW:
3299 StOpc = AArch64::STRHHroW;
3301 case AArch64::ATOMIC_STORE_HINT_WroW:
3302 StOpc = AArch64::STRWroW;
3304 case AArch64::ATOMIC_STORE_HINT_XroW:
3305 StOpc = AArch64::STRXroW;
3307 case AArch64::ATOMIC_STORE_HINT_SroW:
3308 StOpc = AArch64::STRSroW;
3310 case AArch64::ATOMIC_STORE_HINT_DroW:
3311 StOpc = AArch64::STRDroW;
3313 case AArch64::ATOMIC_STORE_HINT_BroX:
3314 StOpc = AArch64::STRBBroX;
3316 case AArch64::ATOMIC_STORE_HINT_HroX:
3317 StOpc = AArch64::STRHHroX;
3319 case AArch64::ATOMIC_STORE_HINT_WroX:
3320 StOpc = AArch64::STRWroX;
3322 case AArch64::ATOMIC_STORE_HINT_XroX:
3323 StOpc = AArch64::STRXroX;
3325 case AArch64::ATOMIC_STORE_HINT_SroX:
3326 StOpc = AArch64::STRSroX;
3328 case AArch64::ATOMIC_STORE_HINT_DroX:
3329 StOpc = AArch64::STRDroX;
3336 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(6).getImm()));
3339 Store.setOpcode(StOpc);
3345 Store.setFlags(
MI->getFlags());
3346 EmitToStreamer(*OutStreamer,
Store);
3349void AArch64AsmPrinter::emitAtomicHintPseudoExpansionImm(
3350 const MachineInstr *
MI) {
3352 assert(
MI->getOperand(3).getImm() == 1 &&
3353 "Atomic store addressing mode only supports relaxed stores");
3355 switch (
MI->getOpcode()) {
3356 case AArch64::ATOMIC_STORE_HINT_Bui:
3357 StOpc = AArch64::STRBBui;
3359 case AArch64::ATOMIC_STORE_HINT_Hui:
3360 StOpc = AArch64::STRHHui;
3362 case AArch64::ATOMIC_STORE_HINT_Wui:
3363 StOpc = AArch64::STRWui;
3365 case AArch64::ATOMIC_STORE_HINT_Xui:
3366 StOpc = AArch64::STRXui;
3368 case AArch64::ATOMIC_STORE_HINT_Sui:
3369 StOpc = AArch64::STRSui;
3371 case AArch64::ATOMIC_STORE_HINT_Dui:
3372 StOpc = AArch64::STRDui;
3374 case AArch64::ATOMIC_STORE_HINT_Bi:
3375 StOpc = AArch64::STURBBi;
3377 case AArch64::ATOMIC_STORE_HINT_Hi:
3378 StOpc = AArch64::STURHHi;
3380 case AArch64::ATOMIC_STORE_HINT_Wi:
3381 StOpc = AArch64::STURWi;
3383 case AArch64::ATOMIC_STORE_HINT_Xi:
3384 StOpc = AArch64::STURXi;
3386 case AArch64::ATOMIC_STORE_HINT_Si:
3387 StOpc = AArch64::STURSi;
3389 case AArch64::ATOMIC_STORE_HINT_Di:
3390 StOpc = AArch64::STURDi;
3397 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(4).getImm()));
3400 Store.setOpcode(StOpc);
3404 Store.setFlags(
MI->getFlags());
3405 EmitToStreamer(*OutStreamer,
Store);
3408void AArch64AsmPrinter::emitAtomicFetchHintPseudoExpansion(
3409 const MachineInstr *
MI) {
3411 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(4).getImm()));
3419 EmitToStreamer(*OutStreamer, Fetch);
3424#include "AArch64GenMCPseudoLowering.inc"
3426void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3433void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3434 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3439 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3444 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3445 EmitToStreamer(*OutStreamer, OutInst);
3449 if (
MI->getOpcode() == AArch64::ADRP) {
3450 for (
auto &Opd :
MI->operands()) {
3451 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3452 "swift_async_extendedFramePointerFlags") {
3453 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3460 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3462 LOHInstToLabel[
MI] = LOHLabel;
3466 AArch64TargetStreamer *TS =
3469 switch (
MI->getOpcode()) {
3472 "Unhandled tail call instruction");
3474 case AArch64::READ_REGISTER_GPR64:
3478 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
3479 .addReg(
MI->getOperand(0).getReg())
3480 .addReg(AArch64::XZR)
3481 .addReg(
MI->getOperand(1).getImm())
3484 case AArch64::READ_REGISTER_FPR64:
3486 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::FMOVDr)
3487 .addReg(
MI->getOperand(0).getReg())
3488 .addReg(
MI->getOperand(1).getImm()));
3490 case AArch64::HINT: {
3495 if (CurrentPatchableFunctionEntrySym &&
3496 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3498 int64_t
Imm =
MI->getOperand(0).getImm();
3499 if (
Imm == 32 ||
Imm == 34 ||
Imm == 36 ||
Imm == 38) {
3501 MCInstLowering.
Lower(
MI, Inst);
3502 EmitToStreamer(*OutStreamer, Inst);
3503 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3504 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3510 case AArch64::MOVMCSym: {
3511 Register DestReg =
MI->getOperand(0).getReg();
3512 const MachineOperand &MO_Sym =
MI->getOperand(1);
3513 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3514 MCOperand Hi_MCSym, Lo_MCSym;
3527 EmitToStreamer(*OutStreamer, MovZ);
3535 EmitToStreamer(*OutStreamer, MovK);
3538 case AArch64::MOVIv2d_ns:
3546 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3547 MI->getOperand(1).getImm() == 0) {
3549 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3552 EmitToStreamer(*OutStreamer, TmpInst);
3557 case AArch64::DBG_VALUE:
3558 case AArch64::DBG_VALUE_LIST:
3560 SmallString<128> TmpStr;
3561 raw_svector_ostream OS(TmpStr);
3562 PrintDebugValueComment(
MI, OS);
3567 case AArch64::EMITBKEY: {
3569 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3570 ExceptionHandlingType != ExceptionHandling::ARM)
3573 if (getFunctionCFISectionType(*MF) == CFISection::None)
3580 case AArch64::EMITMTETAGGED: {
3582 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3583 ExceptionHandlingType != ExceptionHandling::ARM)
3586 if (getFunctionCFISectionType(*MF) != CFISection::None)
3591 case AArch64::AUTx16x17: {
3593 const Register Scratch = AArch64::X17;
3595 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3597 MI->getOperand(1).getImm(),
MI->getOperand(2));
3599 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3600 std::nullopt,
MI->getDeactivationSymbol());
3604 case AArch64::AUTxMxN: {
3606 const Register Scratch =
MI->getOperand(1).getReg();
3608 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3610 MI->getOperand(4).getImm(),
MI->getOperand(5));
3612 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3613 std::nullopt,
MI->getDeactivationSymbol());
3617 case AArch64::AUTPAC: {
3619 const Register Scratch = AArch64::X17;
3621 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3623 MI->getOperand(1).getImm(),
MI->getOperand(2));
3625 auto SignSchema = PtrAuthSchema::CreateImmReg(
3627 MI->getOperand(4).getImm(),
MI->getOperand(5));
3629 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3630 std::nullopt,
MI->getDeactivationSymbol());
3634 case AArch64::AUTPCPAC: {
3635 auto AuthSchema = PtrAuthSchema::CreateRegReg(
3639 auto SignSchema = PtrAuthSchema::CreateImmReg(
3641 MI->getOperand(2).getImm(),
MI->getOperand(3));
3643 emitPtrauthAuthResign(AArch64::X17, AArch64::X16,
3644 AuthSchema, SignSchema, std::nullopt,
3645 MI->getDeactivationSymbol());
3649 case AArch64::AUTRELLOADPAC: {
3651 const Register Scratch = AArch64::X17;
3653 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3655 MI->getOperand(1).getImm(),
MI->getOperand(2));
3657 auto SignSchema = PtrAuthSchema::CreateImmReg(
3659 MI->getOperand(4).getImm(),
MI->getOperand(5));
3661 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3662 MI->getOperand(6).getImm(),
3663 MI->getDeactivationSymbol());
3669 emitPtrauthSign(
MI);
3672 case AArch64::LOADauthptrstatic:
3673 LowerLOADauthptrstatic(*
MI);
3676 case AArch64::LOADgotPAC:
3677 case AArch64::MOVaddrPAC:
3678 LowerMOVaddrPAC(*
MI);
3681 case AArch64::LOADgotAUTH:
3682 LowerLOADgotAUTH(*
MI);
3687 emitPtrauthBranch(
MI);
3693 case AArch64::AUTH_TCRETURN:
3694 case AArch64::AUTH_TCRETURN_BTI: {
3697 const uint64_t Disc =
MI->getOperand(3).getImm();
3699 Register AddrDisc =
MI->getOperand(4).getReg();
3701 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3703 emitPtrauthTailCallHardening(
MI);
3706 if (Callee == AddrDisc)
3713 bool AddrDiscIsImplicitDef =
3714 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3715 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3716 AddrDiscIsImplicitDef);
3717 emitBLRA(
false,
Key, Callee, DiscReg);
3721 case AArch64::TCRETURNri:
3722 case AArch64::TCRETURNrix16x17:
3723 case AArch64::TCRETURNrix17:
3724 case AArch64::TCRETURNrinotx16:
3725 case AArch64::TCRETURNriALL: {
3726 emitPtrauthTailCallHardening(
MI);
3728 recordIfImportCall(
MI);
3732 EmitToStreamer(*OutStreamer, TmpInst);
3735 case AArch64::TCRETURNdi: {
3736 emitPtrauthTailCallHardening(
MI);
3740 recordIfImportCall(
MI);
3744 EmitToStreamer(*OutStreamer, TmpInst);
3747 case AArch64::SpeculationBarrierISBDSBEndBB: {
3752 EmitToStreamer(*OutStreamer, TmpInstDSB);
3756 EmitToStreamer(*OutStreamer, TmpInstISB);
3759 case AArch64::SpeculationBarrierSBEndBB: {
3763 EmitToStreamer(*OutStreamer, TmpInstSB);
3766 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3774 const MachineOperand &MO_Sym =
MI->getOperand(0);
3775 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3776 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3780 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3787 EmitToStreamer(*OutStreamer, Adrp);
3795 EmitToStreamer(*OutStreamer, Ldr);
3798 Add.setOpcode(AArch64::ADDXri);
3801 Add.addOperand(SymTLSDescLo12);
3803 EmitToStreamer(*OutStreamer,
Add);
3807 MCInst TLSAuthDescCall;
3808 TLSAuthDescCall.
setOpcode(AArch64::TLSAUTHDESCCALL);
3810 EmitToStreamer(*OutStreamer, TLSAuthDescCall);
3819 EmitToStreamer(*OutStreamer, Blraa);
3823 case AArch64::TLSDESC_CALLSEQ: {
3831 const MachineOperand &MO_Sym =
MI->getOperand(0);
3832 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3833 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3837 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3844 EmitToStreamer(*OutStreamer, Adrp);
3847 if (STI->isTargetILP32()) {
3857 EmitToStreamer(*OutStreamer, Ldr);
3860 if (STI->isTargetILP32()) {
3861 Add.setOpcode(AArch64::ADDWri);
3865 Add.setOpcode(AArch64::ADDXri);
3869 Add.addOperand(SymTLSDescLo12);
3871 EmitToStreamer(*OutStreamer,
Add);
3876 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3878 EmitToStreamer(*OutStreamer, TLSDescCall);
3886 EmitToStreamer(*OutStreamer, Blr);
3891 case AArch64::JumpTableDest32:
3892 case AArch64::JumpTableDest16:
3893 case AArch64::JumpTableDest8:
3894 LowerJumpTableDest(*OutStreamer, *
MI);
3897 case AArch64::BR_JumpTable:
3898 LowerHardenedBRJumpTable(*
MI);
3901 case AArch64::FMOVH0:
3902 case AArch64::FMOVS0:
3903 case AArch64::FMOVD0:
3907 case AArch64::MOPSMemoryCopyPseudo:
3908 case AArch64::MOPSMemoryMovePseudo:
3909 case AArch64::MOPSMemorySetPseudo:
3910 case AArch64::MOPSMemorySetTaggingPseudo:
3911 LowerMOPS(*OutStreamer, *
MI);
3914 case TargetOpcode::STACKMAP:
3915 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3917 case TargetOpcode::PATCHPOINT:
3918 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3920 case TargetOpcode::STATEPOINT:
3921 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3923 case TargetOpcode::FAULTING_OP:
3924 return LowerFAULTING_OP(*
MI);
3926 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3927 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3930 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3931 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3934 case TargetOpcode::PATCHABLE_TAIL_CALL:
3935 LowerPATCHABLE_TAIL_CALL(*
MI);
3937 case TargetOpcode::PATCHABLE_EVENT_CALL:
3938 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3939 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3940 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3942 case AArch64::KCFI_CHECK:
3943 LowerKCFI_CHECK(*
MI);
3946 case AArch64::HWASAN_CHECK_MEMACCESS:
3947 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3948 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3949 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3950 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3953 case AArch64::SEH_StackAlloc:
3957 case AArch64::SEH_SaveFPLR:
3961 case AArch64::SEH_SaveFPLR_X:
3962 assert(
MI->getOperand(0).getImm() < 0 &&
3963 "Pre increment SEH opcode must have a negative offset");
3967 case AArch64::SEH_SaveReg:
3969 MI->getOperand(1).getImm());
3972 case AArch64::SEH_SaveReg_X:
3973 assert(
MI->getOperand(1).getImm() < 0 &&
3974 "Pre increment SEH opcode must have a negative offset");
3976 -
MI->getOperand(1).getImm());
3979 case AArch64::SEH_SaveRegP:
3980 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3981 MI->getOperand(0).getImm() <= 28) {
3982 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3983 "Register paired with LR must be odd");
3985 MI->getOperand(2).getImm());
3988 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3989 "Non-consecutive registers not allowed for save_regp");
3991 MI->getOperand(2).getImm());
3994 case AArch64::SEH_SaveRegP_X:
3995 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3996 "Non-consecutive registers not allowed for save_regp_x");
3997 assert(
MI->getOperand(2).getImm() < 0 &&
3998 "Pre increment SEH opcode must have a negative offset");
4000 -
MI->getOperand(2).getImm());
4003 case AArch64::SEH_SaveFReg:
4005 MI->getOperand(1).getImm());
4008 case AArch64::SEH_SaveFReg_X:
4009 assert(
MI->getOperand(1).getImm() < 0 &&
4010 "Pre increment SEH opcode must have a negative offset");
4012 -
MI->getOperand(1).getImm());
4015 case AArch64::SEH_SaveFRegP:
4016 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4017 "Non-consecutive registers not allowed for save_regp");
4019 MI->getOperand(2).getImm());
4022 case AArch64::SEH_SaveFRegP_X:
4023 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4024 "Non-consecutive registers not allowed for save_regp_x");
4025 assert(
MI->getOperand(2).getImm() < 0 &&
4026 "Pre increment SEH opcode must have a negative offset");
4028 -
MI->getOperand(2).getImm());
4031 case AArch64::SEH_SetFP:
4035 case AArch64::SEH_AddFP:
4039 case AArch64::SEH_Nop:
4043 case AArch64::SEH_PrologEnd:
4047 case AArch64::SEH_EpilogStart:
4051 case AArch64::SEH_EpilogEnd:
4055 case AArch64::SEH_PACSignLR:
4059 case AArch64::SEH_SaveAnyRegI:
4060 assert(
MI->getOperand(1).getImm() <= 1008 &&
4061 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4063 MI->getOperand(1).getImm());
4066 case AArch64::SEH_SaveAnyRegIP:
4067 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4068 "Non-consecutive registers not allowed for save_any_reg");
4069 assert(
MI->getOperand(2).getImm() <= 1008 &&
4070 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4072 MI->getOperand(2).getImm());
4075 case AArch64::SEH_SaveAnyRegQP:
4076 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4077 "Non-consecutive registers not allowed for save_any_reg");
4078 assert(
MI->getOperand(2).getImm() >= 0 &&
4079 "SaveAnyRegQP SEH opcode offset must be non-negative");
4080 assert(
MI->getOperand(2).getImm() <= 1008 &&
4081 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4083 MI->getOperand(2).getImm());
4086 case AArch64::SEH_SaveAnyRegQPX:
4087 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4088 "Non-consecutive registers not allowed for save_any_reg");
4089 assert(
MI->getOperand(2).getImm() < 0 &&
4090 "SaveAnyRegQPX SEH opcode offset must be negative");
4091 assert(
MI->getOperand(2).getImm() >= -1008 &&
4092 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
4094 -
MI->getOperand(2).getImm());
4097 case AArch64::SEH_AllocZ:
4098 assert(
MI->getOperand(0).getImm() >= 0 &&
4099 "AllocZ SEH opcode offset must be non-negative");
4100 assert(
MI->getOperand(0).getImm() <= 255 &&
4101 "AllocZ SEH opcode offset must fit into 8 bits");
4105 case AArch64::SEH_SaveZReg:
4106 assert(
MI->getOperand(1).getImm() >= 0 &&
4107 "SaveZReg SEH opcode offset must be non-negative");
4108 assert(
MI->getOperand(1).getImm() <= 255 &&
4109 "SaveZReg SEH opcode offset must fit into 8 bits");
4111 MI->getOperand(1).getImm());
4114 case AArch64::SEH_SavePReg:
4115 assert(
MI->getOperand(1).getImm() >= 0 &&
4116 "SavePReg SEH opcode offset must be non-negative");
4117 assert(
MI->getOperand(1).getImm() <= 255 &&
4118 "SavePReg SEH opcode offset must fit into 8 bits");
4120 MI->getOperand(1).getImm());
4125 recordIfImportCall(
MI);
4127 MCInstLowering.
Lower(
MI, TmpInst);
4128 EmitToStreamer(*OutStreamer, TmpInst);
4131 case AArch64::CBWPri:
4132 case AArch64::CBXPri:
4133 case AArch64::CBBAssertExt:
4134 case AArch64::CBHAssertExt:
4135 case AArch64::CBWPrr:
4136 case AArch64::CBXPrr:
4137 emitCBPseudoExpansion(
MI);
4139 case AArch64::ATOMIC_STORE_HINT_B:
4140 case AArch64::ATOMIC_STORE_HINT_H:
4141 case AArch64::ATOMIC_STORE_HINT_W:
4142 case AArch64::ATOMIC_STORE_HINT_X:
4143 emitAtomicHintPseudoExpansion(
MI);
4145 case AArch64::ATOMIC_FETCH_HINT_W:
4146 case AArch64::ATOMIC_FETCH_HINT_X:
4147 emitAtomicFetchHintPseudoExpansion(
MI);
4149 case AArch64::ATOMIC_STORE_HINT_BroW:
4150 case AArch64::ATOMIC_STORE_HINT_HroW:
4151 case AArch64::ATOMIC_STORE_HINT_WroW:
4152 case AArch64::ATOMIC_STORE_HINT_XroW:
4153 case AArch64::ATOMIC_STORE_HINT_SroW:
4154 case AArch64::ATOMIC_STORE_HINT_DroW:
4155 case AArch64::ATOMIC_STORE_HINT_BroX:
4156 case AArch64::ATOMIC_STORE_HINT_HroX:
4157 case AArch64::ATOMIC_STORE_HINT_WroX:
4158 case AArch64::ATOMIC_STORE_HINT_XroX:
4159 case AArch64::ATOMIC_STORE_HINT_SroX:
4160 case AArch64::ATOMIC_STORE_HINT_DroX:
4161 emitAtomicHintPseudoExpansionRO(
MI);
4163 case AArch64::ATOMIC_STORE_HINT_Bui:
4164 case AArch64::ATOMIC_STORE_HINT_Hui:
4165 case AArch64::ATOMIC_STORE_HINT_Wui:
4166 case AArch64::ATOMIC_STORE_HINT_Xui:
4167 case AArch64::ATOMIC_STORE_HINT_Sui:
4168 case AArch64::ATOMIC_STORE_HINT_Dui:
4169 case AArch64::ATOMIC_STORE_HINT_Bi:
4170 case AArch64::ATOMIC_STORE_HINT_Hi:
4171 case AArch64::ATOMIC_STORE_HINT_Wi:
4172 case AArch64::ATOMIC_STORE_HINT_Xi:
4173 case AArch64::ATOMIC_STORE_HINT_Si:
4174 case AArch64::ATOMIC_STORE_HINT_Di:
4175 emitAtomicHintPseudoExpansionImm(
MI);
4179 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
4184 MCInstLowering.
Lower(
MI, TmpInst);
4185 EmitToStreamer(*OutStreamer, TmpInst);
4188void AArch64AsmPrinter::recordIfImportCall(
4189 const llvm::MachineInstr *BranchInst) {
4190 if (!EnableImportCallOptimization)
4194 if (GV && GV->hasDLLImportStorageClass()) {
4195 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
4200 .push_back({CallSiteSymbol, CalledSymbol});
4204void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
4205 MCSymbol *LazyPointer) {
4222 EmitToStreamer(Adrp);
4230 MCOperand SymPageOff;
4237 EmitToStreamer(Ldr);
4240 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
4241 .addReg(AArch64::X16)
4242 .addReg(AArch64::X16)
4245 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4247 .addReg(AArch64::X16));
4250void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
4251 const GlobalIFunc &GI,
4252 MCSymbol *LazyPointer) {
4284 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4285 .addReg(AArch64::SP)
4286 .addReg(AArch64::FP)
4287 .addReg(AArch64::LR)
4288 .addReg(AArch64::SP)
4291 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4292 .addReg(AArch64::FP)
4293 .addReg(AArch64::SP)
4297 for (
int I = 0;
I != 4; ++
I)
4298 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4299 .addReg(AArch64::SP)
4300 .addReg(AArch64::X1 + 2 *
I)
4301 .addReg(AArch64::X0 + 2 *
I)
4302 .addReg(AArch64::SP)
4305 for (
int I = 0;
I != 4; ++
I)
4306 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
4307 .addReg(AArch64::SP)
4308 .addReg(AArch64::D1 + 2 *
I)
4309 .addReg(AArch64::D0 + 2 *
I)
4310 .addReg(AArch64::SP)
4314 MCInstBuilder(AArch64::BL)
4327 EmitToStreamer(Adrp);
4335 MCOperand SymPageOff;
4342 EmitToStreamer(Ldr);
4345 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
4346 .addReg(AArch64::X0)
4347 .addReg(AArch64::X16)
4350 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4351 .addReg(AArch64::X16)
4352 .addReg(AArch64::X0)
4356 for (
int I = 3;
I != -1; --
I)
4357 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
4358 .addReg(AArch64::SP)
4359 .addReg(AArch64::D1 + 2 *
I)
4360 .addReg(AArch64::D0 + 2 *
I)
4361 .addReg(AArch64::SP)
4364 for (
int I = 3;
I != -1; --
I)
4365 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4366 .addReg(AArch64::SP)
4367 .addReg(AArch64::X1 + 2 *
I)
4368 .addReg(AArch64::X0 + 2 *
I)
4369 .addReg(AArch64::SP)
4372 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4373 .addReg(AArch64::SP)
4374 .addReg(AArch64::FP)
4375 .addReg(AArch64::LR)
4376 .addReg(AArch64::SP)
4379 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4381 .addReg(AArch64::X16));
4384const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4385 const Constant *BaseCV,
4395char AArch64AsmPrinter::ID = 0;
4398 "AArch64 Assembly Printer",
false,
false)
4402LLVMInitializeAArch64AsmPrinter() {
4412 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4422 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4433 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond)
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
static bool getOptionalBooleanModuleFlag(Module &M, StringRef Name)
static bool targetSupportsIRelativeRelocation(const Triple &TT)
static PtrauthCheckMode getCheckMode(const MachineFunction *MF)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
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
ModuleAnalysisManager MAM
#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 scope_exit class, which executes user-defined cleanup logic at scope exit.
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
std::unique_ptr< MCStreamer > && Streamer
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool printAsmMRegister(const X86AsmPrinter &P, const MachineInstr &MI, const MachineOperand &MO, char Mode, raw_ostream &O)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static const AArch64AuthMCExpr * create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, bool HasAddressDiversity, MCContext &Ctx, SMLoc Loc=SMLoc())
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 AArch64Options & getCLOpts() const
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)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
void setPreservesAll()
Set by analyses that do not transform their input at all.
const T & front() const
Get the first element.
bool empty() const
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.
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
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.
Function * getFunction() const
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
@ AddrDiscriminator_CtorsDtors
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
static LLVM_ABI ConstantPtrAuth * get(Constant *Ptr, ConstantInt *Key, ConstantInt *Disc, Constant *AddrDisc, Constant *DeactivationSymbol)
Return a pointer signed with the specified parameters.
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.
LLVM_ABI void recordFaultingOp(FaultKind FaultTy, const MCSymbol *FaultingLabel, const MCSymbol *HandlerLabel)
LLVM_ABI void serializeToFaultMapSection()
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const Constant * getAliasee() const
const Constant * getResolver() const
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
bool hasLocalLinkage() const
bool hasExternalWeakLinkage() const
Type * getValueType() const
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
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.
void setFlags(unsigned F)
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
MCSection * getDataSection() const
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
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 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 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.
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 ....
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.
const MachineFunction * getParent() const
Return the MachineFunction containing 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.
MCContext & getContext() const
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...
const MachineBasicBlock & front() const
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
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()
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.
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
constexpr bool isValid() const
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.
Represent a constant reference to a string, i.e.
constexpr const char * data() const
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.
bool regsOverlap(Register RegA, Register RegB) const
Returns true if the two registers are equal or alias each other.
Triple - Helper class for working with autoconf configuration names.
bool isFunctionTy() const
True if this is an instance of FunctionType.
LLVM Value Representation.
LLVMContext & getContext() const
All values hold a context through their type.
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 StringRef getName() const
Return a constant reference to the value's name.
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI 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.
PtrauthCheckMode
Ways to check pointer authentication auth/resign failures.
constexpr AArch64PACKey::ID InitFiniKey
PAuth key to be used with function pointers in .init_array and .fini_array.
AuthCheckMethod
Variants of check performed on an authenticated pointer.
constexpr unsigned InitFiniPointerConstantDiscriminator
Constant discriminator to be used with function pointers in .init_array and .fini_array.
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))
@ AARCH64_PAUTH_PLATFORM_LLVM_LINUX
@ GNU_PROPERTY_AARCH64_FEATURE_1_BTI
@ GNU_PROPERTY_AARCH64_FEATURE_1_PAC
@ GNU_PROPERTY_AARCH64_FEATURE_1_GCS
@ S_REGULAR
S_REGULAR - Regular section.
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
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.
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.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
scope_exit(Callable) -> scope_exit< Callable >
@ Store
The extracted value is stored (ExtractElement only).
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)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
static unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K, bool Zero)
Return B(L)RA opcode to be used for an authenticated branch or call using the given key,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Target & getTheAArch64leTarget()
auto dyn_cast_or_null(const Y &Val)
Target & getTheAArch64_32Target()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
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)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
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)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...