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);
294 void emitAtomicHintPseudoExpansion(
const MachineInstr *
MI);
295 void emitAtomicHintPseudoExpansionRO(
const MachineInstr *
MI);
296 void emitAtomicHintPseudoExpansionImm(
const MachineInstr *
MI);
298 void EmitToStreamer(MCStreamer &S,
const MCInst &Inst);
299 void EmitToStreamer(
const MCInst &Inst) {
300 EmitToStreamer(*OutStreamer, Inst);
305 void emitFunctionHeaderComment()
override;
307 void getAnalysisUsage(AnalysisUsage &AU)
const override {
313 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
314 PSI = &PSIW->getPSI();
316 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
317 SDPI = &SDPIW->getStaticDataProfileInfo();
319 AArch64FI = MF.
getInfo<AArch64FunctionInfo>();
322 SetupMachineFunction(MF);
324 if (STI->isTargetCOFF()) {
331 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
332 OutStreamer->emitCOFFSymbolStorageClass(Scl);
333 OutStreamer->emitCOFFSymbolType(
Type);
334 OutStreamer->endCOFFSymbolDef();
348 const Constant *BaseCV =
nullptr,
352 void printOperand(
const MachineInstr *
MI,
unsigned OpNum, raw_ostream &O);
354 bool printAsmRegInClass(
const MachineOperand &MO,
358 bool PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
359 const char *ExtraCode, raw_ostream &O)
override;
360 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
361 const char *ExtraCode, raw_ostream &O)
override;
363 void PrintDebugValueComment(
const MachineInstr *
MI, raw_ostream &OS);
365 void emitFunctionBodyEnd()
override;
366 void emitGlobalAlias(
const Module &M,
const GlobalAlias &GA)
override;
368 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
369 void emitEndOfAsmFile(
Module &M)
override;
371 AArch64FunctionInfo *AArch64FI =
nullptr;
386 void emitFMov0(
const MachineInstr &
MI);
387 void emitFMov0AsFMov(
const MachineInstr &
MI,
Register DestReg);
389 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
391 MInstToMCSymbol LOHInstToLabel;
393 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
394 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
397 const MCSubtargetInfo *getIFuncMCSubtargetInfo()
const override {
401 void emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
402 MCSymbol *LazyPointer)
override;
403 void emitMachOIFuncStubHelperBody(
Module &M,
const GlobalIFunc &GI,
404 MCSymbol *LazyPointer)
override;
409 void recordIfImportCall(
const MachineInstr *BranchInst);
416 Metadata *Flag = M.getModuleFlag(Name);
421 assert((
Value == 0 ||
Value == 1) &&
"Boolean flag is expected, if present");
425void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
426 const Triple &
TT = TM.getTargetTriple();
428 if (
TT.isOSBinFormatCOFF()) {
429 emitCOFFFeatureSymbol(M);
430 emitCOFFReplaceableFunctionData(M);
432 if (
M.getModuleFlag(
"import-call-optimization"))
433 EnableImportCallOptimization =
true;
438 M,
"ptrauth-init-fini-address-discrimination");
440 if (!
TT.isOSBinFormatELF())
445 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
448 unsigned BAFlags = 0;
449 unsigned GNUFlags = 0;
451 M.getModuleFlag(
"branch-target-enforcement"))) {
452 if (!BTE->isZero()) {
453 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
459 M.getModuleFlag(
"guarded-control-stack"))) {
460 if (!GCS->isZero()) {
461 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
467 M.getModuleFlag(
"sign-return-address"))) {
468 if (!Sign->isZero()) {
469 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
476 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
477 PAuthABIPlatform = PAP->getZExtValue();
482 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
483 PAuthABIVersion = PAV->getZExtValue();
491 PAuthABIVersion == 0) {
497 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
499 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
502void AArch64AsmPrinter::emitFunctionHeaderComment() {
503 const AArch64FunctionInfo *FI = MF->
getInfo<AArch64FunctionInfo>();
505 if (OutlinerString != std::nullopt)
506 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
509void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
512 if (
F.hasFnAttribute(
"patchable-function-entry")) {
514 if (
F.getFnAttribute(
"patchable-function-entry")
516 .getAsInteger(10, Num))
522 emitSled(
MI, SledKind::FUNCTION_ENTER);
525void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
526 emitSled(
MI, SledKind::FUNCTION_EXIT);
529void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
530 emitSled(
MI, SledKind::TAIL_CALL);
533void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
534 static const int8_t NoopsInSledCount = 7;
555 OutStreamer->emitCodeAlignment(
Align(4), getSubtargetInfo());
556 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
557 OutStreamer->emitLabel(CurSled);
558 auto Target = OutContext.createTempSymbol();
563 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
565 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
566 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
568 OutStreamer->emitLabel(Target);
569 recordSled(CurSled,
MI, Kind, 2);
572void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
575 AArch64TargetStreamer *TS) {
577 PAuthABIPlatform = (
uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
578 PAuthABIVersion = (
uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
580 if (PAuthABIPlatform || PAuthABIVersion) {
584 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
585 AArch64BuildAttributes::SubsectionType::ULEB128);
589 PAuthABIPlatform,
"");
603 if (BTIValue || PACValue || GCSValue) {
607 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
608 AArch64BuildAttributes::SubsectionType::ULEB128);
636void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
638 auto &
O = *OutStreamer;
639 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
640 O.emitLabel(CurSled);
641 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
643 OutContext.getOrCreateSymbol(
644 Twine(MachO ?
"_" :
"") +
645 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
648 O.AddComment(
"Begin XRay typed event");
649 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
650 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
656 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
660 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
661 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
662 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
663 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
664 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
668 O.AddComment(
"End XRay typed event");
669 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
676 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
678 O.AddComment(
"Begin XRay custom event");
679 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
680 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
686 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
687 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
688 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
689 O.AddComment(
"End XRay custom event");
690 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
697 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
701void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
703 assert(std::next(
MI.getIterator())->isCall() &&
704 "KCFI_CHECK not followed by a call instruction");
705 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
706 "KCFI_CHECK call target doesn't match call operand");
710 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
711 if (AddrReg == AArch64::XZR) {
715 emitMovXReg(AddrReg, AArch64::XZR);
721 for (
auto &
Reg : ScratchRegs) {
727 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
728 "Invalid scratch registers for KCFI_CHECK");
733 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
734 "patchable-function-prefix");
737 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
738 .addReg(ScratchRegs[0])
740 .addImm(-(PrefixNops * 4 + 4)));
744 const int64_t
Type =
MI.getOperand(1).getImm();
745 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
746 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
749 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
750 .addReg(AArch64::WZR)
751 .addReg(ScratchRegs[0])
752 .addReg(ScratchRegs[1])
756 EmitToStreamer(*OutStreamer,
757 MCInstBuilder(AArch64::Bcc)
766 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
770 AddrIndex = AddrReg - AArch64::X0;
780 assert(AddrIndex < 31 && TypeIndex < 31);
782 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
783 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
784 OutStreamer->emitLabel(
Pass);
787void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
795 if (
Reg == AArch64::XZR)
799 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
801 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
802 uint32_t AccessInfo =
MI.getOperand(1).getImm();
804 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
806 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
807 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
809 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
810 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
813 if (!TM.getTargetTriple().isOSBinFormatELF())
816 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
819 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
821 SymName +=
"_short_v2";
822 Sym = OutContext.getOrCreateSymbol(SymName);
825 EmitToStreamer(*OutStreamer,
826 MCInstBuilder(AArch64::BL)
830void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
831 if (HwasanMemaccessSymbols.empty())
834 const Triple &
TT = TM.getTargetTriple();
838 auto STI = std::make_unique<AArch64Subtarget>(
839 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
841 this->STI = STI.get();
844 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
846 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
848 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
850 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
853 for (
auto &
P : HwasanMemaccessSymbols) {
854 unsigned Reg = std::get<0>(
P.first);
855 bool IsShort = std::get<1>(
P.first);
856 uint32_t AccessInfo = std::get<2>(
P.first);
857 bool IsFixedShadow = std::get<3>(
P.first);
858 uint64_t FixedShadowOffset = std::get<4>(
P.first);
859 const MCSymbolRefExpr *HwasanTagMismatchRef =
860 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
863 bool HasMatchAllTag =
865 uint8_t MatchAllTag =
872 OutStreamer->switchSection(OutContext.getELFSection(
878 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
879 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
880 OutStreamer->emitLabel(Sym);
882 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
883 .addReg(AArch64::X16)
893 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
894 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
895 .addReg(AArch64::W16)
896 .addReg(AArch64::X17)
897 .addReg(AArch64::X16)
901 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
902 .addReg(AArch64::W16)
903 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
904 .addReg(AArch64::X16)
909 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
910 .addReg(AArch64::XZR)
911 .addReg(AArch64::X16)
914 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
915 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
918 HandleMismatchOrPartialSym, OutContext)));
919 MCSymbol *ReturnSym = OutContext.createTempSymbol();
920 OutStreamer->emitLabel(ReturnSym);
921 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
922 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
924 if (HasMatchAllTag) {
925 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
926 .addReg(AArch64::X17)
930 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
931 .addReg(AArch64::XZR)
932 .addReg(AArch64::X17)
936 MCInstBuilder(AArch64::Bcc)
942 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
943 .addReg(AArch64::WZR)
944 .addReg(AArch64::W16)
947 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
949 MCInstBuilder(AArch64::Bcc)
953 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
954 .addReg(AArch64::X17)
958 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
959 .addReg(AArch64::X17)
960 .addReg(AArch64::X17)
963 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
964 .addReg(AArch64::WZR)
965 .addReg(AArch64::W16)
966 .addReg(AArch64::W17)
969 MCInstBuilder(AArch64::Bcc)
973 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
974 .addReg(AArch64::X16)
977 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
978 .addReg(AArch64::W16)
979 .addReg(AArch64::X16)
982 MCInstBuilder(AArch64::SUBSXrs)
983 .addReg(AArch64::XZR)
984 .addReg(AArch64::X16)
988 MCInstBuilder(AArch64::Bcc)
992 OutStreamer->emitLabel(HandleMismatchSym);
995 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
1001 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
1002 .addReg(AArch64::FP)
1003 .addReg(AArch64::LR)
1004 .addReg(AArch64::SP)
1007 if (
Reg != AArch64::X0)
1008 emitMovXReg(AArch64::X0,
Reg);
1011 if (CompileKernel) {
1015 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
1020 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
1021 .addReg(AArch64::X16)
1025 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
1026 .addReg(AArch64::X16)
1027 .addReg(AArch64::X16)
1031 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1034 this->STI =
nullptr;
1039 const MCExpr *StubAuthPtrRef) {
1042 OutStreamer.
emitValue(StubAuthPtrRef, 8);
1045void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
1046 emitHwasanMemaccessSymbols(M);
1048 const Triple &
TT = TM.getTargetTriple();
1049 if (
TT.isOSBinFormatMachO()) {
1051 MachineModuleInfoMachO &MMIMacho =
1052 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1056 if (!Stubs.empty()) {
1058 OutStreamer->switchSection(
1061 emitAlignment(
Align(8));
1063 for (
const auto &Stub : Stubs)
1066 OutStreamer->addBlankLine();
1074 OutStreamer->emitSubsectionsViaSymbols();
1077 if (
TT.isOSBinFormatELF()) {
1079 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1083 if (!Stubs.empty()) {
1084 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1086 emitAlignment(
Align(8));
1088 for (
const auto &Stub : Stubs)
1091 OutStreamer->addBlankLine();
1102 M.getModuleFlag(
"ptrauth-elf-got"));
1103 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1104 for (
const GlobalValue &GV :
M.global_values())
1106 !GV.getName().starts_with(
"llvm."))
1107 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1116 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1117 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1120 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1121 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1132 for (
auto &[Section, CallsToImportedFuncs] :
1133 SectionToImportedFunctionCalls) {
1135 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1136 OutStreamer->emitInt32(SectionSize);
1137 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1138 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1140 OutStreamer->emitInt32(0x13);
1141 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1142 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1148void AArch64AsmPrinter::emitLOHs() {
1152 for (
const MachineInstr *
MI :
D.getArgs()) {
1153 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1154 assert(LabelIt != LOHInstToLabel.end() &&
1155 "Label hasn't been inserted for LOH related instruction");
1158 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1163void AArch64AsmPrinter::emitFunctionBodyEnd() {
1169MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1173 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1174 return OutContext.getOrCreateSymbol(
1175 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1176 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1181void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1183 const MachineOperand &MO =
MI->getOperand(OpNum);
1199 PrintSymbolOperand(MO, O);
1210bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1234bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1236 unsigned AltName, raw_ostream &O) {
1237 assert(MO.
isReg() &&
"Should only get here with a register!");
1238 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1247bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1248 const char *ExtraCode, raw_ostream &O) {
1249 const MachineOperand &MO =
MI->getOperand(OpNum);
1256 if (ExtraCode && ExtraCode[0]) {
1257 if (ExtraCode[1] != 0)
1260 switch (ExtraCode[0]) {
1268 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1282 switch (ExtraCode[0]) {
1284 RC = &AArch64::FPR8RegClass;
1287 RC = &AArch64::FPR16RegClass;
1290 RC = &AArch64::FPR32RegClass;
1293 RC = &AArch64::FPR64RegClass;
1296 RC = &AArch64::FPR128RegClass;
1299 RC = &AArch64::ZPRRegClass;
1304 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1325 unsigned AltName = AArch64::NoRegAltName;
1328 RegClass = &AArch64::ZPRRegClass;
1330 RegClass = &AArch64::PPRRegClass;
1332 RegClass = &AArch64::PNRRegClass;
1334 RegClass = &AArch64::FPR128RegClass;
1335 AltName = AArch64::vreg;
1339 return printAsmRegInClass(MO, RegClass, AltName, O);
1346bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1348 const char *ExtraCode,
1350 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1353 const MachineOperand &MO =
MI->getOperand(OpNum);
1354 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1359void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1361 unsigned NOps =
MI->getNumOperands();
1363 OS <<
'\t' << MAI.getCommentString() <<
"DEBUG_VALUE: ";
1365 OS <<
MI->getDebugVariable()->getName();
1368 assert(
MI->isIndirectDebugValue());
1380void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1381 ArrayRef<unsigned> JumpTableIndices) {
1383 if (JumpTableIndices.
empty())
1385 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1389 MCSection *ReadOnlySec =
nullptr;
1390 if (TM.Options.EnableStaticDataPartitioning) {
1396 OutStreamer->switchSection(ReadOnlySec);
1398 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1399 for (
unsigned JTI : JumpTableIndices) {
1400 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1403 if (JTBBs.empty())
continue;
1405 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1407 OutStreamer->emitLabel(GetJTISymbol(JTI));
1412 for (
auto *JTBB : JTBBs) {
1413 const MCExpr *
Value =
1432AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1433 const MachineInstr *BranchInstr,
1434 const MCSymbol *BranchLabel)
const {
1435 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1438 switch (AFI->getJumpTableEntrySize(JTI)) {
1440 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1443 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1446 EntrySize = codeview::JumpTableEntrySize::Int32;
1451 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1454void AArch64AsmPrinter::emitFunctionEntryLabel() {
1455 const Triple &
TT = TM.getTargetTriple();
1456 if (
TT.isOSBinFormatELF() &&
1459 CallingConv::AArch64_SVE_VectorCall ||
1460 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1462 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1473 OutStreamer->emitAssignment(
1477 auto getSymbolFromMetadata = [&](StringRef
Name) {
1481 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1488 for (MDNode *Node : UnmangledNames) {
1490 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1491 if (std::optional<std::string> MangledName =
1494 MMI->getContext().getOrCreateSymbol(*MangledName);
1495 emitFunctionAlias(UnmangledSym, ECMangledSym);
1498 if (MCSymbol *ECMangledSym =
1499 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1500 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1504void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1505 const Constant *CV) {
1508 "ctors/dtors are to be signed by asm printer");
1510 if (PtrauthInitFini) {
1516 ConstantInt *IntDisc = ConstantInt::get(
1520 if (PtrauthInitFiniAddressDisc) {
1534void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1535 const GlobalAlias &GA) {
1541 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1543 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1546 OutStreamer->beginCOFFSymbolDef(ExpSym);
1550 OutStreamer->endCOFFSymbolDef();
1552 OutStreamer->beginCOFFSymbolDef(Sym);
1556 OutStreamer->endCOFFSymbolDef();
1557 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1558 OutStreamer->emitAssignment(
1575void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1576 const llvm::MachineInstr &
MI) {
1577 Register DestReg =
MI.getOperand(0).getReg();
1578 Register ScratchReg =
MI.getOperand(1).getReg();
1580 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1581 Register TableReg =
MI.getOperand(2).getReg();
1582 Register EntryReg =
MI.getOperand(3).getReg();
1583 int JTIdx =
MI.getOperand(4).getIndex();
1589 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1600 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1602 .addExpr(LabelExpr));
1607 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1608 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1609 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1614 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1615 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1619 .addImm(
Size == 1 ? 0 : 1));
1623 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1627 .addImm(
Size == 4 ? 0 : 2));
1630void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1632 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1634 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1635 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1651 MachineOperand JTOp =
MI.getOperand(0);
1655 "unsupported compressed jump table");
1657 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1661 uint64_t MaxTableEntry = NumTableEntries - 1;
1663 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1664 .addReg(AArch64::XZR)
1665 .addReg(AArch64::X16)
1666 .addImm(MaxTableEntry)
1669 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1674 if ((MaxTableEntry >>
Offset) == 0)
1676 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1679 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1680 .addReg(AArch64::XZR)
1681 .addReg(AArch64::X16)
1682 .addReg(AArch64::X17)
1688 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1689 .addReg(AArch64::X16)
1690 .addReg(AArch64::X16)
1691 .addReg(AArch64::XZR)
1695 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1696 MCOperand JTMCHi, JTMCLo;
1706 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1708 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1709 .addReg(AArch64::X17)
1710 .addReg(AArch64::X17)
1714 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1715 .addReg(AArch64::X16)
1716 .addReg(AArch64::X17)
1717 .addReg(AArch64::X16)
1728 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1730 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1731 .addReg(AArch64::X16)
1732 .addReg(AArch64::X17)
1733 .addReg(AArch64::X16)
1736 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1739void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1740 const llvm::MachineInstr &
MI) {
1741 unsigned Opcode =
MI.getOpcode();
1743 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1745 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1746 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1747 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1748 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1749 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1750 if (Opcode == AArch64::MOPSMemorySetPseudo)
1751 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1752 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1753 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1756 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1757 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1759 for (
auto Op :
Ops) {
1761 auto MCIB = MCInstBuilder(
Op);
1763 MCIB.addReg(
MI.getOperand(i++).getReg());
1764 MCIB.addReg(
MI.getOperand(i++).getReg());
1766 MCIB.addReg(
MI.getOperand(i++).getReg());
1768 MCIB.addReg(
MI.getOperand(i++).getReg());
1769 MCIB.addReg(
MI.getOperand(i++).getReg());
1770 MCIB.addReg(
MI.getOperand(i++).getReg());
1772 EmitToStreamer(OutStreamer, MCIB);
1776void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1777 const MachineInstr &
MI) {
1778 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1781 MCSymbol *MILabel = Ctx.createTempSymbol();
1785 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1791 while (NumNOPBytes > 0) {
1792 if (MII ==
MBB.
end() || MII->isCall() ||
1793 MII->getOpcode() == AArch64::DBG_VALUE ||
1794 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1795 MII->getOpcode() == TargetOpcode::STACKMAP)
1802 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1803 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1808void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1809 const MachineInstr &
MI) {
1811 MCSymbol *MILabel = Ctx.createTempSymbol();
1815 PatchPointOpers Opers(&
MI);
1817 int64_t CallTarget = Opers.getCallTarget().getImm();
1818 unsigned EncodedBytes = 0;
1820 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1821 "High 16 bits of call target should be zero.");
1822 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1825 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1826 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1827 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1828 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1831 unsigned NumBytes = Opers.getNumPatchBytes();
1832 assert(NumBytes >= EncodedBytes &&
1833 "Patchpoint can't request size less than the length of a call.");
1834 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1835 "Invalid number of NOP bytes requested!");
1836 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1837 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1840void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1841 const MachineInstr &
MI) {
1842 StatepointOpers SOpers(&
MI);
1843 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1844 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1845 for (
unsigned i = 0; i < PatchBytes; i += 4)
1846 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1849 const MachineOperand &CallTarget = SOpers.getCallTarget();
1850 MCOperand CallTargetMCOp;
1851 unsigned CallOpcode;
1852 switch (CallTarget.
getType()) {
1855 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1856 CallOpcode = AArch64::BL;
1860 CallOpcode = AArch64::BL;
1864 CallOpcode = AArch64::BLR;
1871 EmitToStreamer(OutStreamer,
1872 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1876 MCSymbol *MILabel = Ctx.createTempSymbol();
1881void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1890 unsigned OperandsBeginIdx = 4;
1893 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1900 MI.setOpcode(Opcode);
1905 for (
const MachineOperand &MO :
1908 lowerOperand(MO, Dest);
1909 MI.addOperand(Dest);
1917 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1919 .addReg(AArch64::XZR)
1925 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1926 EmitToStreamer(*OutStreamer,
1927 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1934 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1935 EmitToStreamer(*OutStreamer,
1936 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1945 bool IsZeroDisc = Disc == AArch64::XZR;
1957 EmitToStreamer(AUTInst);
1962 bool IsZeroDisc = Disc == AArch64::XZR;
1974 EmitToStreamer(PACInst);
1979 bool IsZeroDisc = Disc == AArch64::XZR;
1989 EmitToStreamer(Inst);
1992void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1993 Register DestReg =
MI.getOperand(0).getReg();
1994 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1995 if (STI->hasZeroCycleZeroingFPR64()) {
1997 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1998 if (AArch64::FPR16RegClass.
contains(DestReg))
1999 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2000 &AArch64::FPR64RegClass);
2001 else if (AArch64::FPR32RegClass.
contains(DestReg))
2002 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2003 &AArch64::FPR64RegClass);
2011 EmitToStreamer(*OutStreamer, MOVI);
2012 ++NumZCZeroingInstrsFPR;
2013 }
else if (STI->hasZeroCycleZeroingFPR128()) {
2015 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2016 if (AArch64::FPR16RegClass.
contains(DestReg)) {
2017 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2018 &AArch64::FPR128RegClass);
2019 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
2020 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2021 &AArch64::FPR128RegClass);
2024 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
2025 &AArch64::FPR128RegClass);
2032 EmitToStreamer(*OutStreamer, MOVI);
2033 ++NumZCZeroingInstrsFPR;
2035 emitFMov0AsFMov(
MI, DestReg);
2038 emitFMov0AsFMov(
MI, DestReg);
2042void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
2045 switch (
MI.getOpcode()) {
2048 case AArch64::FMOVH0:
2049 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
2050 if (!STI->hasFullFP16())
2051 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
2055 case AArch64::FMOVS0:
2060 case AArch64::FMOVD0:
2066 EmitToStreamer(*OutStreamer, FMov);
2072 bool MayClobberAddrDisc) {
2073 assert(isPtrauthRegSafe(ScratchReg) &&
2074 "Safe scratch register must be provided by the caller");
2079 AddrDisc = AArch64::XZR;
2087 if (AddrDisc == AArch64::XZR) {
2088 emitMOVZ(ScratchReg, Disc, 0);
2095 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2096 ScratchReg = AddrDisc;
2098 emitMovXReg(ScratchReg, AddrDisc);
2099 assert(ScratchReg != AddrDisc &&
2100 "Forbidden to clobber AddrDisc, but have to");
2103 emitMOVK(ScratchReg, Disc, 48);
2117void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2149 if (Method == AuthCheckMethod::None)
2151 if (Method == AuthCheckMethod::DummyLoad) {
2152 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2156 assert(!OnFailure &&
"DummyLoad always traps on error");
2160 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2161 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2163 emitMovXReg(ScratchReg, TestedReg);
2165 if (Method == AuthCheckMethod::XPAC) {
2169 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2174 assert(TestedReg == AArch64::LR &&
2175 "XPACHint mode is only compatible with checking the LR register");
2177 "XPACHint mode is only compatible with I-keys");
2178 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2182 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2183 .addReg(AArch64::XZR)
2190 MCInstBuilder(AArch64::Bcc)
2193 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2195 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2202 MCInstBuilder(AArch64::TBZX)
2213 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2227 case AuthCheckMethod::XPACHint:
2230 case AuthCheckMethod::XPAC:
2232 emitMovXReg(TestedReg, ScratchReg);
2239 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2244 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2256void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2260 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2261 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2264 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2268 "Neither x16 nor x17 is available as a scratch register");
2271 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2275bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2281 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2284 MCSymbol *Dot = OutContext.createTempSymbol();
2289 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2295AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateImmReg(
2297 PtrAuthSchema Schema;
2299 Schema.IntDisc = IntDisc;
2300 Schema.AddrDisc = AddrDiscOp.
getReg();
2301 Schema.AddrDiscIsKilled = AddrDiscOp.
isKill();
2306AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateRegReg(
2308 assert(PCDisc.
isValid() &&
"Use CreateImmReg for non-PC schemas");
2309 PtrAuthSchema Schema;
2312 Schema.AddrDisc = AddrDisc;
2313 Schema.AddrDiscIsKilled =
false;
2314 Schema.PCDisc = PCDisc;
2318void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2323 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2333 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2335 MCInstBuilder(AArch64::ADDXri)
2338 .addImm((Addend >> BitPos) & 0xfff)
2344 emitMOVZ(Scratch, Addend & 0xffff, 0);
2351 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2358 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2364 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2415void AArch64AsmPrinter::emitPtrauthAuthResign(
2417 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2420 const bool IsAuthWithPC = AuthSchema.PCDisc.isValid();
2421 assert(!SignSchema || !SignSchema->PCDisc.isValid());
2423 Register SignAddrDiscOrNone = SignSchema ? SignSchema->AddrDisc :
Register();
2429 assert(Pointer == AArch64::X17 && Scratch == AArch64::X16 &&
2430 "AUTPCPAC must use x17/x16 as Pointer/Scratch");
2432 assert(AuthSchema.AddrDisc == AArch64::X16 &&
2433 "AUTPCPAC requires address discriminator in X16");
2435 assert(AuthSchema.PCDisc == AArch64::X15 &&
2436 "AUTPCPAC requires PC discriminator in X15");
2438 assert(AuthSchema.IntDisc == 0 &&
"AUTPCPAC does not support IntDisc");
2442 "AUTPCPAC only supports AUT-ing with IA/IB");
2444 if (!emitDeactivationSymbolRelocation(DS)) {
2446 ? AArch64::AUTIB171615
2447 : AArch64::AUTIA171615;
2448 EmitToStreamer(MCInstBuilder(AutOpc));
2458 Register AUTDiscReg = emitPtrauthDiscriminator(
2459 AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2460 AuthSchema.addrDiscIsKilledAndNoneOf({Pointer, SignAddrDiscOrNone}));
2461 if (!emitDeactivationSymbolRelocation(DS))
2462 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2467 auto EmitCheck = [&](
MCSymbol *OnFailure =
nullptr) {
2468 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2469 AArch64PAuth::AuthCheckMethod::XPAC,
2473 auto EmitResignOnSuccess = [&]() {
2474 if (Addend.has_value())
2475 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2477 assert(Pointer != SignSchema->AddrDisc &&
"Pointer is early-clobbered");
2479 emitPtrauthDiscriminator(SignSchema->IntDisc, SignSchema->AddrDisc,
2480 Scratch, SignSchema->AddrDiscIsKilled);
2481 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2493 switch (CheckMode) {
2495 EmitResignOnSuccess();
2499 EmitResignOnSuccess();
2502 MCSymbol *OnFailure = createTempSymbol(
"resign_end_");
2503 EmitCheck(OnFailure);
2504 EmitResignOnSuccess();
2510void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2514 Register AddrDisc =
MI->getOperand(4).getReg();
2515 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2519 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2520 assert(ScratchReg != AddrDisc &&
2521 "Neither X16 nor X17 is available as a scratch register");
2524 Register DiscReg = emitPtrauthDiscriminator(
2525 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2527 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2530 emitPAC(
Key, Val, DiscReg);
2533void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2534 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2535 unsigned BrTarget =
MI->getOperand(0).getReg();
2540 unsigned AddrDisc =
MI->getOperand(3).getReg();
2546 if (BrTarget == AddrDisc)
2563 bool AddrDiscIsImplicitDef =
2564 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2565 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2566 AddrDiscIsImplicitDef);
2567 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2570void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2574 const bool IsNeg = Addend < 0;
2576 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2579 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2582 .addImm((AbsOffset >> BitPos) & 0xfff)
2587 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2589 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2591 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2592 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2593 uint64_t Shifted = UAddend >> BitPos;
2595 return Shifted != 0;
2596 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2597 if (((Shifted >>
I) & 0xffff) != 0xffff)
2601 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2602 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2604 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2613void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2614 MCRegister Tmp,
bool DSOLocal,
2615 const MCSubtargetInfo &STI) {
2621 MCInstBuilder(AArch64::ADRP)
2625 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2635 MCInstBuilder(AArch64::ADRP)
2640 MCInstBuilder(AArch64::LDRXui)
2651 if (!TT.isOSBinFormatELF())
2655 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2656 TT.isOSDragonFly() || TT.isOSNetBSD();
2710const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2712 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2713 const Triple &
TT = TM.getTargetTriple();
2725 auto STI = std::make_unique<AArch64Subtarget>(
2726 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2728 this->STI = STI.get();
2734 const MCSymbolELF *Group =
2749 .addReg(AArch64::X0)
2754 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2756 if (HasAddressDiversity) {
2761 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2765 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2767 "' out of range [0, 0xFFFF]");
2769 emitMOVZ(AArch64::X1, Disc, 0);
2776 auto *PrePACInstExpr =
2788 const MCSymbolRefExpr *EmuPACRef =
2790 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2797 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2806AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2807 MCContext &Ctx = OutContext;
2812 getDataLayout(),
Offset,
true);
2832 const MCExpr *DSExpr =
nullptr;
2844 "' out of range [0, " +
2852 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2854 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2859 "' out of range [0, 0xFFFF]");
2865 "expressions on this target");
2872void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2873 unsigned DstReg =
MI.getOperand(0).getReg();
2874 const MachineOperand &GAOp =
MI.getOperand(1);
2875 const uint64_t KeyC =
MI.getOperand(2).getImm();
2877 "key is out of range [0, AArch64PACKey::LAST]");
2879 const uint64_t Disc =
MI.getOperand(3).getImm();
2881 "constant discriminator is out of range [0, 0xffff]");
2890 if (TM.getTargetTriple().isOSBinFormatELF()) {
2892 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2895 "non-zero offset for $auth_ptr$ stub slots is not supported");
2897 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2899 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2900 "LOADauthptrstatic is implemented only for MachO/ELF");
2902 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2903 getObjFileLowering());
2906 "non-zero offset for $auth_ptr$ stub slots is not supported");
2908 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2911 MachineOperand StubMOHi =
2915 MCOperand StubMCHi, StubMCLo;
2922 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2924 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2930void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2931 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2932 const bool IsELFSignedGOT =
MI.getParent()
2934 ->getInfo<AArch64FunctionInfo>()
2935 ->hasELFSignedGOT();
2936 MachineOperand GAOp =
MI.getOperand(0);
2937 const uint64_t KeyC =
MI.getOperand(1).getImm();
2939 "key is out of range [0, AArch64PACKey::LAST]");
2941 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2942 const uint64_t Disc =
MI.getOperand(3).getImm();
2989 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2990 MCOperand GAMCHi, GAMCLo;
3003 MCInstBuilder(AArch64::ADRP)
3004 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
3008 if (IsELFSignedGOT) {
3009 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3010 .addReg(AArch64::X17)
3011 .addReg(AArch64::X17)
3015 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3016 .addReg(AArch64::X16)
3017 .addReg(AArch64::X17)
3025 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
3027 if (!STI->hasFPAC())
3028 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
3029 AArch64PAuth::AuthCheckMethod::XPAC);
3031 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3032 .addReg(AArch64::X16)
3033 .addReg(AArch64::X16)
3037 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3038 .addReg(AArch64::X16)
3039 .addReg(AArch64::X16)
3044 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
3045 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
3047 emitPAC(
Key, AArch64::X16, DiscReg);
3050void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
3052 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
3053 const MachineOperand &GAMO =
MI.getOperand(1);
3060 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
3061 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3062 .addReg(AuthResultReg)
3063 .addReg(AArch64::X17)
3066 MachineOperand GAHiOp(GAMO);
3067 MachineOperand GALoOp(GAMO);
3071 MCOperand GAMCHi, GAMCLo;
3076 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
3078 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3079 .addReg(AArch64::X17)
3080 .addReg(AArch64::X17)
3084 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3085 .addReg(AuthResultReg)
3086 .addReg(AArch64::X17)
3093 UndefWeakSym = createTempSymbol(
"undef_weak");
3095 MCInstBuilder(AArch64::CBZX)
3096 .addReg(AuthResultReg)
3104 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
3109 if (!STI->hasFPAC()) {
3110 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
3111 AArch64PAuth::AuthCheckMethod::XPAC);
3113 emitMovXReg(DstReg, AuthResultReg);
3118AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
3122 if (std::optional<uint16_t> BADisc =
3123 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3130void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3134 switch (
MI->getOpcode()) {
3137 case AArch64::CBBAssertExt:
3141 case AArch64::CBHAssertExt:
3145 case AArch64::CBWPrr:
3148 case AArch64::CBXPrr:
3151 case AArch64::CBWPri:
3155 case AArch64::CBXPri:
3163 bool NeedsRegSwap =
false;
3164 bool NeedsImmDec =
false;
3165 bool NeedsImmInc =
false;
3167#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3169 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3171 ? AArch64::CBB##RegCond##Wrr \
3172 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3173 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3174 : AArch64::CB##RegCond##Xrr))))
3190 NeedsImmDec = IsImm;
3194 NeedsRegSwap = !IsImm;
3201 NeedsRegSwap = !IsImm;
3202 NeedsImmInc = IsImm;
3206 NeedsImmDec = IsImm;
3210 NeedsRegSwap = !IsImm;
3217 NeedsRegSwap = !IsImm;
3218 NeedsImmInc = IsImm;
3226 MCOperand Lhs, Rhs, Trgt;
3227 lowerOperand(
MI->getOperand(1), Lhs);
3228 lowerOperand(
MI->getOperand(2), Rhs);
3229 lowerOperand(
MI->getOperand(3), Trgt);
3233 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3234 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3237 }
else if (NeedsImmDec) {
3241 }
else if (NeedsImmInc) {
3251 "CB immediate operand out-of-bounds");
3254 EmitToStreamer(*OutStreamer, Inst);
3257void AArch64AsmPrinter::emitAtomicHintPseudoExpansion(
const MachineInstr *
MI) {
3260 unsigned Relaxed =
MI->getOperand(2).getImm();
3261 assert(
Relaxed < 2 &&
"Atomic hint relaxed immediate out-of-bounds");
3262 switch (
MI->getOpcode()) {
3263 case AArch64::ATOMIC_STORE_HINT_B:
3264 StOpc =
Relaxed ? AArch64::STRBBui : AArch64::STLRB;
3266 case AArch64::ATOMIC_STORE_HINT_H:
3267 StOpc =
Relaxed ? AArch64::STRHHui : AArch64::STLRH;
3269 case AArch64::ATOMIC_STORE_HINT_W:
3270 StOpc =
Relaxed ? AArch64::STRWui : AArch64::STLRW;
3272 case AArch64::ATOMIC_STORE_HINT_X:
3273 StOpc =
Relaxed ? AArch64::STRXui : AArch64::STLRX;
3280 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(3).getImm()));
3283 Store.setOpcode(StOpc);
3286 Store.setFlags(
MI->getFlags());
3289 EmitToStreamer(*OutStreamer,
Store);
3292void AArch64AsmPrinter::emitAtomicHintPseudoExpansionRO(
3293 const MachineInstr *
MI) {
3295 assert(
MI->getOperand(5).getImm() == 1 &&
3296 "Atomic store addressing mode only supports relaxed stores");
3298 switch (
MI->getOpcode()) {
3299 case AArch64::ATOMIC_STORE_HINT_BroW:
3300 StOpc = AArch64::STRBBroW;
3302 case AArch64::ATOMIC_STORE_HINT_HroW:
3303 StOpc = AArch64::STRHHroW;
3305 case AArch64::ATOMIC_STORE_HINT_WroW:
3306 StOpc = AArch64::STRWroW;
3308 case AArch64::ATOMIC_STORE_HINT_XroW:
3309 StOpc = AArch64::STRXroW;
3311 case AArch64::ATOMIC_STORE_HINT_SroW:
3312 StOpc = AArch64::STRSroW;
3314 case AArch64::ATOMIC_STORE_HINT_DroW:
3315 StOpc = AArch64::STRDroW;
3317 case AArch64::ATOMIC_STORE_HINT_BroX:
3318 StOpc = AArch64::STRBBroX;
3320 case AArch64::ATOMIC_STORE_HINT_HroX:
3321 StOpc = AArch64::STRHHroX;
3323 case AArch64::ATOMIC_STORE_HINT_WroX:
3324 StOpc = AArch64::STRWroX;
3326 case AArch64::ATOMIC_STORE_HINT_XroX:
3327 StOpc = AArch64::STRXroX;
3329 case AArch64::ATOMIC_STORE_HINT_SroX:
3330 StOpc = AArch64::STRSroX;
3332 case AArch64::ATOMIC_STORE_HINT_DroX:
3333 StOpc = AArch64::STRDroX;
3340 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(6).getImm()));
3343 Store.setOpcode(StOpc);
3349 Store.setFlags(
MI->getFlags());
3350 EmitToStreamer(*OutStreamer,
Store);
3353void AArch64AsmPrinter::emitAtomicHintPseudoExpansionImm(
3354 const MachineInstr *
MI) {
3356 assert(
MI->getOperand(3).getImm() == 1 &&
3357 "Atomic store addressing mode only supports relaxed stores");
3359 switch (
MI->getOpcode()) {
3360 case AArch64::ATOMIC_STORE_HINT_Bui:
3361 StOpc = AArch64::STRBBui;
3363 case AArch64::ATOMIC_STORE_HINT_Hui:
3364 StOpc = AArch64::STRHHui;
3366 case AArch64::ATOMIC_STORE_HINT_Wui:
3367 StOpc = AArch64::STRWui;
3369 case AArch64::ATOMIC_STORE_HINT_Xui:
3370 StOpc = AArch64::STRXui;
3372 case AArch64::ATOMIC_STORE_HINT_Sui:
3373 StOpc = AArch64::STRSui;
3375 case AArch64::ATOMIC_STORE_HINT_Dui:
3376 StOpc = AArch64::STRDui;
3378 case AArch64::ATOMIC_STORE_HINT_Bi:
3379 StOpc = AArch64::STURBBi;
3381 case AArch64::ATOMIC_STORE_HINT_Hi:
3382 StOpc = AArch64::STURHHi;
3384 case AArch64::ATOMIC_STORE_HINT_Wi:
3385 StOpc = AArch64::STURWi;
3387 case AArch64::ATOMIC_STORE_HINT_Xi:
3388 StOpc = AArch64::STURXi;
3390 case AArch64::ATOMIC_STORE_HINT_Si:
3391 StOpc = AArch64::STURSi;
3393 case AArch64::ATOMIC_STORE_HINT_Di:
3394 StOpc = AArch64::STURDi;
3401 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(4).getImm()));
3404 Store.setOpcode(StOpc);
3408 Store.setFlags(
MI->getFlags());
3409 EmitToStreamer(*OutStreamer,
Store);
3414#include "AArch64GenMCPseudoLowering.inc"
3416void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3423void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3424 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3429 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3434 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3435 EmitToStreamer(*OutStreamer, OutInst);
3439 if (
MI->getOpcode() == AArch64::ADRP) {
3440 for (
auto &Opd :
MI->operands()) {
3441 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3442 "swift_async_extendedFramePointerFlags") {
3443 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3450 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3452 LOHInstToLabel[
MI] = LOHLabel;
3456 AArch64TargetStreamer *TS =
3459 switch (
MI->getOpcode()) {
3462 "Unhandled tail call instruction");
3464 case AArch64::READ_REGISTER_GPR64:
3468 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
3469 .addReg(
MI->getOperand(0).getReg())
3470 .addReg(AArch64::XZR)
3471 .addReg(
MI->getOperand(1).getImm())
3474 case AArch64::READ_REGISTER_FPR64:
3476 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::FMOVDr)
3477 .addReg(
MI->getOperand(0).getReg())
3478 .addReg(
MI->getOperand(1).getImm()));
3480 case AArch64::HINT: {
3485 if (CurrentPatchableFunctionEntrySym &&
3486 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3488 int64_t
Imm =
MI->getOperand(0).getImm();
3489 if (
Imm == 32 ||
Imm == 34 ||
Imm == 36 ||
Imm == 38) {
3491 MCInstLowering.
Lower(
MI, Inst);
3492 EmitToStreamer(*OutStreamer, Inst);
3493 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3494 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3500 case AArch64::MOVMCSym: {
3501 Register DestReg =
MI->getOperand(0).getReg();
3502 const MachineOperand &MO_Sym =
MI->getOperand(1);
3503 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3504 MCOperand Hi_MCSym, Lo_MCSym;
3517 EmitToStreamer(*OutStreamer, MovZ);
3525 EmitToStreamer(*OutStreamer, MovK);
3528 case AArch64::MOVIv2d_ns:
3536 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3537 MI->getOperand(1).getImm() == 0) {
3539 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3542 EmitToStreamer(*OutStreamer, TmpInst);
3547 case AArch64::DBG_VALUE:
3548 case AArch64::DBG_VALUE_LIST:
3550 SmallString<128> TmpStr;
3551 raw_svector_ostream OS(TmpStr);
3552 PrintDebugValueComment(
MI, OS);
3557 case AArch64::EMITBKEY: {
3559 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3560 ExceptionHandlingType != ExceptionHandling::ARM)
3563 if (getFunctionCFISectionType(*MF) == CFISection::None)
3570 case AArch64::EMITMTETAGGED: {
3572 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3573 ExceptionHandlingType != ExceptionHandling::ARM)
3576 if (getFunctionCFISectionType(*MF) != CFISection::None)
3581 case AArch64::AUTx16x17: {
3583 const Register Scratch = AArch64::X17;
3585 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3587 MI->getOperand(1).getImm(),
MI->getOperand(2));
3589 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3590 std::nullopt,
MI->getDeactivationSymbol());
3594 case AArch64::AUTxMxN: {
3596 const Register Scratch =
MI->getOperand(1).getReg();
3598 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3600 MI->getOperand(4).getImm(),
MI->getOperand(5));
3602 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3603 std::nullopt,
MI->getDeactivationSymbol());
3607 case AArch64::AUTPAC: {
3609 const Register Scratch = AArch64::X17;
3611 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3613 MI->getOperand(1).getImm(),
MI->getOperand(2));
3615 auto SignSchema = PtrAuthSchema::CreateImmReg(
3617 MI->getOperand(4).getImm(),
MI->getOperand(5));
3619 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3620 std::nullopt,
MI->getDeactivationSymbol());
3624 case AArch64::AUTPCPAC: {
3625 auto AuthSchema = PtrAuthSchema::CreateRegReg(
3629 auto SignSchema = PtrAuthSchema::CreateImmReg(
3631 MI->getOperand(2).getImm(),
MI->getOperand(3));
3633 emitPtrauthAuthResign(AArch64::X17, AArch64::X16,
3634 AuthSchema, SignSchema, std::nullopt,
3635 MI->getDeactivationSymbol());
3639 case AArch64::AUTRELLOADPAC: {
3641 const Register Scratch = AArch64::X17;
3643 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3645 MI->getOperand(1).getImm(),
MI->getOperand(2));
3647 auto SignSchema = PtrAuthSchema::CreateImmReg(
3649 MI->getOperand(4).getImm(),
MI->getOperand(5));
3651 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3652 MI->getOperand(6).getImm(),
3653 MI->getDeactivationSymbol());
3659 emitPtrauthSign(
MI);
3662 case AArch64::LOADauthptrstatic:
3663 LowerLOADauthptrstatic(*
MI);
3666 case AArch64::LOADgotPAC:
3667 case AArch64::MOVaddrPAC:
3668 LowerMOVaddrPAC(*
MI);
3671 case AArch64::LOADgotAUTH:
3672 LowerLOADgotAUTH(*
MI);
3677 emitPtrauthBranch(
MI);
3683 case AArch64::AUTH_TCRETURN:
3684 case AArch64::AUTH_TCRETURN_BTI: {
3687 const uint64_t Disc =
MI->getOperand(3).getImm();
3689 Register AddrDisc =
MI->getOperand(4).getReg();
3691 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3693 emitPtrauthTailCallHardening(
MI);
3696 if (Callee == AddrDisc)
3703 bool AddrDiscIsImplicitDef =
3704 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3705 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3706 AddrDiscIsImplicitDef);
3707 emitBLRA(
false,
Key, Callee, DiscReg);
3711 case AArch64::TCRETURNri:
3712 case AArch64::TCRETURNrix16x17:
3713 case AArch64::TCRETURNrix17:
3714 case AArch64::TCRETURNrinotx16:
3715 case AArch64::TCRETURNriALL: {
3716 emitPtrauthTailCallHardening(
MI);
3718 recordIfImportCall(
MI);
3722 EmitToStreamer(*OutStreamer, TmpInst);
3725 case AArch64::TCRETURNdi: {
3726 emitPtrauthTailCallHardening(
MI);
3730 recordIfImportCall(
MI);
3734 EmitToStreamer(*OutStreamer, TmpInst);
3737 case AArch64::SpeculationBarrierISBDSBEndBB: {
3742 EmitToStreamer(*OutStreamer, TmpInstDSB);
3746 EmitToStreamer(*OutStreamer, TmpInstISB);
3749 case AArch64::SpeculationBarrierSBEndBB: {
3753 EmitToStreamer(*OutStreamer, TmpInstSB);
3756 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3764 const MachineOperand &MO_Sym =
MI->getOperand(0);
3765 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3766 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3770 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3777 EmitToStreamer(*OutStreamer, Adrp);
3785 EmitToStreamer(*OutStreamer, Ldr);
3788 Add.setOpcode(AArch64::ADDXri);
3791 Add.addOperand(SymTLSDescLo12);
3793 EmitToStreamer(*OutStreamer,
Add);
3797 MCInst TLSAuthDescCall;
3798 TLSAuthDescCall.
setOpcode(AArch64::TLSAUTHDESCCALL);
3800 EmitToStreamer(*OutStreamer, TLSAuthDescCall);
3809 EmitToStreamer(*OutStreamer, Blraa);
3813 case AArch64::TLSDESC_CALLSEQ: {
3821 const MachineOperand &MO_Sym =
MI->getOperand(0);
3822 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3823 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3827 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3834 EmitToStreamer(*OutStreamer, Adrp);
3837 if (STI->isTargetILP32()) {
3847 EmitToStreamer(*OutStreamer, Ldr);
3850 if (STI->isTargetILP32()) {
3851 Add.setOpcode(AArch64::ADDWri);
3855 Add.setOpcode(AArch64::ADDXri);
3859 Add.addOperand(SymTLSDescLo12);
3861 EmitToStreamer(*OutStreamer,
Add);
3866 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3868 EmitToStreamer(*OutStreamer, TLSDescCall);
3876 EmitToStreamer(*OutStreamer, Blr);
3881 case AArch64::JumpTableDest32:
3882 case AArch64::JumpTableDest16:
3883 case AArch64::JumpTableDest8:
3884 LowerJumpTableDest(*OutStreamer, *
MI);
3887 case AArch64::BR_JumpTable:
3888 LowerHardenedBRJumpTable(*
MI);
3891 case AArch64::FMOVH0:
3892 case AArch64::FMOVS0:
3893 case AArch64::FMOVD0:
3897 case AArch64::MOPSMemoryCopyPseudo:
3898 case AArch64::MOPSMemoryMovePseudo:
3899 case AArch64::MOPSMemorySetPseudo:
3900 case AArch64::MOPSMemorySetTaggingPseudo:
3901 LowerMOPS(*OutStreamer, *
MI);
3904 case TargetOpcode::STACKMAP:
3905 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3907 case TargetOpcode::PATCHPOINT:
3908 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3910 case TargetOpcode::STATEPOINT:
3911 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3913 case TargetOpcode::FAULTING_OP:
3914 return LowerFAULTING_OP(*
MI);
3916 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3917 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3920 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3921 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3924 case TargetOpcode::PATCHABLE_TAIL_CALL:
3925 LowerPATCHABLE_TAIL_CALL(*
MI);
3927 case TargetOpcode::PATCHABLE_EVENT_CALL:
3928 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3929 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3930 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3932 case AArch64::KCFI_CHECK:
3933 LowerKCFI_CHECK(*
MI);
3936 case AArch64::HWASAN_CHECK_MEMACCESS:
3937 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3938 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3939 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3940 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3943 case AArch64::SEH_StackAlloc:
3947 case AArch64::SEH_SaveFPLR:
3951 case AArch64::SEH_SaveFPLR_X:
3952 assert(
MI->getOperand(0).getImm() < 0 &&
3953 "Pre increment SEH opcode must have a negative offset");
3957 case AArch64::SEH_SaveReg:
3959 MI->getOperand(1).getImm());
3962 case AArch64::SEH_SaveReg_X:
3963 assert(
MI->getOperand(1).getImm() < 0 &&
3964 "Pre increment SEH opcode must have a negative offset");
3966 -
MI->getOperand(1).getImm());
3969 case AArch64::SEH_SaveRegP:
3970 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3971 MI->getOperand(0).getImm() <= 28) {
3972 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3973 "Register paired with LR must be odd");
3975 MI->getOperand(2).getImm());
3978 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3979 "Non-consecutive registers not allowed for save_regp");
3981 MI->getOperand(2).getImm());
3984 case AArch64::SEH_SaveRegP_X:
3985 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3986 "Non-consecutive registers not allowed for save_regp_x");
3987 assert(
MI->getOperand(2).getImm() < 0 &&
3988 "Pre increment SEH opcode must have a negative offset");
3990 -
MI->getOperand(2).getImm());
3993 case AArch64::SEH_SaveFReg:
3995 MI->getOperand(1).getImm());
3998 case AArch64::SEH_SaveFReg_X:
3999 assert(
MI->getOperand(1).getImm() < 0 &&
4000 "Pre increment SEH opcode must have a negative offset");
4002 -
MI->getOperand(1).getImm());
4005 case AArch64::SEH_SaveFRegP:
4006 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4007 "Non-consecutive registers not allowed for save_regp");
4009 MI->getOperand(2).getImm());
4012 case AArch64::SEH_SaveFRegP_X:
4013 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4014 "Non-consecutive registers not allowed for save_regp_x");
4015 assert(
MI->getOperand(2).getImm() < 0 &&
4016 "Pre increment SEH opcode must have a negative offset");
4018 -
MI->getOperand(2).getImm());
4021 case AArch64::SEH_SetFP:
4025 case AArch64::SEH_AddFP:
4029 case AArch64::SEH_Nop:
4033 case AArch64::SEH_PrologEnd:
4037 case AArch64::SEH_EpilogStart:
4041 case AArch64::SEH_EpilogEnd:
4045 case AArch64::SEH_PACSignLR:
4049 case AArch64::SEH_SaveAnyRegI:
4050 assert(
MI->getOperand(1).getImm() <= 1008 &&
4051 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4053 MI->getOperand(1).getImm());
4056 case AArch64::SEH_SaveAnyRegIP:
4057 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4058 "Non-consecutive registers not allowed for save_any_reg");
4059 assert(
MI->getOperand(2).getImm() <= 1008 &&
4060 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4062 MI->getOperand(2).getImm());
4065 case AArch64::SEH_SaveAnyRegQP:
4066 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4067 "Non-consecutive registers not allowed for save_any_reg");
4068 assert(
MI->getOperand(2).getImm() >= 0 &&
4069 "SaveAnyRegQP SEH opcode offset must be non-negative");
4070 assert(
MI->getOperand(2).getImm() <= 1008 &&
4071 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4073 MI->getOperand(2).getImm());
4076 case AArch64::SEH_SaveAnyRegQPX:
4077 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4078 "Non-consecutive registers not allowed for save_any_reg");
4079 assert(
MI->getOperand(2).getImm() < 0 &&
4080 "SaveAnyRegQPX SEH opcode offset must be negative");
4081 assert(
MI->getOperand(2).getImm() >= -1008 &&
4082 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
4084 -
MI->getOperand(2).getImm());
4087 case AArch64::SEH_AllocZ:
4088 assert(
MI->getOperand(0).getImm() >= 0 &&
4089 "AllocZ SEH opcode offset must be non-negative");
4090 assert(
MI->getOperand(0).getImm() <= 255 &&
4091 "AllocZ SEH opcode offset must fit into 8 bits");
4095 case AArch64::SEH_SaveZReg:
4096 assert(
MI->getOperand(1).getImm() >= 0 &&
4097 "SaveZReg SEH opcode offset must be non-negative");
4098 assert(
MI->getOperand(1).getImm() <= 255 &&
4099 "SaveZReg SEH opcode offset must fit into 8 bits");
4101 MI->getOperand(1).getImm());
4104 case AArch64::SEH_SavePReg:
4105 assert(
MI->getOperand(1).getImm() >= 0 &&
4106 "SavePReg SEH opcode offset must be non-negative");
4107 assert(
MI->getOperand(1).getImm() <= 255 &&
4108 "SavePReg SEH opcode offset must fit into 8 bits");
4110 MI->getOperand(1).getImm());
4115 recordIfImportCall(
MI);
4117 MCInstLowering.
Lower(
MI, TmpInst);
4118 EmitToStreamer(*OutStreamer, TmpInst);
4121 case AArch64::CBWPri:
4122 case AArch64::CBXPri:
4123 case AArch64::CBBAssertExt:
4124 case AArch64::CBHAssertExt:
4125 case AArch64::CBWPrr:
4126 case AArch64::CBXPrr:
4127 emitCBPseudoExpansion(
MI);
4129 case AArch64::ATOMIC_STORE_HINT_B:
4130 case AArch64::ATOMIC_STORE_HINT_H:
4131 case AArch64::ATOMIC_STORE_HINT_W:
4132 case AArch64::ATOMIC_STORE_HINT_X:
4133 emitAtomicHintPseudoExpansion(
MI);
4135 case AArch64::ATOMIC_STORE_HINT_BroW:
4136 case AArch64::ATOMIC_STORE_HINT_HroW:
4137 case AArch64::ATOMIC_STORE_HINT_WroW:
4138 case AArch64::ATOMIC_STORE_HINT_XroW:
4139 case AArch64::ATOMIC_STORE_HINT_SroW:
4140 case AArch64::ATOMIC_STORE_HINT_DroW:
4141 case AArch64::ATOMIC_STORE_HINT_BroX:
4142 case AArch64::ATOMIC_STORE_HINT_HroX:
4143 case AArch64::ATOMIC_STORE_HINT_WroX:
4144 case AArch64::ATOMIC_STORE_HINT_XroX:
4145 case AArch64::ATOMIC_STORE_HINT_SroX:
4146 case AArch64::ATOMIC_STORE_HINT_DroX:
4147 emitAtomicHintPseudoExpansionRO(
MI);
4149 case AArch64::ATOMIC_STORE_HINT_Bui:
4150 case AArch64::ATOMIC_STORE_HINT_Hui:
4151 case AArch64::ATOMIC_STORE_HINT_Wui:
4152 case AArch64::ATOMIC_STORE_HINT_Xui:
4153 case AArch64::ATOMIC_STORE_HINT_Sui:
4154 case AArch64::ATOMIC_STORE_HINT_Dui:
4155 case AArch64::ATOMIC_STORE_HINT_Bi:
4156 case AArch64::ATOMIC_STORE_HINT_Hi:
4157 case AArch64::ATOMIC_STORE_HINT_Wi:
4158 case AArch64::ATOMIC_STORE_HINT_Xi:
4159 case AArch64::ATOMIC_STORE_HINT_Si:
4160 case AArch64::ATOMIC_STORE_HINT_Di:
4161 emitAtomicHintPseudoExpansionImm(
MI);
4165 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
4170 MCInstLowering.
Lower(
MI, TmpInst);
4171 EmitToStreamer(*OutStreamer, TmpInst);
4174void AArch64AsmPrinter::recordIfImportCall(
4175 const llvm::MachineInstr *BranchInst) {
4176 if (!EnableImportCallOptimization)
4180 if (GV && GV->hasDLLImportStorageClass()) {
4181 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
4186 .push_back({CallSiteSymbol, CalledSymbol});
4190void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
4191 MCSymbol *LazyPointer) {
4208 EmitToStreamer(Adrp);
4216 MCOperand SymPageOff;
4223 EmitToStreamer(Ldr);
4226 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
4227 .addReg(AArch64::X16)
4228 .addReg(AArch64::X16)
4231 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4233 .addReg(AArch64::X16));
4236void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
4237 const GlobalIFunc &GI,
4238 MCSymbol *LazyPointer) {
4270 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4271 .addReg(AArch64::SP)
4272 .addReg(AArch64::FP)
4273 .addReg(AArch64::LR)
4274 .addReg(AArch64::SP)
4277 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4278 .addReg(AArch64::FP)
4279 .addReg(AArch64::SP)
4283 for (
int I = 0;
I != 4; ++
I)
4284 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4285 .addReg(AArch64::SP)
4286 .addReg(AArch64::X1 + 2 *
I)
4287 .addReg(AArch64::X0 + 2 *
I)
4288 .addReg(AArch64::SP)
4291 for (
int I = 0;
I != 4; ++
I)
4292 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
4293 .addReg(AArch64::SP)
4294 .addReg(AArch64::D1 + 2 *
I)
4295 .addReg(AArch64::D0 + 2 *
I)
4296 .addReg(AArch64::SP)
4300 MCInstBuilder(AArch64::BL)
4313 EmitToStreamer(Adrp);
4321 MCOperand SymPageOff;
4328 EmitToStreamer(Ldr);
4331 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
4332 .addReg(AArch64::X0)
4333 .addReg(AArch64::X16)
4336 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4337 .addReg(AArch64::X16)
4338 .addReg(AArch64::X0)
4342 for (
int I = 3;
I != -1; --
I)
4343 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
4344 .addReg(AArch64::SP)
4345 .addReg(AArch64::D1 + 2 *
I)
4346 .addReg(AArch64::D0 + 2 *
I)
4347 .addReg(AArch64::SP)
4350 for (
int I = 3;
I != -1; --
I)
4351 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4352 .addReg(AArch64::SP)
4353 .addReg(AArch64::X1 + 2 *
I)
4354 .addReg(AArch64::X0 + 2 *
I)
4355 .addReg(AArch64::SP)
4358 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4359 .addReg(AArch64::SP)
4360 .addReg(AArch64::FP)
4361 .addReg(AArch64::LR)
4362 .addReg(AArch64::SP)
4365 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4367 .addReg(AArch64::X16));
4370const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4371 const Constant *BaseCV,
4381char AArch64AsmPrinter::ID = 0;
4384 "AArch64 Assembly Printer",
false,
false)
4388LLVMInitializeAArch64AsmPrinter() {
4398 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4408 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4419 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 isValid() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static SectionKind getMetadata()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void push_back(const T &Elt)
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
Represent a constant reference to a string, i.e.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
virtual MCSection * getSectionForJumpTable(const Function &F, const TargetMachine &TM) const
Primary interface to the complete machine description for the target machine.
bool regsOverlap(Register RegA, Register RegB) const
Returns true if the two registers are equal or alias each other.
Triple - Helper class for working with autoconf configuration names.
bool isFunctionTy() const
True if this is an instance of FunctionType.
LLVM Value Representation.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI StringRef getVendorName(unsigned const Vendor)
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
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 >
@ Store
The extracted value is stored (ExtractElement only).
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
std::string utostr(uint64_t X, bool isNeg=false)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
static unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K, bool Zero)
Return B(L)RA opcode to be used for an authenticated branch or call using the given key,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Target & getTheAArch64leTarget()
auto dyn_cast_or_null(const Y &Val)
Target & getTheAArch64_32Target()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Target & getTheARM64_32Target()
static MCRegister getXRegFromWReg(MCRegister Reg)
Target & getTheARM64Target()
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static MCRegister getXRegFromXRegTuple(MCRegister RegTuple)
static unsigned getPACOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return PAC opcode to be used for a ptrauth sign using the given key, or its PAC*Z variant that doesn'...
static MCRegister getWRegFromXReg(MCRegister Reg)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
static unsigned getAUTOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return AUT opcode to be used for a ptrauth auth using the given key, or its AUT*Z variant that doesn'...
@ MCSA_WeakAntiDep
.weak_anti_dep (COFF)
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...