80#define DEBUG_TYPE "AArch64AsmPrinter"
85 "Number of zero-cycle FPR zeroing instructions expanded from "
86 "canonical pseudo instructions");
94 cl::desc(
"Check pointer authentication auth/resign failures"));
102 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
103 bool PtrauthInitFini =
false;
104 bool PtrauthInitFiniAddressDisc =
false;
106 unsigned InstsEmitted;
108 bool EnableImportCallOptimization =
false;
110 SectionToImportedFunctionCalls;
111 unsigned PAuthIFuncNextUniqueID = 1;
118 MCInstLowering(OutContext, *this), FM(*this) {}
120 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
124 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const {
125 return MCInstLowering.lowerOperand(MO, MCOp);
128 const MCExpr *lowerConstantPtrAuth(
const ConstantPtrAuth &CPA)
override;
130 const MCExpr *lowerBlockAddressConstant(
const BlockAddress &BA)
override;
132 void emitStartOfAsmFile(
Module &M)
override;
133 void emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
134 ArrayRef<unsigned> JumpTableIndices)
override;
137 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
138 const MCSymbol *BranchLabel)
const override;
140 void emitFunctionEntryLabel()
override;
142 void emitXXStructor(
const DataLayout &
DL,
const Constant *CV)
override;
144 void LowerJumpTableDest(MCStreamer &OutStreamer,
const MachineInstr &
MI);
146 void LowerHardenedBRJumpTable(
const MachineInstr &
MI);
148 void LowerMOPS(MCStreamer &OutStreamer,
const MachineInstr &
MI);
150 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
151 const MachineInstr &
MI);
152 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
153 const MachineInstr &
MI);
154 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
155 const MachineInstr &
MI);
156 void LowerFAULTING_OP(
const MachineInstr &
MI);
158 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI);
159 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI);
160 void LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI);
161 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
163 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
164 HwasanMemaccessTuple;
165 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
166 void LowerKCFI_CHECK(
const MachineInstr &
MI);
167 void LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI);
168 void emitHwasanMemaccessSymbols(
Module &M);
170 void emitSled(
const MachineInstr &
MI, SledKind Kind);
178 if (STI->isX16X17Safer())
179 return Reg == AArch64::X16 ||
Reg == AArch64::X17;
185 void emitPtrauthBranch(
const MachineInstr *
MI);
187 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
191 const MCSymbol *OnFailure =
nullptr);
194 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
196 struct PtrAuthSchema {
198 const MachineOperand &AddrDiscOp);
205 bool AddrDiscIsKilled;
208 bool addrDiscIsKilledAndNoneOf(std::initializer_list<Register> Regs) {
226 PtrAuthSchema AuthSchema,
227 std::optional<PtrAuthSchema> SignSchema,
228 std::optional<int64_t> Addend,
Value *DS);
233 bool emitDeactivationSymbolRelocation(
Value *DS);
236 void emitPtrauthSign(
const MachineInstr *
MI);
260 bool MayClobberAddrDisc =
false);
263 void LowerLOADauthptrstatic(
const MachineInstr &
MI);
267 void LowerMOVaddrPAC(
const MachineInstr &
MI);
272 void LowerLOADgotAUTH(
const MachineInstr &
MI);
274 void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
275 void emitAddress(MCRegister
Reg,
const MCExpr *Expr, MCRegister Tmp,
276 bool DSOLocal,
const MCSubtargetInfo &STI);
278 const MCExpr *emitPAuthRelocationAsIRelative(
280 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
284 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
287 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
288 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
291 void emitCBPseudoExpansion(
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 = TM.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 = TM.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 = TM.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 = TM.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");
2073 if (AddrDisc == AArch64::NoRegister)
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();
2297 Schema.PCDisc = AArch64::NoRegister;
2301AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateRegReg(
2303 assert(PCDisc != AArch64::NoRegister &&
2304 "Use CreateImmReg for non-PC schemas");
2305 PtrAuthSchema Schema;
2308 Schema.AddrDisc = AddrDisc;
2309 Schema.AddrDiscIsKilled =
false;
2310 Schema.PCDisc = PCDisc;
2314void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2319 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2329 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2331 MCInstBuilder(AArch64::ADDXri)
2334 .addImm((Addend >> BitPos) & 0xfff)
2340 emitMOVZ(Scratch, Addend & 0xffff, 0);
2342 if (
unsigned Fragment = (Addend >>
Offset) & 0xffff)
2343 emitMOVK(Scratch, Fragment,
Offset);
2347 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2354 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2360 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2411void AArch64AsmPrinter::emitPtrauthAuthResign(
2413 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2416 const bool IsAuthWithPC = AuthSchema.PCDisc != AArch64::NoRegister;
2417 assert(!SignSchema || SignSchema->PCDisc == AArch64::NoRegister);
2420 SignSchema ? SignSchema->AddrDisc : AArch64::NoRegister;
2426 assert(Pointer == AArch64::X17 && Scratch == AArch64::X16 &&
2427 "AUTPCPAC must use x17/x16 as Pointer/Scratch");
2429 assert(AuthSchema.AddrDisc == AArch64::X16 &&
2430 "AUTPCPAC requires address discriminator in X16");
2432 assert(AuthSchema.PCDisc == AArch64::X15 &&
2433 "AUTPCPAC requires PC discriminator in X15");
2435 assert(AuthSchema.IntDisc == 0 &&
"AUTPCPAC does not support IntDisc");
2439 "AUTPCPAC only supports AUT-ing with IA/IB");
2441 if (!emitDeactivationSymbolRelocation(DS)) {
2443 ? AArch64::AUTIB171615
2444 : AArch64::AUTIA171615;
2445 EmitToStreamer(MCInstBuilder(AutOpc));
2455 Register AUTDiscReg = emitPtrauthDiscriminator(
2456 AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2457 AuthSchema.addrDiscIsKilledAndNoneOf({Pointer, SignAddrDiscOrNone}));
2458 if (!emitDeactivationSymbolRelocation(DS))
2459 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2464 auto EmitCheck = [&](
MCSymbol *OnFailure =
nullptr) {
2465 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2466 AArch64PAuth::AuthCheckMethod::XPAC,
2470 auto EmitResignOnSuccess = [&]() {
2471 if (Addend.has_value())
2472 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2474 assert(Pointer != SignSchema->AddrDisc &&
"Pointer is early-clobbered");
2476 emitPtrauthDiscriminator(SignSchema->IntDisc, SignSchema->AddrDisc,
2477 Scratch, SignSchema->AddrDiscIsKilled);
2478 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2490 switch (CheckMode) {
2492 EmitResignOnSuccess();
2496 EmitResignOnSuccess();
2499 MCSymbol *OnFailure = createTempSymbol(
"resign_end_");
2500 EmitCheck(OnFailure);
2501 EmitResignOnSuccess();
2507void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2511 Register AddrDisc =
MI->getOperand(4).getReg();
2512 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2516 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2517 assert(ScratchReg != AddrDisc &&
2518 "Neither X16 nor X17 is available as a scratch register");
2521 Register DiscReg = emitPtrauthDiscriminator(
2522 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2524 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2527 emitPAC(
Key, Val, DiscReg);
2530void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2531 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2532 unsigned BrTarget =
MI->getOperand(0).getReg();
2537 unsigned AddrDisc =
MI->getOperand(3).getReg();
2543 if (BrTarget == AddrDisc)
2560 bool AddrDiscIsImplicitDef =
2561 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2562 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2563 AddrDiscIsImplicitDef);
2564 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2567void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2571 const bool IsNeg = Addend < 0;
2573 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2576 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2579 .addImm((AbsOffset >> BitPos) & 0xfff)
2584 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2586 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2588 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2589 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2590 uint64_t Shifted = UAddend >> BitPos;
2592 return Shifted != 0;
2593 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2594 if (((Shifted >>
I) & 0xffff) != 0xffff)
2598 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2599 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2601 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2610void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2611 MCRegister Tmp,
bool DSOLocal,
2612 const MCSubtargetInfo &STI) {
2618 MCInstBuilder(AArch64::ADRP)
2622 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2632 MCInstBuilder(AArch64::ADRP)
2637 MCInstBuilder(AArch64::LDRXui)
2648 if (!TT.isOSBinFormatELF())
2652 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2653 TT.isOSDragonFly() || TT.isOSNetBSD();
2707const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2709 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2710 const Triple &
TT = TM.getTargetTriple();
2722 auto STI = std::make_unique<AArch64Subtarget>(
2723 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2725 this->STI = STI.get();
2731 const MCSymbolELF *Group =
2746 .addReg(AArch64::X0)
2751 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2753 if (HasAddressDiversity) {
2758 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2762 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2764 "' out of range [0, 0xFFFF]");
2766 emitMOVZ(AArch64::X1, Disc, 0);
2773 auto *PrePACInstExpr =
2785 const MCSymbolRefExpr *EmuPACRef =
2787 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2794 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2803AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2804 MCContext &Ctx = OutContext;
2809 getDataLayout(),
Offset,
true);
2829 const MCExpr *DSExpr =
nullptr;
2841 "' out of range [0, " +
2849 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2851 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2856 "' out of range [0, 0xFFFF]");
2862 "expressions on this target");
2869void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2870 unsigned DstReg =
MI.getOperand(0).getReg();
2871 const MachineOperand &GAOp =
MI.getOperand(1);
2872 const uint64_t KeyC =
MI.getOperand(2).getImm();
2874 "key is out of range [0, AArch64PACKey::LAST]");
2876 const uint64_t Disc =
MI.getOperand(3).getImm();
2878 "constant discriminator is out of range [0, 0xffff]");
2887 if (TM.getTargetTriple().isOSBinFormatELF()) {
2889 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2892 "non-zero offset for $auth_ptr$ stub slots is not supported");
2894 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2896 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2897 "LOADauthptrstatic is implemented only for MachO/ELF");
2899 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2900 getObjFileLowering());
2903 "non-zero offset for $auth_ptr$ stub slots is not supported");
2905 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2908 MachineOperand StubMOHi =
2912 MCOperand StubMCHi, StubMCLo;
2919 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2921 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2927void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2928 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2929 const bool IsELFSignedGOT =
MI.getParent()
2931 ->getInfo<AArch64FunctionInfo>()
2932 ->hasELFSignedGOT();
2933 MachineOperand GAOp =
MI.getOperand(0);
2934 const uint64_t KeyC =
MI.getOperand(1).getImm();
2936 "key is out of range [0, AArch64PACKey::LAST]");
2938 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2939 const uint64_t Disc =
MI.getOperand(3).getImm();
2986 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2987 MCOperand GAMCHi, GAMCLo;
3000 MCInstBuilder(AArch64::ADRP)
3001 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
3005 if (IsELFSignedGOT) {
3006 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3007 .addReg(AArch64::X17)
3008 .addReg(AArch64::X17)
3012 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3013 .addReg(AArch64::X16)
3014 .addReg(AArch64::X17)
3022 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
3024 if (!STI->hasFPAC())
3025 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
3026 AArch64PAuth::AuthCheckMethod::XPAC);
3028 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3029 .addReg(AArch64::X16)
3030 .addReg(AArch64::X16)
3034 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3035 .addReg(AArch64::X16)
3036 .addReg(AArch64::X16)
3041 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
3042 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
3044 emitPAC(
Key, AArch64::X16, DiscReg);
3047void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
3049 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
3050 const MachineOperand &GAMO =
MI.getOperand(1);
3057 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
3058 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3059 .addReg(AuthResultReg)
3060 .addReg(AArch64::X17)
3063 MachineOperand GAHiOp(GAMO);
3064 MachineOperand GALoOp(GAMO);
3068 MCOperand GAMCHi, GAMCLo;
3073 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
3075 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3076 .addReg(AArch64::X17)
3077 .addReg(AArch64::X17)
3081 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3082 .addReg(AuthResultReg)
3083 .addReg(AArch64::X17)
3090 UndefWeakSym = createTempSymbol(
"undef_weak");
3092 MCInstBuilder(AArch64::CBZX)
3093 .addReg(AuthResultReg)
3101 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
3106 if (!STI->hasFPAC()) {
3107 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
3108 AArch64PAuth::AuthCheckMethod::XPAC);
3110 emitMovXReg(DstReg, AuthResultReg);
3115AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
3119 if (std::optional<uint16_t> BADisc =
3120 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3127void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3131 switch (
MI->getOpcode()) {
3134 case AArch64::CBBAssertExt:
3138 case AArch64::CBHAssertExt:
3142 case AArch64::CBWPrr:
3145 case AArch64::CBXPrr:
3148 case AArch64::CBWPri:
3152 case AArch64::CBXPri:
3160 bool NeedsRegSwap =
false;
3161 bool NeedsImmDec =
false;
3162 bool NeedsImmInc =
false;
3164#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3166 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3168 ? AArch64::CBB##RegCond##Wrr \
3169 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3170 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3171 : AArch64::CB##RegCond##Xrr))))
3187 NeedsImmDec = IsImm;
3191 NeedsRegSwap = !IsImm;
3198 NeedsRegSwap = !IsImm;
3199 NeedsImmInc = IsImm;
3203 NeedsImmDec = IsImm;
3207 NeedsRegSwap = !IsImm;
3214 NeedsRegSwap = !IsImm;
3215 NeedsImmInc = IsImm;
3223 MCOperand Lhs, Rhs, Trgt;
3224 lowerOperand(
MI->getOperand(1), Lhs);
3225 lowerOperand(
MI->getOperand(2), Rhs);
3226 lowerOperand(
MI->getOperand(3), Trgt);
3230 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3231 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3234 }
else if (NeedsImmDec) {
3238 }
else if (NeedsImmInc) {
3248 "CB immediate operand out-of-bounds");
3251 EmitToStreamer(*OutStreamer, Inst);
3256#include "AArch64GenMCPseudoLowering.inc"
3258void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3265void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3266 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3271 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3276 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3277 EmitToStreamer(*OutStreamer, OutInst);
3281 if (
MI->getOpcode() == AArch64::ADRP) {
3282 for (
auto &Opd :
MI->operands()) {
3283 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3284 "swift_async_extendedFramePointerFlags") {
3285 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3292 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3294 LOHInstToLabel[
MI] = LOHLabel;
3298 AArch64TargetStreamer *TS =
3301 switch (
MI->getOpcode()) {
3304 "Unhandled tail call instruction");
3306 case AArch64::READ_REGISTER_GPR64:
3310 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
3311 .addReg(
MI->getOperand(0).getReg())
3312 .addReg(AArch64::XZR)
3313 .addReg(
MI->getOperand(1).getImm())
3316 case AArch64::READ_REGISTER_FPR64:
3318 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::FMOVDr)
3319 .addReg(
MI->getOperand(0).getReg())
3320 .addReg(
MI->getOperand(1).getImm()));
3322 case AArch64::HINT: {
3327 if (CurrentPatchableFunctionEntrySym &&
3328 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3330 int64_t
Imm =
MI->getOperand(0).getImm();
3331 if (
Imm == 32 ||
Imm == 34 ||
Imm == 36 ||
Imm == 38) {
3333 MCInstLowering.
Lower(
MI, Inst);
3334 EmitToStreamer(*OutStreamer, Inst);
3335 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3336 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3342 case AArch64::MOVMCSym: {
3343 Register DestReg =
MI->getOperand(0).getReg();
3344 const MachineOperand &MO_Sym =
MI->getOperand(1);
3345 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3346 MCOperand Hi_MCSym, Lo_MCSym;
3359 EmitToStreamer(*OutStreamer, MovZ);
3367 EmitToStreamer(*OutStreamer, MovK);
3370 case AArch64::MOVIv2d_ns:
3378 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3379 MI->getOperand(1).getImm() == 0) {
3381 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3384 EmitToStreamer(*OutStreamer, TmpInst);
3389 case AArch64::DBG_VALUE:
3390 case AArch64::DBG_VALUE_LIST:
3392 SmallString<128> TmpStr;
3393 raw_svector_ostream OS(TmpStr);
3394 PrintDebugValueComment(
MI, OS);
3399 case AArch64::EMITBKEY: {
3401 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3402 ExceptionHandlingType != ExceptionHandling::ARM)
3405 if (getFunctionCFISectionType(*MF) == CFISection::None)
3412 case AArch64::EMITMTETAGGED: {
3414 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3415 ExceptionHandlingType != ExceptionHandling::ARM)
3418 if (getFunctionCFISectionType(*MF) != CFISection::None)
3423 case AArch64::AUTx16x17: {
3425 const Register Scratch = AArch64::X17;
3427 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3429 MI->getOperand(1).getImm(),
MI->getOperand(2));
3431 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3432 std::nullopt,
MI->getDeactivationSymbol());
3436 case AArch64::AUTxMxN: {
3438 const Register Scratch =
MI->getOperand(1).getReg();
3440 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3442 MI->getOperand(4).getImm(),
MI->getOperand(5));
3444 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3445 std::nullopt,
MI->getDeactivationSymbol());
3449 case AArch64::AUTPAC: {
3451 const Register Scratch = AArch64::X17;
3453 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3455 MI->getOperand(1).getImm(),
MI->getOperand(2));
3457 auto SignSchema = PtrAuthSchema::CreateImmReg(
3459 MI->getOperand(4).getImm(),
MI->getOperand(5));
3461 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3462 std::nullopt,
MI->getDeactivationSymbol());
3466 case AArch64::AUTPCPAC: {
3467 auto AuthSchema = PtrAuthSchema::CreateRegReg(
3471 auto SignSchema = PtrAuthSchema::CreateImmReg(
3473 MI->getOperand(2).getImm(),
MI->getOperand(3));
3475 emitPtrauthAuthResign(AArch64::X17, AArch64::X16,
3476 AuthSchema, SignSchema, std::nullopt,
3477 MI->getDeactivationSymbol());
3481 case AArch64::AUTRELLOADPAC: {
3483 const Register Scratch = AArch64::X17;
3485 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3487 MI->getOperand(1).getImm(),
MI->getOperand(2));
3489 auto SignSchema = PtrAuthSchema::CreateImmReg(
3491 MI->getOperand(4).getImm(),
MI->getOperand(5));
3493 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3494 MI->getOperand(6).getImm(),
3495 MI->getDeactivationSymbol());
3501 emitPtrauthSign(
MI);
3504 case AArch64::LOADauthptrstatic:
3505 LowerLOADauthptrstatic(*
MI);
3508 case AArch64::LOADgotPAC:
3509 case AArch64::MOVaddrPAC:
3510 LowerMOVaddrPAC(*
MI);
3513 case AArch64::LOADgotAUTH:
3514 LowerLOADgotAUTH(*
MI);
3519 emitPtrauthBranch(
MI);
3525 case AArch64::AUTH_TCRETURN:
3526 case AArch64::AUTH_TCRETURN_BTI: {
3529 const uint64_t Disc =
MI->getOperand(3).getImm();
3531 Register AddrDisc =
MI->getOperand(4).getReg();
3533 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3535 emitPtrauthTailCallHardening(
MI);
3538 if (Callee == AddrDisc)
3545 bool AddrDiscIsImplicitDef =
3546 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3547 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3548 AddrDiscIsImplicitDef);
3549 emitBLRA(
false,
Key, Callee, DiscReg);
3553 case AArch64::TCRETURNri:
3554 case AArch64::TCRETURNrix16x17:
3555 case AArch64::TCRETURNrix17:
3556 case AArch64::TCRETURNrinotx16:
3557 case AArch64::TCRETURNriALL: {
3558 emitPtrauthTailCallHardening(
MI);
3560 recordIfImportCall(
MI);
3564 EmitToStreamer(*OutStreamer, TmpInst);
3567 case AArch64::TCRETURNdi: {
3568 emitPtrauthTailCallHardening(
MI);
3572 recordIfImportCall(
MI);
3576 EmitToStreamer(*OutStreamer, TmpInst);
3579 case AArch64::SpeculationBarrierISBDSBEndBB: {
3584 EmitToStreamer(*OutStreamer, TmpInstDSB);
3588 EmitToStreamer(*OutStreamer, TmpInstISB);
3591 case AArch64::SpeculationBarrierSBEndBB: {
3595 EmitToStreamer(*OutStreamer, TmpInstSB);
3598 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3605 const MachineOperand &MO_Sym =
MI->getOperand(0);
3606 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3607 MCOperand SymTLSDescLo12, SymTLSDesc;
3610 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3617 EmitToStreamer(*OutStreamer, Adrp);
3625 EmitToStreamer(*OutStreamer, Ldr);
3628 Add.setOpcode(AArch64::ADDXri);
3631 Add.addOperand(SymTLSDescLo12);
3633 EmitToStreamer(*OutStreamer,
Add);
3642 EmitToStreamer(*OutStreamer, Blraa);
3646 case AArch64::TLSDESC_CALLSEQ: {
3654 const MachineOperand &MO_Sym =
MI->getOperand(0);
3655 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3656 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3660 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3667 EmitToStreamer(*OutStreamer, Adrp);
3670 if (STI->isTargetILP32()) {
3680 EmitToStreamer(*OutStreamer, Ldr);
3683 if (STI->isTargetILP32()) {
3684 Add.setOpcode(AArch64::ADDWri);
3688 Add.setOpcode(AArch64::ADDXri);
3692 Add.addOperand(SymTLSDescLo12);
3694 EmitToStreamer(*OutStreamer,
Add);
3699 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3701 EmitToStreamer(*OutStreamer, TLSDescCall);
3709 EmitToStreamer(*OutStreamer, Blr);
3714 case AArch64::JumpTableDest32:
3715 case AArch64::JumpTableDest16:
3716 case AArch64::JumpTableDest8:
3717 LowerJumpTableDest(*OutStreamer, *
MI);
3720 case AArch64::BR_JumpTable:
3721 LowerHardenedBRJumpTable(*
MI);
3724 case AArch64::FMOVH0:
3725 case AArch64::FMOVS0:
3726 case AArch64::FMOVD0:
3730 case AArch64::MOPSMemoryCopyPseudo:
3731 case AArch64::MOPSMemoryMovePseudo:
3732 case AArch64::MOPSMemorySetPseudo:
3733 case AArch64::MOPSMemorySetTaggingPseudo:
3734 LowerMOPS(*OutStreamer, *
MI);
3737 case TargetOpcode::STACKMAP:
3738 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3740 case TargetOpcode::PATCHPOINT:
3741 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3743 case TargetOpcode::STATEPOINT:
3744 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3746 case TargetOpcode::FAULTING_OP:
3747 return LowerFAULTING_OP(*
MI);
3749 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3750 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3753 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3754 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3757 case TargetOpcode::PATCHABLE_TAIL_CALL:
3758 LowerPATCHABLE_TAIL_CALL(*
MI);
3760 case TargetOpcode::PATCHABLE_EVENT_CALL:
3761 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3762 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3763 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3765 case AArch64::KCFI_CHECK:
3766 LowerKCFI_CHECK(*
MI);
3769 case AArch64::HWASAN_CHECK_MEMACCESS:
3770 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3771 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3772 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3773 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3776 case AArch64::SEH_StackAlloc:
3780 case AArch64::SEH_SaveFPLR:
3784 case AArch64::SEH_SaveFPLR_X:
3785 assert(
MI->getOperand(0).getImm() < 0 &&
3786 "Pre increment SEH opcode must have a negative offset");
3790 case AArch64::SEH_SaveReg:
3792 MI->getOperand(1).getImm());
3795 case AArch64::SEH_SaveReg_X:
3796 assert(
MI->getOperand(1).getImm() < 0 &&
3797 "Pre increment SEH opcode must have a negative offset");
3799 -
MI->getOperand(1).getImm());
3802 case AArch64::SEH_SaveRegP:
3803 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3804 MI->getOperand(0).getImm() <= 28) {
3805 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3806 "Register paired with LR must be odd");
3808 MI->getOperand(2).getImm());
3811 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3812 "Non-consecutive registers not allowed for save_regp");
3814 MI->getOperand(2).getImm());
3817 case AArch64::SEH_SaveRegP_X:
3818 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3819 "Non-consecutive registers not allowed for save_regp_x");
3820 assert(
MI->getOperand(2).getImm() < 0 &&
3821 "Pre increment SEH opcode must have a negative offset");
3823 -
MI->getOperand(2).getImm());
3826 case AArch64::SEH_SaveFReg:
3828 MI->getOperand(1).getImm());
3831 case AArch64::SEH_SaveFReg_X:
3832 assert(
MI->getOperand(1).getImm() < 0 &&
3833 "Pre increment SEH opcode must have a negative offset");
3835 -
MI->getOperand(1).getImm());
3838 case AArch64::SEH_SaveFRegP:
3839 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3840 "Non-consecutive registers not allowed for save_regp");
3842 MI->getOperand(2).getImm());
3845 case AArch64::SEH_SaveFRegP_X:
3846 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3847 "Non-consecutive registers not allowed for save_regp_x");
3848 assert(
MI->getOperand(2).getImm() < 0 &&
3849 "Pre increment SEH opcode must have a negative offset");
3851 -
MI->getOperand(2).getImm());
3854 case AArch64::SEH_SetFP:
3858 case AArch64::SEH_AddFP:
3862 case AArch64::SEH_Nop:
3866 case AArch64::SEH_PrologEnd:
3870 case AArch64::SEH_EpilogStart:
3874 case AArch64::SEH_EpilogEnd:
3878 case AArch64::SEH_PACSignLR:
3882 case AArch64::SEH_SaveAnyRegI:
3883 assert(
MI->getOperand(1).getImm() <= 1008 &&
3884 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3886 MI->getOperand(1).getImm());
3889 case AArch64::SEH_SaveAnyRegIP:
3890 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3891 "Non-consecutive registers not allowed for save_any_reg");
3892 assert(
MI->getOperand(2).getImm() <= 1008 &&
3893 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3895 MI->getOperand(2).getImm());
3898 case AArch64::SEH_SaveAnyRegQP:
3899 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3900 "Non-consecutive registers not allowed for save_any_reg");
3901 assert(
MI->getOperand(2).getImm() >= 0 &&
3902 "SaveAnyRegQP SEH opcode offset must be non-negative");
3903 assert(
MI->getOperand(2).getImm() <= 1008 &&
3904 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3906 MI->getOperand(2).getImm());
3909 case AArch64::SEH_SaveAnyRegQPX:
3910 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3911 "Non-consecutive registers not allowed for save_any_reg");
3912 assert(
MI->getOperand(2).getImm() < 0 &&
3913 "SaveAnyRegQPX SEH opcode offset must be negative");
3914 assert(
MI->getOperand(2).getImm() >= -1008 &&
3915 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3917 -
MI->getOperand(2).getImm());
3920 case AArch64::SEH_AllocZ:
3921 assert(
MI->getOperand(0).getImm() >= 0 &&
3922 "AllocZ SEH opcode offset must be non-negative");
3923 assert(
MI->getOperand(0).getImm() <= 255 &&
3924 "AllocZ SEH opcode offset must fit into 8 bits");
3928 case AArch64::SEH_SaveZReg:
3929 assert(
MI->getOperand(1).getImm() >= 0 &&
3930 "SaveZReg SEH opcode offset must be non-negative");
3931 assert(
MI->getOperand(1).getImm() <= 255 &&
3932 "SaveZReg SEH opcode offset must fit into 8 bits");
3934 MI->getOperand(1).getImm());
3937 case AArch64::SEH_SavePReg:
3938 assert(
MI->getOperand(1).getImm() >= 0 &&
3939 "SavePReg SEH opcode offset must be non-negative");
3940 assert(
MI->getOperand(1).getImm() <= 255 &&
3941 "SavePReg SEH opcode offset must fit into 8 bits");
3943 MI->getOperand(1).getImm());
3948 recordIfImportCall(
MI);
3950 MCInstLowering.
Lower(
MI, TmpInst);
3951 EmitToStreamer(*OutStreamer, TmpInst);
3954 case AArch64::CBWPri:
3955 case AArch64::CBXPri:
3956 case AArch64::CBBAssertExt:
3957 case AArch64::CBHAssertExt:
3958 case AArch64::CBWPrr:
3959 case AArch64::CBXPrr:
3960 emitCBPseudoExpansion(
MI);
3964 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3969 MCInstLowering.
Lower(
MI, TmpInst);
3970 EmitToStreamer(*OutStreamer, TmpInst);
3973void AArch64AsmPrinter::recordIfImportCall(
3974 const llvm::MachineInstr *BranchInst) {
3975 if (!EnableImportCallOptimization)
3979 if (GV && GV->hasDLLImportStorageClass()) {
3980 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3985 .push_back({CallSiteSymbol, CalledSymbol});
3989void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3990 MCSymbol *LazyPointer) {
4007 EmitToStreamer(Adrp);
4015 MCOperand SymPageOff;
4022 EmitToStreamer(Ldr);
4025 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
4026 .addReg(AArch64::X16)
4027 .addReg(AArch64::X16)
4030 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4032 .addReg(AArch64::X16));
4035void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
4036 const GlobalIFunc &GI,
4037 MCSymbol *LazyPointer) {
4069 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4070 .addReg(AArch64::SP)
4071 .addReg(AArch64::FP)
4072 .addReg(AArch64::LR)
4073 .addReg(AArch64::SP)
4076 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4077 .addReg(AArch64::FP)
4078 .addReg(AArch64::SP)
4082 for (
int I = 0;
I != 4; ++
I)
4083 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4084 .addReg(AArch64::SP)
4085 .addReg(AArch64::X1 + 2 *
I)
4086 .addReg(AArch64::X0 + 2 *
I)
4087 .addReg(AArch64::SP)
4090 for (
int I = 0;
I != 4; ++
I)
4091 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
4092 .addReg(AArch64::SP)
4093 .addReg(AArch64::D1 + 2 *
I)
4094 .addReg(AArch64::D0 + 2 *
I)
4095 .addReg(AArch64::SP)
4099 MCInstBuilder(AArch64::BL)
4112 EmitToStreamer(Adrp);
4120 MCOperand SymPageOff;
4127 EmitToStreamer(Ldr);
4130 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
4131 .addReg(AArch64::X0)
4132 .addReg(AArch64::X16)
4135 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4136 .addReg(AArch64::X16)
4137 .addReg(AArch64::X0)
4141 for (
int I = 3;
I != -1; --
I)
4142 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
4143 .addReg(AArch64::SP)
4144 .addReg(AArch64::D1 + 2 *
I)
4145 .addReg(AArch64::D0 + 2 *
I)
4146 .addReg(AArch64::SP)
4149 for (
int I = 3;
I != -1; --
I)
4150 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4151 .addReg(AArch64::SP)
4152 .addReg(AArch64::X1 + 2 *
I)
4153 .addReg(AArch64::X0 + 2 *
I)
4154 .addReg(AArch64::SP)
4157 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4158 .addReg(AArch64::SP)
4159 .addReg(AArch64::FP)
4160 .addReg(AArch64::LR)
4161 .addReg(AArch64::SP)
4164 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4166 .addReg(AArch64::X16));
4169const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4170 const Constant *BaseCV,
4180char AArch64AsmPrinter::ID = 0;
4183 "AArch64 Assembly Printer",
false,
false)
4187LLVMInitializeAArch64AsmPrinter() {
4197 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4207 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4218 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 cl::opt< PtrauthCheckMode > PtrauthAuthChecks("aarch64-ptrauth-auth-checks", cl::Hidden, cl::values(clEnumValN(Unchecked, "none", "don't test for failure"), clEnumValN(Poison, "poison", "poison on failure"), clEnumValN(Trap, "trap", "trap on failure")), cl::desc("Check pointer authentication auth/resign failures"))
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 clEnumValN(ENUMVAL, FLAGNAME, DESC)
#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
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 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 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.
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)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
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 >
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,...