81#define DEBUG_TYPE "AArch64AsmPrinter"
86 "Number of zero-cycle FPR zeroing instructions expanded from "
87 "canonical pseudo instructions");
95 cl::desc(
"Check pointer authentication auth/resign failures"));
103 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
104 bool PtrauthInitFini =
false;
105 bool PtrauthInitFiniAddressDisc =
false;
107 unsigned InstsEmitted;
109 bool EnableImportCallOptimization =
false;
111 SectionToImportedFunctionCalls;
112 unsigned PAuthIFuncNextUniqueID = 1;
119 MCInstLowering(OutContext, *this), FM(*this) {}
121 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
125 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const {
126 return MCInstLowering.lowerOperand(MO, MCOp);
129 const MCExpr *lowerConstantPtrAuth(
const ConstantPtrAuth &CPA)
override;
131 const MCExpr *lowerBlockAddressConstant(
const BlockAddress &BA)
override;
133 void emitStartOfAsmFile(
Module &M)
override;
134 void emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
135 ArrayRef<unsigned> JumpTableIndices)
override;
138 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
139 const MCSymbol *BranchLabel)
const override;
141 void emitFunctionEntryLabel()
override;
143 void emitXXStructor(
const DataLayout &
DL,
const Constant *CV)
override;
145 void LowerJumpTableDest(MCStreamer &OutStreamer,
const MachineInstr &
MI);
147 void LowerHardenedBRJumpTable(
const MachineInstr &
MI);
149 void LowerMOPS(MCStreamer &OutStreamer,
const MachineInstr &
MI);
151 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
152 const MachineInstr &
MI);
153 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
154 const MachineInstr &
MI);
155 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
156 const MachineInstr &
MI);
157 void LowerFAULTING_OP(
const MachineInstr &
MI);
159 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI);
160 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI);
161 void LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI);
162 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
164 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
165 HwasanMemaccessTuple;
166 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
167 void LowerKCFI_CHECK(
const MachineInstr &
MI);
168 void LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI);
169 void emitHwasanMemaccessSymbols(
Module &M);
171 void emitSled(
const MachineInstr &
MI, SledKind Kind);
179 if (STI->isX16X17Safer())
180 return Reg == AArch64::X16 ||
Reg == AArch64::X17;
186 void emitPtrauthBranch(
const MachineInstr *
MI);
188 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
192 const MCSymbol *OnFailure =
nullptr);
195 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
197 struct PtrAuthSchema {
199 const MachineOperand &AddrDiscOp);
206 bool AddrDiscIsKilled;
209 bool addrDiscIsKilledAndNoneOf(std::initializer_list<Register> Regs) {
227 PtrAuthSchema AuthSchema,
228 std::optional<PtrAuthSchema> SignSchema,
229 std::optional<int64_t> Addend,
Value *DS);
234 bool emitDeactivationSymbolRelocation(
Value *DS);
237 void emitPtrauthSign(
const MachineInstr *
MI);
261 bool MayClobberAddrDisc =
false);
264 void LowerLOADauthptrstatic(
const MachineInstr &
MI);
268 void LowerMOVaddrPAC(
const MachineInstr &
MI);
273 void LowerLOADgotAUTH(
const MachineInstr &
MI);
275 void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
276 void emitAddress(MCRegister
Reg,
const MCExpr *Expr, MCRegister Tmp,
277 bool DSOLocal,
const MCSubtargetInfo &STI);
279 const MCExpr *emitPAuthRelocationAsIRelative(
281 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
285 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
288 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
289 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
292 void emitCBPseudoExpansion(
const MachineInstr *
MI);
294 void EmitToStreamer(MCStreamer &S,
const MCInst &Inst);
295 void EmitToStreamer(
const MCInst &Inst) {
296 EmitToStreamer(*OutStreamer, Inst);
301 void emitFunctionHeaderComment()
override;
303 void getAnalysisUsage(AnalysisUsage &AU)
const override {
309 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
310 PSI = &PSIW->getPSI();
312 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
313 SDPI = &SDPIW->getStaticDataProfileInfo();
315 AArch64FI = MF.
getInfo<AArch64FunctionInfo>();
318 SetupMachineFunction(MF);
320 if (STI->isTargetCOFF()) {
327 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
328 OutStreamer->emitCOFFSymbolStorageClass(Scl);
329 OutStreamer->emitCOFFSymbolType(
Type);
330 OutStreamer->endCOFFSymbolDef();
344 const Constant *BaseCV =
nullptr,
348 void printOperand(
const MachineInstr *
MI,
unsigned OpNum, raw_ostream &O);
350 bool printAsmRegInClass(
const MachineOperand &MO,
354 bool PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
355 const char *ExtraCode, raw_ostream &O)
override;
356 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
357 const char *ExtraCode, raw_ostream &O)
override;
359 void PrintDebugValueComment(
const MachineInstr *
MI, raw_ostream &OS);
361 void emitFunctionBodyEnd()
override;
362 void emitGlobalAlias(
const Module &M,
const GlobalAlias &GA)
override;
364 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
365 void emitEndOfAsmFile(
Module &M)
override;
367 AArch64FunctionInfo *AArch64FI =
nullptr;
382 void emitFMov0(
const MachineInstr &
MI);
383 void emitFMov0AsFMov(
const MachineInstr &
MI,
Register DestReg);
385 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
387 MInstToMCSymbol LOHInstToLabel;
389 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
390 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
393 const MCSubtargetInfo *getIFuncMCSubtargetInfo()
const override {
397 void emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
398 MCSymbol *LazyPointer)
override;
399 void emitMachOIFuncStubHelperBody(
Module &M,
const GlobalIFunc &GI,
400 MCSymbol *LazyPointer)
override;
405 void recordIfImportCall(
const MachineInstr *BranchInst);
412 Metadata *Flag = M.getModuleFlag(Name);
417 assert((
Value == 0 ||
Value == 1) &&
"Boolean flag is expected, if present");
421void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
422 const Triple &
TT = TM.getTargetTriple();
424 if (
TT.isOSBinFormatCOFF()) {
425 emitCOFFFeatureSymbol(M);
426 emitCOFFReplaceableFunctionData(M);
428 if (
M.getModuleFlag(
"import-call-optimization"))
429 EnableImportCallOptimization =
true;
434 M,
"ptrauth-init-fini-address-discrimination");
436 if (!
TT.isOSBinFormatELF())
441 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
444 unsigned BAFlags = 0;
445 unsigned GNUFlags = 0;
447 M.getModuleFlag(
"branch-target-enforcement"))) {
448 if (!BTE->isZero()) {
449 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
455 M.getModuleFlag(
"guarded-control-stack"))) {
456 if (!GCS->isZero()) {
457 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
463 M.getModuleFlag(
"sign-return-address"))) {
464 if (!Sign->isZero()) {
465 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
472 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
473 PAuthABIPlatform = PAP->getZExtValue();
478 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
479 PAuthABIVersion = PAV->getZExtValue();
487 PAuthABIVersion == 0) {
493 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
495 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
498void AArch64AsmPrinter::emitFunctionHeaderComment() {
499 const AArch64FunctionInfo *FI = MF->
getInfo<AArch64FunctionInfo>();
501 if (OutlinerString != std::nullopt)
502 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
505void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
508 if (
F.hasFnAttribute(
"patchable-function-entry")) {
510 if (
F.getFnAttribute(
"patchable-function-entry")
512 .getAsInteger(10, Num))
518 emitSled(
MI, SledKind::FUNCTION_ENTER);
521void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
522 emitSled(
MI, SledKind::FUNCTION_EXIT);
525void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
526 emitSled(
MI, SledKind::TAIL_CALL);
529void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
530 static const int8_t NoopsInSledCount = 7;
551 OutStreamer->emitCodeAlignment(
Align(4), getSubtargetInfo());
552 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
553 OutStreamer->emitLabel(CurSled);
554 auto Target = OutContext.createTempSymbol();
559 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
561 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
562 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
564 OutStreamer->emitLabel(Target);
565 recordSled(CurSled,
MI, Kind, 2);
568void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
571 AArch64TargetStreamer *TS) {
573 PAuthABIPlatform = (
uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
574 PAuthABIVersion = (
uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
576 if (PAuthABIPlatform || PAuthABIVersion) {
580 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
581 AArch64BuildAttributes::SubsectionType::ULEB128);
585 PAuthABIPlatform,
"");
599 if (BTIValue || PACValue || GCSValue) {
603 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
604 AArch64BuildAttributes::SubsectionType::ULEB128);
632void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
634 auto &
O = *OutStreamer;
635 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
636 O.emitLabel(CurSled);
637 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
639 OutContext.getOrCreateSymbol(
640 Twine(MachO ?
"_" :
"") +
641 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
644 O.AddComment(
"Begin XRay typed event");
645 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
646 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
652 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
656 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
657 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
658 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
659 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
660 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
664 O.AddComment(
"End XRay typed event");
665 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
672 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
674 O.AddComment(
"Begin XRay custom event");
675 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
676 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
682 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
683 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
684 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
685 O.AddComment(
"End XRay custom event");
686 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
693 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
697void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
699 assert(std::next(
MI.getIterator())->isCall() &&
700 "KCFI_CHECK not followed by a call instruction");
701 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
702 "KCFI_CHECK call target doesn't match call operand");
706 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
707 if (AddrReg == AArch64::XZR) {
711 emitMovXReg(AddrReg, AArch64::XZR);
717 for (
auto &
Reg : ScratchRegs) {
723 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
724 "Invalid scratch registers for KCFI_CHECK");
729 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
730 "patchable-function-prefix");
733 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
734 .addReg(ScratchRegs[0])
736 .addImm(-(PrefixNops * 4 + 4)));
740 const int64_t
Type =
MI.getOperand(1).getImm();
741 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
742 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
745 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
746 .addReg(AArch64::WZR)
747 .addReg(ScratchRegs[0])
748 .addReg(ScratchRegs[1])
752 EmitToStreamer(*OutStreamer,
753 MCInstBuilder(AArch64::Bcc)
762 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
766 AddrIndex = AddrReg - AArch64::X0;
776 assert(AddrIndex < 31 && TypeIndex < 31);
778 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
779 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
780 OutStreamer->emitLabel(
Pass);
783void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
791 if (
Reg == AArch64::XZR)
795 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
797 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
798 uint32_t AccessInfo =
MI.getOperand(1).getImm();
800 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
802 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
803 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
805 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
806 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
809 if (!TM.getTargetTriple().isOSBinFormatELF())
812 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
815 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
817 SymName +=
"_short_v2";
818 Sym = OutContext.getOrCreateSymbol(SymName);
821 EmitToStreamer(*OutStreamer,
822 MCInstBuilder(AArch64::BL)
826void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
827 if (HwasanMemaccessSymbols.empty())
830 const Triple &
TT = TM.getTargetTriple();
834 auto STI = std::make_unique<AArch64Subtarget>(
835 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
837 this->STI = STI.get();
840 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
842 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
844 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
846 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
849 for (
auto &
P : HwasanMemaccessSymbols) {
850 unsigned Reg = std::get<0>(
P.first);
851 bool IsShort = std::get<1>(
P.first);
852 uint32_t AccessInfo = std::get<2>(
P.first);
853 bool IsFixedShadow = std::get<3>(
P.first);
854 uint64_t FixedShadowOffset = std::get<4>(
P.first);
855 const MCSymbolRefExpr *HwasanTagMismatchRef =
856 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
859 bool HasMatchAllTag =
861 uint8_t MatchAllTag =
868 OutStreamer->switchSection(OutContext.getELFSection(
874 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
875 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
876 OutStreamer->emitLabel(Sym);
878 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
879 .addReg(AArch64::X16)
889 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
890 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
891 .addReg(AArch64::W16)
892 .addReg(AArch64::X17)
893 .addReg(AArch64::X16)
897 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
898 .addReg(AArch64::W16)
899 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
900 .addReg(AArch64::X16)
905 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
906 .addReg(AArch64::XZR)
907 .addReg(AArch64::X16)
910 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
911 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
914 HandleMismatchOrPartialSym, OutContext)));
915 MCSymbol *ReturnSym = OutContext.createTempSymbol();
916 OutStreamer->emitLabel(ReturnSym);
917 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
918 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
920 if (HasMatchAllTag) {
921 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
922 .addReg(AArch64::X17)
926 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
927 .addReg(AArch64::XZR)
928 .addReg(AArch64::X17)
932 MCInstBuilder(AArch64::Bcc)
938 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
939 .addReg(AArch64::WZR)
940 .addReg(AArch64::W16)
943 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
945 MCInstBuilder(AArch64::Bcc)
949 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
950 .addReg(AArch64::X17)
954 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
955 .addReg(AArch64::X17)
956 .addReg(AArch64::X17)
959 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
960 .addReg(AArch64::WZR)
961 .addReg(AArch64::W16)
962 .addReg(AArch64::W17)
965 MCInstBuilder(AArch64::Bcc)
969 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
970 .addReg(AArch64::X16)
973 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
974 .addReg(AArch64::W16)
975 .addReg(AArch64::X16)
978 MCInstBuilder(AArch64::SUBSXrs)
979 .addReg(AArch64::XZR)
980 .addReg(AArch64::X16)
984 MCInstBuilder(AArch64::Bcc)
988 OutStreamer->emitLabel(HandleMismatchSym);
991 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
997 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
1000 .addReg(AArch64::SP)
1003 if (
Reg != AArch64::X0)
1004 emitMovXReg(AArch64::X0,
Reg);
1007 if (CompileKernel) {
1011 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
1016 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
1017 .addReg(AArch64::X16)
1021 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
1022 .addReg(AArch64::X16)
1023 .addReg(AArch64::X16)
1027 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1030 this->STI =
nullptr;
1035 const MCExpr *StubAuthPtrRef) {
1038 OutStreamer.
emitValue(StubAuthPtrRef, 8);
1041void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
1042 emitHwasanMemaccessSymbols(M);
1044 const Triple &
TT = TM.getTargetTriple();
1045 if (
TT.isOSBinFormatMachO()) {
1047 MachineModuleInfoMachO &MMIMacho =
1048 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1052 if (!Stubs.empty()) {
1054 OutStreamer->switchSection(
1057 emitAlignment(
Align(8));
1059 for (
const auto &Stub : Stubs)
1062 OutStreamer->addBlankLine();
1070 OutStreamer->emitSubsectionsViaSymbols();
1073 if (
TT.isOSBinFormatELF()) {
1075 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1079 if (!Stubs.empty()) {
1080 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1082 emitAlignment(
Align(8));
1084 for (
const auto &Stub : Stubs)
1087 OutStreamer->addBlankLine();
1098 M.getModuleFlag(
"ptrauth-elf-got"));
1099 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1100 for (
const GlobalValue &GV :
M.global_values())
1102 !GV.getName().starts_with(
"llvm."))
1103 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1112 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1113 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1116 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1117 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1128 for (
auto &[Section, CallsToImportedFuncs] :
1129 SectionToImportedFunctionCalls) {
1131 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1132 OutStreamer->emitInt32(SectionSize);
1133 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1134 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1136 OutStreamer->emitInt32(0x13);
1137 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1138 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1144void AArch64AsmPrinter::emitLOHs() {
1148 for (
const MachineInstr *
MI :
D.getArgs()) {
1149 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1150 assert(LabelIt != LOHInstToLabel.end() &&
1151 "Label hasn't been inserted for LOH related instruction");
1154 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1159void AArch64AsmPrinter::emitFunctionBodyEnd() {
1165MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1169 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1170 return OutContext.getOrCreateSymbol(
1171 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1172 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1177void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1179 const MachineOperand &MO =
MI->getOperand(OpNum);
1195 PrintSymbolOperand(MO, O);
1206bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1230bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1232 unsigned AltName, raw_ostream &O) {
1233 assert(MO.
isReg() &&
"Should only get here with a register!");
1234 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1243bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1244 const char *ExtraCode, raw_ostream &O) {
1245 const MachineOperand &MO =
MI->getOperand(OpNum);
1252 if (ExtraCode && ExtraCode[0]) {
1253 if (ExtraCode[1] != 0)
1256 switch (ExtraCode[0]) {
1264 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1278 switch (ExtraCode[0]) {
1280 RC = &AArch64::FPR8RegClass;
1283 RC = &AArch64::FPR16RegClass;
1286 RC = &AArch64::FPR32RegClass;
1289 RC = &AArch64::FPR64RegClass;
1292 RC = &AArch64::FPR128RegClass;
1295 RC = &AArch64::ZPRRegClass;
1300 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1321 unsigned AltName = AArch64::NoRegAltName;
1324 RegClass = &AArch64::ZPRRegClass;
1326 RegClass = &AArch64::PPRRegClass;
1328 RegClass = &AArch64::PNRRegClass;
1330 RegClass = &AArch64::FPR128RegClass;
1331 AltName = AArch64::vreg;
1335 return printAsmRegInClass(MO, RegClass, AltName, O);
1342bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1344 const char *ExtraCode,
1346 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1349 const MachineOperand &MO =
MI->getOperand(OpNum);
1350 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1355void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1357 unsigned NOps =
MI->getNumOperands();
1359 OS <<
'\t' << MAI.getCommentString() <<
"DEBUG_VALUE: ";
1361 OS <<
MI->getDebugVariable()->getName();
1364 assert(
MI->isIndirectDebugValue());
1376void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1377 ArrayRef<unsigned> JumpTableIndices) {
1379 if (JumpTableIndices.
empty())
1381 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1385 MCSection *ReadOnlySec =
nullptr;
1386 if (TM.Options.EnableStaticDataPartitioning) {
1392 OutStreamer->switchSection(ReadOnlySec);
1394 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1395 for (
unsigned JTI : JumpTableIndices) {
1396 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1399 if (JTBBs.empty())
continue;
1401 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1403 OutStreamer->emitLabel(GetJTISymbol(JTI));
1408 for (
auto *JTBB : JTBBs) {
1409 const MCExpr *
Value =
1428AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1429 const MachineInstr *BranchInstr,
1430 const MCSymbol *BranchLabel)
const {
1431 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1434 switch (AFI->getJumpTableEntrySize(JTI)) {
1436 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1439 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1442 EntrySize = codeview::JumpTableEntrySize::Int32;
1447 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1450void AArch64AsmPrinter::emitFunctionEntryLabel() {
1451 const Triple &
TT = TM.getTargetTriple();
1452 if (
TT.isOSBinFormatELF() &&
1455 CallingConv::AArch64_SVE_VectorCall ||
1456 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1458 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1469 OutStreamer->emitAssignment(
1473 auto getSymbolFromMetadata = [&](StringRef
Name) {
1477 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1484 for (MDNode *Node : UnmangledNames) {
1486 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1487 if (std::optional<std::string> MangledName =
1490 MMI->getContext().getOrCreateSymbol(*MangledName);
1491 emitFunctionAlias(UnmangledSym, ECMangledSym);
1494 if (MCSymbol *ECMangledSym =
1495 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1496 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1500void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1501 const Constant *CV) {
1504 "ctors/dtors are to be signed by asm printer");
1506 if (PtrauthInitFini) {
1512 ConstantInt *IntDisc = ConstantInt::get(
1516 if (PtrauthInitFiniAddressDisc) {
1530void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1531 const GlobalAlias &GA) {
1537 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1539 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1542 OutStreamer->beginCOFFSymbolDef(ExpSym);
1546 OutStreamer->endCOFFSymbolDef();
1548 OutStreamer->beginCOFFSymbolDef(Sym);
1552 OutStreamer->endCOFFSymbolDef();
1553 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1554 OutStreamer->emitAssignment(
1571void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1572 const llvm::MachineInstr &
MI) {
1573 Register DestReg =
MI.getOperand(0).getReg();
1574 Register ScratchReg =
MI.getOperand(1).getReg();
1576 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1577 Register TableReg =
MI.getOperand(2).getReg();
1578 Register EntryReg =
MI.getOperand(3).getReg();
1579 int JTIdx =
MI.getOperand(4).getIndex();
1585 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1596 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1598 .addExpr(LabelExpr));
1603 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1604 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1605 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1610 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1611 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1615 .addImm(
Size == 1 ? 0 : 1));
1619 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1623 .addImm(
Size == 4 ? 0 : 2));
1626void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1628 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1630 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1631 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1647 MachineOperand JTOp =
MI.getOperand(0);
1651 "unsupported compressed jump table");
1653 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1657 uint64_t MaxTableEntry = NumTableEntries - 1;
1659 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1660 .addReg(AArch64::XZR)
1661 .addReg(AArch64::X16)
1662 .addImm(MaxTableEntry)
1665 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1670 if ((MaxTableEntry >>
Offset) == 0)
1672 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1675 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1676 .addReg(AArch64::XZR)
1677 .addReg(AArch64::X16)
1678 .addReg(AArch64::X17)
1684 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1685 .addReg(AArch64::X16)
1686 .addReg(AArch64::X16)
1687 .addReg(AArch64::XZR)
1691 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1692 MCOperand JTMCHi, JTMCLo;
1702 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1704 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1705 .addReg(AArch64::X17)
1706 .addReg(AArch64::X17)
1710 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1711 .addReg(AArch64::X16)
1712 .addReg(AArch64::X17)
1713 .addReg(AArch64::X16)
1724 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1726 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1727 .addReg(AArch64::X16)
1728 .addReg(AArch64::X17)
1729 .addReg(AArch64::X16)
1732 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1735void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1736 const llvm::MachineInstr &
MI) {
1737 unsigned Opcode =
MI.getOpcode();
1739 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1741 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1742 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1743 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1744 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1745 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1746 if (Opcode == AArch64::MOPSMemorySetPseudo)
1747 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1748 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1749 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1752 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1753 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1755 for (
auto Op :
Ops) {
1757 auto MCIB = MCInstBuilder(
Op);
1759 MCIB.addReg(
MI.getOperand(i++).getReg());
1760 MCIB.addReg(
MI.getOperand(i++).getReg());
1762 MCIB.addReg(
MI.getOperand(i++).getReg());
1764 MCIB.addReg(
MI.getOperand(i++).getReg());
1765 MCIB.addReg(
MI.getOperand(i++).getReg());
1766 MCIB.addReg(
MI.getOperand(i++).getReg());
1768 EmitToStreamer(OutStreamer, MCIB);
1772void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1773 const MachineInstr &
MI) {
1774 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1777 MCSymbol *MILabel = Ctx.createTempSymbol();
1781 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1787 while (NumNOPBytes > 0) {
1788 if (MII ==
MBB.
end() || MII->isCall() ||
1789 MII->getOpcode() == AArch64::DBG_VALUE ||
1790 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1791 MII->getOpcode() == TargetOpcode::STACKMAP)
1798 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1799 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1804void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1805 const MachineInstr &
MI) {
1807 MCSymbol *MILabel = Ctx.createTempSymbol();
1811 PatchPointOpers Opers(&
MI);
1813 int64_t CallTarget = Opers.getCallTarget().getImm();
1814 unsigned EncodedBytes = 0;
1816 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1817 "High 16 bits of call target should be zero.");
1818 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1821 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1822 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1823 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1824 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1827 unsigned NumBytes = Opers.getNumPatchBytes();
1828 assert(NumBytes >= EncodedBytes &&
1829 "Patchpoint can't request size less than the length of a call.");
1830 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1831 "Invalid number of NOP bytes requested!");
1832 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1833 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1836void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1837 const MachineInstr &
MI) {
1838 StatepointOpers SOpers(&
MI);
1839 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1840 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1841 for (
unsigned i = 0; i < PatchBytes; i += 4)
1842 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1845 const MachineOperand &CallTarget = SOpers.getCallTarget();
1846 MCOperand CallTargetMCOp;
1847 unsigned CallOpcode;
1848 switch (CallTarget.
getType()) {
1851 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1852 CallOpcode = AArch64::BL;
1856 CallOpcode = AArch64::BL;
1860 CallOpcode = AArch64::BLR;
1867 EmitToStreamer(OutStreamer,
1868 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1872 MCSymbol *MILabel = Ctx.createTempSymbol();
1877void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1886 unsigned OperandsBeginIdx = 4;
1889 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1896 MI.setOpcode(Opcode);
1901 for (
const MachineOperand &MO :
1904 lowerOperand(MO, Dest);
1905 MI.addOperand(Dest);
1913 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1915 .addReg(AArch64::XZR)
1921 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1922 EmitToStreamer(*OutStreamer,
1923 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1930 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1931 EmitToStreamer(*OutStreamer,
1932 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1941 bool IsZeroDisc = Disc == AArch64::XZR;
1953 EmitToStreamer(AUTInst);
1958 bool IsZeroDisc = Disc == AArch64::XZR;
1970 EmitToStreamer(PACInst);
1975 bool IsZeroDisc = Disc == AArch64::XZR;
1985 EmitToStreamer(Inst);
1988void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1989 Register DestReg =
MI.getOperand(0).getReg();
1990 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1991 if (STI->hasZeroCycleZeroingFPR64()) {
1993 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1994 if (AArch64::FPR16RegClass.
contains(DestReg))
1995 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1996 &AArch64::FPR64RegClass);
1997 else if (AArch64::FPR32RegClass.
contains(DestReg))
1998 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1999 &AArch64::FPR64RegClass);
2007 EmitToStreamer(*OutStreamer, MOVI);
2008 ++NumZCZeroingInstrsFPR;
2009 }
else if (STI->hasZeroCycleZeroingFPR128()) {
2011 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2012 if (AArch64::FPR16RegClass.
contains(DestReg)) {
2013 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2014 &AArch64::FPR128RegClass);
2015 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
2016 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2017 &AArch64::FPR128RegClass);
2020 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
2021 &AArch64::FPR128RegClass);
2028 EmitToStreamer(*OutStreamer, MOVI);
2029 ++NumZCZeroingInstrsFPR;
2031 emitFMov0AsFMov(
MI, DestReg);
2034 emitFMov0AsFMov(
MI, DestReg);
2038void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
2041 switch (
MI.getOpcode()) {
2044 case AArch64::FMOVH0:
2045 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
2046 if (!STI->hasFullFP16())
2047 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
2051 case AArch64::FMOVS0:
2056 case AArch64::FMOVD0:
2062 EmitToStreamer(*OutStreamer, FMov);
2068 bool MayClobberAddrDisc) {
2069 assert(isPtrauthRegSafe(ScratchReg) &&
2070 "Safe scratch register must be provided by the caller");
2074 if (AddrDisc == AArch64::NoRegister)
2075 AddrDisc = AArch64::XZR;
2083 if (AddrDisc == AArch64::XZR) {
2084 emitMOVZ(ScratchReg, Disc, 0);
2091 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2092 ScratchReg = AddrDisc;
2094 emitMovXReg(ScratchReg, AddrDisc);
2095 assert(ScratchReg != AddrDisc &&
2096 "Forbidden to clobber AddrDisc, but have to");
2099 emitMOVK(ScratchReg, Disc, 48);
2113void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2145 if (Method == AuthCheckMethod::None)
2147 if (Method == AuthCheckMethod::DummyLoad) {
2148 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2152 assert(!OnFailure &&
"DummyLoad always traps on error");
2156 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2157 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2159 emitMovXReg(ScratchReg, TestedReg);
2161 if (Method == AuthCheckMethod::XPAC) {
2165 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2170 assert(TestedReg == AArch64::LR &&
2171 "XPACHint mode is only compatible with checking the LR register");
2173 "XPACHint mode is only compatible with I-keys");
2174 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2178 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2179 .addReg(AArch64::XZR)
2186 MCInstBuilder(AArch64::Bcc)
2189 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2191 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2198 MCInstBuilder(AArch64::TBZX)
2209 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2223 case AuthCheckMethod::XPACHint:
2226 case AuthCheckMethod::XPAC:
2228 emitMovXReg(TestedReg, ScratchReg);
2235 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2240 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2252void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2256 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2257 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2260 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2264 "Neither x16 nor x17 is available as a scratch register");
2267 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2271bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2277 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2280 MCSymbol *Dot = OutContext.createTempSymbol();
2285 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2291AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateImmReg(
2293 PtrAuthSchema Schema;
2295 Schema.IntDisc = IntDisc;
2296 Schema.AddrDisc = AddrDiscOp.
getReg();
2297 Schema.AddrDiscIsKilled = AddrDiscOp.
isKill();
2298 Schema.PCDisc = AArch64::NoRegister;
2302AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateRegReg(
2304 assert(PCDisc != AArch64::NoRegister &&
2305 "Use CreateImmReg for non-PC schemas");
2306 PtrAuthSchema Schema;
2309 Schema.AddrDisc = AddrDisc;
2310 Schema.AddrDiscIsKilled =
false;
2311 Schema.PCDisc = PCDisc;
2315void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2320 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2330 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2332 MCInstBuilder(AArch64::ADDXri)
2335 .addImm((Addend >> BitPos) & 0xfff)
2341 emitMOVZ(Scratch, Addend & 0xffff, 0);
2343 if (
unsigned Fragment = (Addend >>
Offset) & 0xffff)
2344 emitMOVK(Scratch, Fragment,
Offset);
2348 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2355 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2361 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2412void AArch64AsmPrinter::emitPtrauthAuthResign(
2414 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2417 const bool IsAuthWithPC = AuthSchema.PCDisc != AArch64::NoRegister;
2418 assert(!SignSchema || SignSchema->PCDisc == AArch64::NoRegister);
2421 SignSchema ? SignSchema->AddrDisc : AArch64::NoRegister;
2427 assert(Pointer == AArch64::X17 && Scratch == AArch64::X16 &&
2428 "AUTPCPAC must use x17/x16 as Pointer/Scratch");
2430 assert(AuthSchema.AddrDisc == AArch64::X16 &&
2431 "AUTPCPAC requires address discriminator in X16");
2433 assert(AuthSchema.PCDisc == AArch64::X15 &&
2434 "AUTPCPAC requires PC discriminator in X15");
2436 assert(AuthSchema.IntDisc == 0 &&
"AUTPCPAC does not support IntDisc");
2440 "AUTPCPAC only supports AUT-ing with IA/IB");
2442 if (!emitDeactivationSymbolRelocation(DS)) {
2444 ? AArch64::AUTIB171615
2445 : AArch64::AUTIA171615;
2446 EmitToStreamer(MCInstBuilder(AutOpc));
2456 Register AUTDiscReg = emitPtrauthDiscriminator(
2457 AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2458 AuthSchema.addrDiscIsKilledAndNoneOf({Pointer, SignAddrDiscOrNone}));
2459 if (!emitDeactivationSymbolRelocation(DS))
2460 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2465 auto EmitCheck = [&](
MCSymbol *OnFailure =
nullptr) {
2466 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2467 AArch64PAuth::AuthCheckMethod::XPAC,
2471 auto EmitResignOnSuccess = [&]() {
2472 if (Addend.has_value())
2473 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2475 assert(Pointer != SignSchema->AddrDisc &&
"Pointer is early-clobbered");
2477 emitPtrauthDiscriminator(SignSchema->IntDisc, SignSchema->AddrDisc,
2478 Scratch, SignSchema->AddrDiscIsKilled);
2479 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2491 switch (CheckMode) {
2493 EmitResignOnSuccess();
2497 EmitResignOnSuccess();
2500 MCSymbol *OnFailure = createTempSymbol(
"resign_end_");
2501 EmitCheck(OnFailure);
2502 EmitResignOnSuccess();
2508void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2512 Register AddrDisc =
MI->getOperand(4).getReg();
2513 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2517 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2518 assert(ScratchReg != AddrDisc &&
2519 "Neither X16 nor X17 is available as a scratch register");
2522 Register DiscReg = emitPtrauthDiscriminator(
2523 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2525 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2528 emitPAC(
Key, Val, DiscReg);
2531void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2532 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2533 unsigned BrTarget =
MI->getOperand(0).getReg();
2538 unsigned AddrDisc =
MI->getOperand(3).getReg();
2544 if (BrTarget == AddrDisc)
2561 bool AddrDiscIsImplicitDef =
2562 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2563 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2564 AddrDiscIsImplicitDef);
2565 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2568void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2572 const bool IsNeg = Addend < 0;
2574 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2577 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2580 .addImm((AbsOffset >> BitPos) & 0xfff)
2585 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2587 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2589 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2590 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2591 uint64_t Shifted = UAddend >> BitPos;
2593 return Shifted != 0;
2594 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2595 if (((Shifted >>
I) & 0xffff) != 0xffff)
2599 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2600 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2602 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2611void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2612 MCRegister Tmp,
bool DSOLocal,
2613 const MCSubtargetInfo &STI) {
2619 MCInstBuilder(AArch64::ADRP)
2623 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2633 MCInstBuilder(AArch64::ADRP)
2638 MCInstBuilder(AArch64::LDRXui)
2649 if (!TT.isOSBinFormatELF())
2653 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2654 TT.isOSDragonFly() || TT.isOSNetBSD();
2708const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2710 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2711 const Triple &
TT = TM.getTargetTriple();
2723 auto STI = std::make_unique<AArch64Subtarget>(
2724 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2726 this->STI = STI.get();
2732 const MCSymbolELF *Group =
2747 .addReg(AArch64::X0)
2752 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2754 if (HasAddressDiversity) {
2759 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2763 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2765 "' out of range [0, 0xFFFF]");
2767 emitMOVZ(AArch64::X1, Disc, 0);
2774 auto *PrePACInstExpr =
2786 const MCSymbolRefExpr *EmuPACRef =
2788 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2795 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2804AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2805 MCContext &Ctx = OutContext;
2810 getDataLayout(),
Offset,
true);
2830 const MCExpr *DSExpr =
nullptr;
2842 "' out of range [0, " +
2850 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2852 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2857 "' out of range [0, 0xFFFF]");
2863 "expressions on this target");
2870void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2871 unsigned DstReg =
MI.getOperand(0).getReg();
2872 const MachineOperand &GAOp =
MI.getOperand(1);
2873 const uint64_t KeyC =
MI.getOperand(2).getImm();
2875 "key is out of range [0, AArch64PACKey::LAST]");
2877 const uint64_t Disc =
MI.getOperand(3).getImm();
2879 "constant discriminator is out of range [0, 0xffff]");
2888 if (TM.getTargetTriple().isOSBinFormatELF()) {
2890 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2893 "non-zero offset for $auth_ptr$ stub slots is not supported");
2895 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2897 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2898 "LOADauthptrstatic is implemented only for MachO/ELF");
2900 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2901 getObjFileLowering());
2904 "non-zero offset for $auth_ptr$ stub slots is not supported");
2906 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2909 MachineOperand StubMOHi =
2913 MCOperand StubMCHi, StubMCLo;
2920 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2922 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2928void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2929 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2930 const bool IsELFSignedGOT =
MI.getParent()
2932 ->getInfo<AArch64FunctionInfo>()
2933 ->hasELFSignedGOT();
2934 MachineOperand GAOp =
MI.getOperand(0);
2935 const uint64_t KeyC =
MI.getOperand(1).getImm();
2937 "key is out of range [0, AArch64PACKey::LAST]");
2939 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2940 const uint64_t Disc =
MI.getOperand(3).getImm();
2987 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2988 MCOperand GAMCHi, GAMCLo;
3001 MCInstBuilder(AArch64::ADRP)
3002 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
3006 if (IsELFSignedGOT) {
3007 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3008 .addReg(AArch64::X17)
3009 .addReg(AArch64::X17)
3013 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3014 .addReg(AArch64::X16)
3015 .addReg(AArch64::X17)
3023 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
3025 if (!STI->hasFPAC())
3026 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
3027 AArch64PAuth::AuthCheckMethod::XPAC);
3029 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3030 .addReg(AArch64::X16)
3031 .addReg(AArch64::X16)
3035 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3036 .addReg(AArch64::X16)
3037 .addReg(AArch64::X16)
3042 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
3043 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
3045 emitPAC(
Key, AArch64::X16, DiscReg);
3048void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
3050 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
3051 const MachineOperand &GAMO =
MI.getOperand(1);
3058 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
3059 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3060 .addReg(AuthResultReg)
3061 .addReg(AArch64::X17)
3064 MachineOperand GAHiOp(GAMO);
3065 MachineOperand GALoOp(GAMO);
3069 MCOperand GAMCHi, GAMCLo;
3074 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
3076 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3077 .addReg(AArch64::X17)
3078 .addReg(AArch64::X17)
3082 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3083 .addReg(AuthResultReg)
3084 .addReg(AArch64::X17)
3091 UndefWeakSym = createTempSymbol(
"undef_weak");
3093 MCInstBuilder(AArch64::CBZX)
3094 .addReg(AuthResultReg)
3102 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
3107 if (!STI->hasFPAC()) {
3108 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
3109 AArch64PAuth::AuthCheckMethod::XPAC);
3111 emitMovXReg(DstReg, AuthResultReg);
3116AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
3120 if (std::optional<uint16_t> BADisc =
3121 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3128void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3132 switch (
MI->getOpcode()) {
3135 case AArch64::CBBAssertExt:
3139 case AArch64::CBHAssertExt:
3143 case AArch64::CBWPrr:
3146 case AArch64::CBXPrr:
3149 case AArch64::CBWPri:
3153 case AArch64::CBXPri:
3161 bool NeedsRegSwap =
false;
3162 bool NeedsImmDec =
false;
3163 bool NeedsImmInc =
false;
3165#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3167 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3169 ? AArch64::CBB##RegCond##Wrr \
3170 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3171 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3172 : AArch64::CB##RegCond##Xrr))))
3188 NeedsImmDec = IsImm;
3192 NeedsRegSwap = !IsImm;
3199 NeedsRegSwap = !IsImm;
3200 NeedsImmInc = IsImm;
3204 NeedsImmDec = IsImm;
3208 NeedsRegSwap = !IsImm;
3215 NeedsRegSwap = !IsImm;
3216 NeedsImmInc = IsImm;
3224 MCOperand Lhs, Rhs, Trgt;
3225 lowerOperand(
MI->getOperand(1), Lhs);
3226 lowerOperand(
MI->getOperand(2), Rhs);
3227 lowerOperand(
MI->getOperand(3), Trgt);
3231 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3232 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3235 }
else if (NeedsImmDec) {
3239 }
else if (NeedsImmInc) {
3249 "CB immediate operand out-of-bounds");
3252 EmitToStreamer(*OutStreamer, Inst);
3257#include "AArch64GenMCPseudoLowering.inc"
3259void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3266void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3267 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3272 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3277 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3278 EmitToStreamer(*OutStreamer, OutInst);
3282 if (
MI->getOpcode() == AArch64::ADRP) {
3283 for (
auto &Opd :
MI->operands()) {
3284 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3285 "swift_async_extendedFramePointerFlags") {
3286 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3293 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3295 LOHInstToLabel[
MI] = LOHLabel;
3299 AArch64TargetStreamer *TS =
3302 switch (
MI->getOpcode()) {
3305 "Unhandled tail call instruction");
3307 case AArch64::READ_REGISTER_GPR64:
3311 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
3312 .addReg(
MI->getOperand(0).getReg())
3313 .addReg(AArch64::XZR)
3314 .addReg(
MI->getOperand(1).getImm())
3317 case AArch64::READ_REGISTER_FPR64:
3319 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::FMOVDr)
3320 .addReg(
MI->getOperand(0).getReg())
3321 .addReg(
MI->getOperand(1).getImm()));
3323 case AArch64::HINT: {
3328 if (CurrentPatchableFunctionEntrySym &&
3329 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3331 int64_t
Imm =
MI->getOperand(0).getImm();
3332 if (
Imm == 32 ||
Imm == 34 ||
Imm == 36 ||
Imm == 38) {
3334 MCInstLowering.
Lower(
MI, Inst);
3335 EmitToStreamer(*OutStreamer, Inst);
3336 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3337 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3343 case AArch64::MOVMCSym: {
3344 Register DestReg =
MI->getOperand(0).getReg();
3345 const MachineOperand &MO_Sym =
MI->getOperand(1);
3346 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3347 MCOperand Hi_MCSym, Lo_MCSym;
3360 EmitToStreamer(*OutStreamer, MovZ);
3368 EmitToStreamer(*OutStreamer, MovK);
3371 case AArch64::MOVIv2d_ns:
3379 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3380 MI->getOperand(1).getImm() == 0) {
3382 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3385 EmitToStreamer(*OutStreamer, TmpInst);
3390 case AArch64::DBG_VALUE:
3391 case AArch64::DBG_VALUE_LIST:
3393 SmallString<128> TmpStr;
3394 raw_svector_ostream OS(TmpStr);
3395 PrintDebugValueComment(
MI, OS);
3400 case AArch64::EMITBKEY: {
3402 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3403 ExceptionHandlingType != ExceptionHandling::ARM)
3406 if (getFunctionCFISectionType(*MF) == CFISection::None)
3413 case AArch64::EMITMTETAGGED: {
3415 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3416 ExceptionHandlingType != ExceptionHandling::ARM)
3419 if (getFunctionCFISectionType(*MF) != CFISection::None)
3424 case AArch64::AUTx16x17: {
3426 const Register Scratch = AArch64::X17;
3428 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3430 MI->getOperand(1).getImm(),
MI->getOperand(2));
3432 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3433 std::nullopt,
MI->getDeactivationSymbol());
3437 case AArch64::AUTxMxN: {
3439 const Register Scratch =
MI->getOperand(1).getReg();
3441 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3443 MI->getOperand(4).getImm(),
MI->getOperand(5));
3445 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3446 std::nullopt,
MI->getDeactivationSymbol());
3450 case AArch64::AUTPAC: {
3452 const Register Scratch = AArch64::X17;
3454 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3456 MI->getOperand(1).getImm(),
MI->getOperand(2));
3458 auto SignSchema = PtrAuthSchema::CreateImmReg(
3460 MI->getOperand(4).getImm(),
MI->getOperand(5));
3462 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3463 std::nullopt,
MI->getDeactivationSymbol());
3467 case AArch64::AUTPCPAC: {
3468 auto AuthSchema = PtrAuthSchema::CreateRegReg(
3472 auto SignSchema = PtrAuthSchema::CreateImmReg(
3474 MI->getOperand(2).getImm(),
MI->getOperand(3));
3476 emitPtrauthAuthResign(AArch64::X17, AArch64::X16,
3477 AuthSchema, SignSchema, std::nullopt,
3478 MI->getDeactivationSymbol());
3482 case AArch64::AUTRELLOADPAC: {
3484 const Register Scratch = AArch64::X17;
3486 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3488 MI->getOperand(1).getImm(),
MI->getOperand(2));
3490 auto SignSchema = PtrAuthSchema::CreateImmReg(
3492 MI->getOperand(4).getImm(),
MI->getOperand(5));
3494 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3495 MI->getOperand(6).getImm(),
3496 MI->getDeactivationSymbol());
3502 emitPtrauthSign(
MI);
3505 case AArch64::LOADauthptrstatic:
3506 LowerLOADauthptrstatic(*
MI);
3509 case AArch64::LOADgotPAC:
3510 case AArch64::MOVaddrPAC:
3511 LowerMOVaddrPAC(*
MI);
3514 case AArch64::LOADgotAUTH:
3515 LowerLOADgotAUTH(*
MI);
3520 emitPtrauthBranch(
MI);
3526 case AArch64::AUTH_TCRETURN:
3527 case AArch64::AUTH_TCRETURN_BTI: {
3530 const uint64_t Disc =
MI->getOperand(3).getImm();
3532 Register AddrDisc =
MI->getOperand(4).getReg();
3534 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3536 emitPtrauthTailCallHardening(
MI);
3539 if (Callee == AddrDisc)
3546 bool AddrDiscIsImplicitDef =
3547 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3548 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3549 AddrDiscIsImplicitDef);
3550 emitBLRA(
false,
Key, Callee, DiscReg);
3554 case AArch64::TCRETURNri:
3555 case AArch64::TCRETURNrix16x17:
3556 case AArch64::TCRETURNrix17:
3557 case AArch64::TCRETURNrinotx16:
3558 case AArch64::TCRETURNriALL: {
3559 emitPtrauthTailCallHardening(
MI);
3561 recordIfImportCall(
MI);
3565 EmitToStreamer(*OutStreamer, TmpInst);
3568 case AArch64::TCRETURNdi: {
3569 emitPtrauthTailCallHardening(
MI);
3573 recordIfImportCall(
MI);
3577 EmitToStreamer(*OutStreamer, TmpInst);
3580 case AArch64::SpeculationBarrierISBDSBEndBB: {
3585 EmitToStreamer(*OutStreamer, TmpInstDSB);
3589 EmitToStreamer(*OutStreamer, TmpInstISB);
3592 case AArch64::SpeculationBarrierSBEndBB: {
3596 EmitToStreamer(*OutStreamer, TmpInstSB);
3599 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3606 const MachineOperand &MO_Sym =
MI->getOperand(0);
3607 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3608 MCOperand SymTLSDescLo12, SymTLSDesc;
3611 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3618 EmitToStreamer(*OutStreamer, Adrp);
3626 EmitToStreamer(*OutStreamer, Ldr);
3629 Add.setOpcode(AArch64::ADDXri);
3632 Add.addOperand(SymTLSDescLo12);
3634 EmitToStreamer(*OutStreamer,
Add);
3643 EmitToStreamer(*OutStreamer, Blraa);
3647 case AArch64::TLSDESC_CALLSEQ: {
3655 const MachineOperand &MO_Sym =
MI->getOperand(0);
3656 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3657 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3661 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3668 EmitToStreamer(*OutStreamer, Adrp);
3671 if (STI->isTargetILP32()) {
3681 EmitToStreamer(*OutStreamer, Ldr);
3684 if (STI->isTargetILP32()) {
3685 Add.setOpcode(AArch64::ADDWri);
3689 Add.setOpcode(AArch64::ADDXri);
3693 Add.addOperand(SymTLSDescLo12);
3695 EmitToStreamer(*OutStreamer,
Add);
3700 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3702 EmitToStreamer(*OutStreamer, TLSDescCall);
3710 EmitToStreamer(*OutStreamer, Blr);
3715 case AArch64::JumpTableDest32:
3716 case AArch64::JumpTableDest16:
3717 case AArch64::JumpTableDest8:
3718 LowerJumpTableDest(*OutStreamer, *
MI);
3721 case AArch64::BR_JumpTable:
3722 LowerHardenedBRJumpTable(*
MI);
3725 case AArch64::FMOVH0:
3726 case AArch64::FMOVS0:
3727 case AArch64::FMOVD0:
3731 case AArch64::MOPSMemoryCopyPseudo:
3732 case AArch64::MOPSMemoryMovePseudo:
3733 case AArch64::MOPSMemorySetPseudo:
3734 case AArch64::MOPSMemorySetTaggingPseudo:
3735 LowerMOPS(*OutStreamer, *
MI);
3738 case TargetOpcode::STACKMAP:
3739 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3741 case TargetOpcode::PATCHPOINT:
3742 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3744 case TargetOpcode::STATEPOINT:
3745 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3747 case TargetOpcode::FAULTING_OP:
3748 return LowerFAULTING_OP(*
MI);
3750 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3751 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3754 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3755 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3758 case TargetOpcode::PATCHABLE_TAIL_CALL:
3759 LowerPATCHABLE_TAIL_CALL(*
MI);
3761 case TargetOpcode::PATCHABLE_EVENT_CALL:
3762 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3763 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3764 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3766 case AArch64::KCFI_CHECK:
3767 LowerKCFI_CHECK(*
MI);
3770 case AArch64::HWASAN_CHECK_MEMACCESS:
3771 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3772 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3773 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3774 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3777 case AArch64::SEH_StackAlloc:
3781 case AArch64::SEH_SaveFPLR:
3785 case AArch64::SEH_SaveFPLR_X:
3786 assert(
MI->getOperand(0).getImm() < 0 &&
3787 "Pre increment SEH opcode must have a negative offset");
3791 case AArch64::SEH_SaveReg:
3793 MI->getOperand(1).getImm());
3796 case AArch64::SEH_SaveReg_X:
3797 assert(
MI->getOperand(1).getImm() < 0 &&
3798 "Pre increment SEH opcode must have a negative offset");
3800 -
MI->getOperand(1).getImm());
3803 case AArch64::SEH_SaveRegP:
3804 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3805 MI->getOperand(0).getImm() <= 28) {
3806 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3807 "Register paired with LR must be odd");
3809 MI->getOperand(2).getImm());
3812 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3813 "Non-consecutive registers not allowed for save_regp");
3815 MI->getOperand(2).getImm());
3818 case AArch64::SEH_SaveRegP_X:
3819 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3820 "Non-consecutive registers not allowed for save_regp_x");
3821 assert(
MI->getOperand(2).getImm() < 0 &&
3822 "Pre increment SEH opcode must have a negative offset");
3824 -
MI->getOperand(2).getImm());
3827 case AArch64::SEH_SaveFReg:
3829 MI->getOperand(1).getImm());
3832 case AArch64::SEH_SaveFReg_X:
3833 assert(
MI->getOperand(1).getImm() < 0 &&
3834 "Pre increment SEH opcode must have a negative offset");
3836 -
MI->getOperand(1).getImm());
3839 case AArch64::SEH_SaveFRegP:
3840 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3841 "Non-consecutive registers not allowed for save_regp");
3843 MI->getOperand(2).getImm());
3846 case AArch64::SEH_SaveFRegP_X:
3847 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3848 "Non-consecutive registers not allowed for save_regp_x");
3849 assert(
MI->getOperand(2).getImm() < 0 &&
3850 "Pre increment SEH opcode must have a negative offset");
3852 -
MI->getOperand(2).getImm());
3855 case AArch64::SEH_SetFP:
3859 case AArch64::SEH_AddFP:
3863 case AArch64::SEH_Nop:
3867 case AArch64::SEH_PrologEnd:
3871 case AArch64::SEH_EpilogStart:
3875 case AArch64::SEH_EpilogEnd:
3879 case AArch64::SEH_PACSignLR:
3883 case AArch64::SEH_SaveAnyRegI:
3884 assert(
MI->getOperand(1).getImm() <= 1008 &&
3885 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3887 MI->getOperand(1).getImm());
3890 case AArch64::SEH_SaveAnyRegIP:
3891 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3892 "Non-consecutive registers not allowed for save_any_reg");
3893 assert(
MI->getOperand(2).getImm() <= 1008 &&
3894 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3896 MI->getOperand(2).getImm());
3899 case AArch64::SEH_SaveAnyRegQP:
3900 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3901 "Non-consecutive registers not allowed for save_any_reg");
3902 assert(
MI->getOperand(2).getImm() >= 0 &&
3903 "SaveAnyRegQP SEH opcode offset must be non-negative");
3904 assert(
MI->getOperand(2).getImm() <= 1008 &&
3905 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3907 MI->getOperand(2).getImm());
3910 case AArch64::SEH_SaveAnyRegQPX:
3911 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3912 "Non-consecutive registers not allowed for save_any_reg");
3913 assert(
MI->getOperand(2).getImm() < 0 &&
3914 "SaveAnyRegQPX SEH opcode offset must be negative");
3915 assert(
MI->getOperand(2).getImm() >= -1008 &&
3916 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3918 -
MI->getOperand(2).getImm());
3921 case AArch64::SEH_AllocZ:
3922 assert(
MI->getOperand(0).getImm() >= 0 &&
3923 "AllocZ SEH opcode offset must be non-negative");
3924 assert(
MI->getOperand(0).getImm() <= 255 &&
3925 "AllocZ SEH opcode offset must fit into 8 bits");
3929 case AArch64::SEH_SaveZReg:
3930 assert(
MI->getOperand(1).getImm() >= 0 &&
3931 "SaveZReg SEH opcode offset must be non-negative");
3932 assert(
MI->getOperand(1).getImm() <= 255 &&
3933 "SaveZReg SEH opcode offset must fit into 8 bits");
3935 MI->getOperand(1).getImm());
3938 case AArch64::SEH_SavePReg:
3939 assert(
MI->getOperand(1).getImm() >= 0 &&
3940 "SavePReg SEH opcode offset must be non-negative");
3941 assert(
MI->getOperand(1).getImm() <= 255 &&
3942 "SavePReg SEH opcode offset must fit into 8 bits");
3944 MI->getOperand(1).getImm());
3949 recordIfImportCall(
MI);
3951 MCInstLowering.
Lower(
MI, TmpInst);
3952 EmitToStreamer(*OutStreamer, TmpInst);
3955 case AArch64::CBWPri:
3956 case AArch64::CBXPri:
3957 case AArch64::CBBAssertExt:
3958 case AArch64::CBHAssertExt:
3959 case AArch64::CBWPrr:
3960 case AArch64::CBXPrr:
3961 emitCBPseudoExpansion(
MI);
3965 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3970 MCInstLowering.
Lower(
MI, TmpInst);
3971 EmitToStreamer(*OutStreamer, TmpInst);
3974void AArch64AsmPrinter::recordIfImportCall(
3975 const llvm::MachineInstr *BranchInst) {
3976 if (!EnableImportCallOptimization)
3980 if (GV && GV->hasDLLImportStorageClass()) {
3981 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3986 .push_back({CallSiteSymbol, CalledSymbol});
3990void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3991 MCSymbol *LazyPointer) {
4008 EmitToStreamer(Adrp);
4016 MCOperand SymPageOff;
4023 EmitToStreamer(Ldr);
4026 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
4027 .addReg(AArch64::X16)
4028 .addReg(AArch64::X16)
4031 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4033 .addReg(AArch64::X16));
4036void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
4037 const GlobalIFunc &GI,
4038 MCSymbol *LazyPointer) {
4070 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4071 .addReg(AArch64::SP)
4072 .addReg(AArch64::FP)
4073 .addReg(AArch64::LR)
4074 .addReg(AArch64::SP)
4077 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4078 .addReg(AArch64::FP)
4079 .addReg(AArch64::SP)
4083 for (
int I = 0;
I != 4; ++
I)
4084 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4085 .addReg(AArch64::SP)
4086 .addReg(AArch64::X1 + 2 *
I)
4087 .addReg(AArch64::X0 + 2 *
I)
4088 .addReg(AArch64::SP)
4091 for (
int I = 0;
I != 4; ++
I)
4092 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
4093 .addReg(AArch64::SP)
4094 .addReg(AArch64::D1 + 2 *
I)
4095 .addReg(AArch64::D0 + 2 *
I)
4096 .addReg(AArch64::SP)
4100 MCInstBuilder(AArch64::BL)
4113 EmitToStreamer(Adrp);
4121 MCOperand SymPageOff;
4128 EmitToStreamer(Ldr);
4131 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
4132 .addReg(AArch64::X0)
4133 .addReg(AArch64::X16)
4136 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4137 .addReg(AArch64::X16)
4138 .addReg(AArch64::X0)
4142 for (
int I = 3;
I != -1; --
I)
4143 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
4144 .addReg(AArch64::SP)
4145 .addReg(AArch64::D1 + 2 *
I)
4146 .addReg(AArch64::D0 + 2 *
I)
4147 .addReg(AArch64::SP)
4150 for (
int I = 3;
I != -1; --
I)
4151 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4152 .addReg(AArch64::SP)
4153 .addReg(AArch64::X1 + 2 *
I)
4154 .addReg(AArch64::X0 + 2 *
I)
4155 .addReg(AArch64::SP)
4158 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4159 .addReg(AArch64::SP)
4160 .addReg(AArch64::FP)
4161 .addReg(AArch64::LR)
4162 .addReg(AArch64::SP)
4165 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4167 .addReg(AArch64::X16));
4170const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4171 const Constant *BaseCV,
4181char AArch64AsmPrinter::ID = 0;
4184 "AArch64 Assembly Printer",
false,
false)
4188LLVMInitializeAArch64AsmPrinter() {
4198 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4208 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4219 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
This file defines the DenseMap class.
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 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,...