80#define DEBUG_TYPE "AArch64AsmPrinter"
85 "Number of zero-cycle FPR zeroing instructions expanded from "
86 "canonical pseudo instructions");
94 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
95 bool PtrauthInitFini =
false;
96 bool PtrauthInitFiniAddressDisc =
false;
98 unsigned InstsEmitted;
100 bool EnableImportCallOptimization =
false;
102 SectionToImportedFunctionCalls;
103 unsigned PAuthIFuncNextUniqueID = 1;
110 MCInstLowering(OutContext, *this), FM(*this) {}
112 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
116 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const {
117 return MCInstLowering.lowerOperand(MO, MCOp);
120 const MCExpr *lowerConstantPtrAuth(
const ConstantPtrAuth &CPA)
override;
122 const MCExpr *lowerBlockAddressConstant(
const BlockAddress &BA)
override;
124 void emitStartOfAsmFile(
Module &M)
override;
125 void emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
126 ArrayRef<unsigned> JumpTableIndices)
override;
129 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
130 const MCSymbol *BranchLabel)
const override;
132 void emitFunctionEntryLabel()
override;
134 void emitXXStructor(
const DataLayout &
DL,
const Constant *CV)
override;
136 void LowerJumpTableDest(MCStreamer &OutStreamer,
const MachineInstr &
MI);
138 void LowerHardenedBRJumpTable(
const MachineInstr &
MI);
140 void LowerMOPS(MCStreamer &OutStreamer,
const MachineInstr &
MI);
142 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
143 const MachineInstr &
MI);
144 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
145 const MachineInstr &
MI);
146 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
147 const MachineInstr &
MI);
148 void LowerFAULTING_OP(
const MachineInstr &
MI);
150 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI);
151 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI);
152 void LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI);
153 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
155 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
156 HwasanMemaccessTuple;
157 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
158 void LowerKCFI_CHECK(
const MachineInstr &
MI);
159 void LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI);
160 void emitHwasanMemaccessSymbols(
Module &M);
162 void emitSled(
const MachineInstr &
MI, SledKind Kind);
170 if (STI->isX16X17Safer())
171 return Reg == AArch64::X16 ||
Reg == AArch64::X17;
177 void emitPtrauthBranch(
const MachineInstr *
MI);
179 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
183 const MCSymbol *OnFailure =
nullptr);
186 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
188 struct PtrAuthSchema {
190 const MachineOperand &AddrDiscOp);
197 bool AddrDiscIsKilled;
200 bool addrDiscIsKilledAndNoneOf(std::initializer_list<Register> Regs) {
218 PtrAuthSchema AuthSchema,
219 std::optional<PtrAuthSchema> SignSchema,
220 std::optional<int64_t> Addend,
Value *DS);
225 bool emitDeactivationSymbolRelocation(
Value *DS);
228 void emitPtrauthSign(
const MachineInstr *
MI);
252 bool MayClobberAddrDisc =
false);
255 void LowerLOADauthptrstatic(
const MachineInstr &
MI);
259 void LowerMOVaddrPAC(
const MachineInstr &
MI);
264 void LowerLOADgotAUTH(
const MachineInstr &
MI);
266 void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
267 void emitAddress(MCRegister
Reg,
const MCExpr *Expr, MCRegister Tmp,
268 bool DSOLocal,
const MCSubtargetInfo &STI);
270 const MCExpr *emitPAuthRelocationAsIRelative(
272 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
276 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
279 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
280 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
283 void emitCBPseudoExpansion(
const MachineInstr *
MI);
286 void emitAtomicHintPseudoExpansion(
const MachineInstr *
MI);
287 void emitAtomicHintPseudoExpansionRO(
const MachineInstr *
MI);
288 void emitAtomicHintPseudoExpansionImm(
const MachineInstr *
MI);
291 void emitAtomicFetchHintPseudoExpansion(
const MachineInstr *
MI);
293 void EmitToStreamer(MCStreamer &S,
const MCInst &Inst);
294 void EmitToStreamer(
const MCInst &Inst) {
295 EmitToStreamer(*OutStreamer, Inst);
300 void emitFunctionHeaderComment()
override;
302 void getAnalysisUsage(AnalysisUsage &AU)
const override {
308 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
309 PSI = &PSIW->getPSI();
311 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
312 SDPI = &SDPIW->getStaticDataProfileInfo();
314 AArch64FI = MF.
getInfo<AArch64FunctionInfo>();
317 SetupMachineFunction(MF);
319 if (STI->isTargetCOFF()) {
326 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
327 OutStreamer->emitCOFFSymbolStorageClass(Scl);
328 OutStreamer->emitCOFFSymbolType(
Type);
329 OutStreamer->endCOFFSymbolDef();
343 const Constant *BaseCV =
nullptr,
347 void printOperand(
const MachineInstr *
MI,
unsigned OpNum, raw_ostream &O);
349 bool printAsmRegInClass(
const MachineOperand &MO,
353 bool PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
354 const char *ExtraCode, raw_ostream &O)
override;
355 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
356 const char *ExtraCode, raw_ostream &O)
override;
358 void PrintDebugValueComment(
const MachineInstr *
MI, raw_ostream &OS);
360 void emitFunctionBodyEnd()
override;
361 void emitBasicBlockEnd(
const MachineBasicBlock &
MBB)
override;
362 void emitGlobalAlias(
const Module &M,
const GlobalAlias &GA)
override;
364 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
365 void emitEndOfAsmFile(
Module &M)
override;
367 AArch64FunctionInfo *AArch64FI =
nullptr;
382 void emitFMov0(
const MachineInstr &
MI);
383 void emitFMov0AsFMov(
const MachineInstr &
MI,
Register DestReg);
385 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
387 MInstToMCSymbol LOHInstToLabel;
389 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
390 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
393 const MCSubtargetInfo *getIFuncMCSubtargetInfo()
const override {
397 void emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
398 MCSymbol *LazyPointer)
override;
399 void emitMachOIFuncStubHelperBody(
Module &M,
const GlobalIFunc &GI,
400 MCSymbol *LazyPointer)
override;
405 void recordIfImportCall(
const MachineInstr *BranchInst);
412 Metadata *Flag = M.getModuleFlag(Name);
417 assert((
Value == 0 ||
Value == 1) &&
"Boolean flag is expected, if present");
421void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
422 const Triple &
TT =
M.getTargetTriple();
424 if (
TT.isOSBinFormatCOFF()) {
425 emitCOFFFeatureSymbol(M);
426 emitCOFFReplaceableFunctionData(M);
428 if (
M.getModuleFlag(
"import-call-optimization"))
429 EnableImportCallOptimization =
true;
434 M,
"ptrauth-init-fini-address-discrimination");
436 if (!
TT.isOSBinFormatELF())
441 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
444 unsigned BAFlags = 0;
445 unsigned GNUFlags = 0;
447 M.getModuleFlag(
"branch-target-enforcement"))) {
448 if (!BTE->isZero()) {
449 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
455 M.getModuleFlag(
"guarded-control-stack"))) {
456 if (!GCS->isZero()) {
457 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
463 M.getModuleFlag(
"sign-return-address"))) {
464 if (!Sign->isZero()) {
465 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
472 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
473 PAuthABIPlatform = PAP->getZExtValue();
478 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
479 PAuthABIVersion = PAV->getZExtValue();
487 PAuthABIVersion == 0) {
493 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
495 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
498void AArch64AsmPrinter::emitFunctionHeaderComment() {
499 const AArch64FunctionInfo *FI = MF->
getInfo<AArch64FunctionInfo>();
501 if (OutlinerString != std::nullopt)
502 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
505void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
508 if (
F.hasFnAttribute(
"patchable-function-entry")) {
510 if (
F.getFnAttribute(
"patchable-function-entry")
512 .getAsInteger(10, Num))
518 emitSled(
MI, SledKind::FUNCTION_ENTER);
521void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
522 emitSled(
MI, SledKind::FUNCTION_EXIT);
525void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
526 emitSled(
MI, SledKind::TAIL_CALL);
529void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
530 static const int8_t NoopsInSledCount = 7;
551 OutStreamer->emitCodeAlignment(
Align(4), getSubtargetInfo());
552 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
553 OutStreamer->emitLabel(CurSled);
554 auto Target = OutContext.createTempSymbol();
559 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
561 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
562 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
564 OutStreamer->emitLabel(Target);
565 recordSled(CurSled,
MI, Kind, 2);
568void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
571 AArch64TargetStreamer *TS) {
573 PAuthABIPlatform = (
uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
574 PAuthABIVersion = (
uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
576 if (PAuthABIPlatform || PAuthABIVersion) {
580 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
581 AArch64BuildAttributes::SubsectionType::ULEB128);
585 PAuthABIPlatform,
"");
599 if (BTIValue || PACValue || GCSValue) {
603 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
604 AArch64BuildAttributes::SubsectionType::ULEB128);
632void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
634 auto &
O = *OutStreamer;
635 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
636 O.emitLabel(CurSled);
637 bool MachO = MMI->getModule()->getTargetTriple().isOSBinFormatMachO();
639 OutContext.getOrCreateSymbol(
640 Twine(MachO ?
"_" :
"") +
641 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
644 O.AddComment(
"Begin XRay typed event");
645 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
646 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
652 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
656 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
657 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
658 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
659 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
660 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
664 O.AddComment(
"End XRay typed event");
665 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
672 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
674 O.AddComment(
"Begin XRay custom event");
675 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
676 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
682 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
683 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
684 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
685 O.AddComment(
"End XRay custom event");
686 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
693 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
697void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
699 assert(std::next(
MI.getIterator())->isCall() &&
700 "KCFI_CHECK not followed by a call instruction");
701 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
702 "KCFI_CHECK call target doesn't match call operand");
706 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
707 if (AddrReg == AArch64::XZR) {
711 emitMovXReg(AddrReg, AArch64::XZR);
717 for (
auto &
Reg : ScratchRegs) {
723 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
724 "Invalid scratch registers for KCFI_CHECK");
729 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
730 "patchable-function-prefix");
733 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
734 .addReg(ScratchRegs[0])
736 .addImm(-(PrefixNops * 4 + 4)));
740 const int64_t
Type =
MI.getOperand(1).getImm();
741 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
742 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
745 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
746 .addReg(AArch64::WZR)
747 .addReg(ScratchRegs[0])
748 .addReg(ScratchRegs[1])
752 EmitToStreamer(*OutStreamer,
753 MCInstBuilder(AArch64::Bcc)
762 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
766 AddrIndex = AddrReg - AArch64::X0;
776 assert(AddrIndex < 31 && TypeIndex < 31);
778 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
779 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
780 OutStreamer->emitLabel(
Pass);
783void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
791 if (
Reg == AArch64::XZR)
795 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
797 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
798 uint32_t AccessInfo =
MI.getOperand(1).getImm();
800 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
802 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
803 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
805 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
806 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
809 if (!TM.getTargetTriple().isOSBinFormatELF())
812 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
815 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
817 SymName +=
"_short_v2";
818 Sym = OutContext.getOrCreateSymbol(SymName);
821 EmitToStreamer(*OutStreamer,
822 MCInstBuilder(AArch64::BL)
826void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
827 if (HwasanMemaccessSymbols.empty())
830 const Triple &
TT =
M.getTargetTriple();
834 auto STI = std::make_unique<AArch64Subtarget>(
835 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
837 this->STI = STI.get();
840 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
842 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
844 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
846 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
849 for (
auto &
P : HwasanMemaccessSymbols) {
850 unsigned Reg = std::get<0>(
P.first);
851 bool IsShort = std::get<1>(
P.first);
852 uint32_t AccessInfo = std::get<2>(
P.first);
853 bool IsFixedShadow = std::get<3>(
P.first);
854 uint64_t FixedShadowOffset = std::get<4>(
P.first);
855 const MCSymbolRefExpr *HwasanTagMismatchRef =
856 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
859 bool HasMatchAllTag =
861 uint8_t MatchAllTag =
868 OutStreamer->switchSection(OutContext.getELFSection(
874 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
875 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
876 OutStreamer->emitLabel(Sym);
878 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
879 .addReg(AArch64::X16)
889 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
890 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
891 .addReg(AArch64::W16)
892 .addReg(AArch64::X17)
893 .addReg(AArch64::X16)
897 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
898 .addReg(AArch64::W16)
899 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
900 .addReg(AArch64::X16)
905 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
906 .addReg(AArch64::XZR)
907 .addReg(AArch64::X16)
910 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
911 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
914 HandleMismatchOrPartialSym, OutContext)));
915 MCSymbol *ReturnSym = OutContext.createTempSymbol();
916 OutStreamer->emitLabel(ReturnSym);
917 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
918 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
920 if (HasMatchAllTag) {
921 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
922 .addReg(AArch64::X17)
926 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
927 .addReg(AArch64::XZR)
928 .addReg(AArch64::X17)
932 MCInstBuilder(AArch64::Bcc)
938 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
939 .addReg(AArch64::WZR)
940 .addReg(AArch64::W16)
943 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
945 MCInstBuilder(AArch64::Bcc)
949 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
950 .addReg(AArch64::X17)
954 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
955 .addReg(AArch64::X17)
956 .addReg(AArch64::X17)
959 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
960 .addReg(AArch64::WZR)
961 .addReg(AArch64::W16)
962 .addReg(AArch64::W17)
965 MCInstBuilder(AArch64::Bcc)
969 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
970 .addReg(AArch64::X16)
973 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
974 .addReg(AArch64::W16)
975 .addReg(AArch64::X16)
978 MCInstBuilder(AArch64::SUBSXrs)
979 .addReg(AArch64::XZR)
980 .addReg(AArch64::X16)
984 MCInstBuilder(AArch64::Bcc)
988 OutStreamer->emitLabel(HandleMismatchSym);
991 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
997 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
1000 .addReg(AArch64::SP)
1003 if (
Reg != AArch64::X0)
1004 emitMovXReg(AArch64::X0,
Reg);
1007 if (CompileKernel) {
1011 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
1016 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
1017 .addReg(AArch64::X16)
1021 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
1022 .addReg(AArch64::X16)
1023 .addReg(AArch64::X16)
1027 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1030 this->STI =
nullptr;
1035 const MCExpr *StubAuthPtrRef) {
1038 OutStreamer.
emitValue(StubAuthPtrRef, 8);
1041void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
1042 emitHwasanMemaccessSymbols(M);
1044 const Triple &
TT =
M.getTargetTriple();
1045 if (
TT.isOSBinFormatMachO()) {
1047 MachineModuleInfoMachO &MMIMacho =
1048 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1052 if (!Stubs.empty()) {
1054 OutStreamer->switchSection(
1057 emitAlignment(
Align(8));
1059 for (
const auto &Stub : Stubs)
1062 OutStreamer->addBlankLine();
1070 OutStreamer->emitSubsectionsViaSymbols();
1073 if (
TT.isOSBinFormatELF()) {
1075 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1079 if (!Stubs.empty()) {
1080 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1082 emitAlignment(
Align(8));
1084 for (
const auto &Stub : Stubs)
1087 OutStreamer->addBlankLine();
1098 M.getModuleFlag(
"ptrauth-elf-got"));
1099 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1100 for (
const GlobalValue &GV :
M.global_values())
1102 !GV.getName().starts_with(
"llvm."))
1103 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1112 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1113 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1116 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1117 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1128 for (
auto &[Section, CallsToImportedFuncs] :
1129 SectionToImportedFunctionCalls) {
1131 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1132 OutStreamer->emitInt32(SectionSize);
1133 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1134 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1136 OutStreamer->emitInt32(0x13);
1137 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1138 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1144void AArch64AsmPrinter::emitLOHs() {
1148 for (
const MachineInstr *
MI :
D.getArgs()) {
1149 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1150 assert(LabelIt != LOHInstToLabel.end() &&
1151 "Label hasn't been inserted for LOH related instruction");
1154 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1165void AArch64AsmPrinter::emitBasicBlockEnd(
const MachineBasicBlock &
MBB) {
1168 if (
Next == MF->
end() ||
Next->isEHFuncletEntry()) {
1170 if (
MI.isMetaInstruction() || AArch64InstrInfo::isSEHInstruction(
MI))
1172 if (
MI.isCall() && !
MI.isReturn())
1173 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(1));
1182void AArch64AsmPrinter::emitFunctionBodyEnd() {
1188MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1192 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1193 return OutContext.getOrCreateSymbol(
1194 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1195 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1200void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1202 const MachineOperand &MO =
MI->getOperand(OpNum);
1218 PrintSymbolOperand(MO, O);
1229bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1253bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1255 unsigned AltName, raw_ostream &O) {
1256 assert(MO.
isReg() &&
"Should only get here with a register!");
1257 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1266bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1267 const char *ExtraCode, raw_ostream &O) {
1268 const MachineOperand &MO =
MI->getOperand(OpNum);
1275 if (ExtraCode && ExtraCode[0]) {
1276 if (ExtraCode[1] != 0)
1279 switch (ExtraCode[0]) {
1287 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1301 switch (ExtraCode[0]) {
1303 RC = &AArch64::FPR8RegClass;
1306 RC = &AArch64::FPR16RegClass;
1309 RC = &AArch64::FPR32RegClass;
1312 RC = &AArch64::FPR64RegClass;
1315 RC = &AArch64::FPR128RegClass;
1318 RC = &AArch64::ZPRRegClass;
1323 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1344 unsigned AltName = AArch64::NoRegAltName;
1347 RegClass = &AArch64::ZPRRegClass;
1349 RegClass = &AArch64::PPRRegClass;
1351 RegClass = &AArch64::PNRRegClass;
1353 RegClass = &AArch64::FPR128RegClass;
1354 AltName = AArch64::vreg;
1358 return printAsmRegInClass(MO, RegClass, AltName, O);
1365bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1367 const char *ExtraCode,
1369 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1372 const MachineOperand &MO =
MI->getOperand(OpNum);
1373 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1378void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1380 unsigned NOps =
MI->getNumOperands();
1382 OS <<
'\t' << MAI.getCommentString() <<
"DEBUG_VALUE: ";
1384 OS <<
MI->getDebugVariable()->getName();
1387 assert(
MI->isIndirectDebugValue());
1399void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1400 ArrayRef<unsigned> JumpTableIndices) {
1402 if (JumpTableIndices.
empty())
1404 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1408 MCSection *ReadOnlySec =
nullptr;
1409 if (TM.Options.EnableStaticDataPartitioning) {
1415 OutStreamer->switchSection(ReadOnlySec);
1417 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1418 for (
unsigned JTI : JumpTableIndices) {
1419 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1422 if (JTBBs.empty())
continue;
1424 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1426 OutStreamer->emitLabel(GetJTISymbol(JTI));
1431 for (
auto *JTBB : JTBBs) {
1432 const MCExpr *
Value =
1451AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1452 const MachineInstr *BranchInstr,
1453 const MCSymbol *BranchLabel)
const {
1454 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1457 switch (AFI->getJumpTableEntrySize(JTI)) {
1459 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1462 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1465 EntrySize = codeview::JumpTableEntrySize::Int32;
1470 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1473void AArch64AsmPrinter::emitFunctionEntryLabel() {
1474 const Triple &
TT = TM.getTargetTriple();
1475 if (
TT.isOSBinFormatELF() &&
1478 CallingConv::AArch64_SVE_VectorCall ||
1479 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1481 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1492 OutStreamer->emitAssignment(
1496 auto getSymbolFromMetadata = [&](StringRef
Name) {
1500 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1507 for (MDNode *Node : UnmangledNames) {
1509 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1510 if (std::optional<std::string> MangledName =
1513 MMI->getContext().getOrCreateSymbol(*MangledName);
1514 emitFunctionAlias(UnmangledSym, ECMangledSym);
1517 if (MCSymbol *ECMangledSym =
1518 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1519 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1523void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1524 const Constant *CV) {
1527 "ctors/dtors are to be signed by asm printer");
1529 if (PtrauthInitFini) {
1535 ConstantInt *IntDisc = ConstantInt::get(
1539 if (PtrauthInitFiniAddressDisc) {
1553void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1554 const GlobalAlias &GA) {
1560 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1562 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1565 OutStreamer->beginCOFFSymbolDef(ExpSym);
1569 OutStreamer->endCOFFSymbolDef();
1571 OutStreamer->beginCOFFSymbolDef(Sym);
1575 OutStreamer->endCOFFSymbolDef();
1576 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1577 OutStreamer->emitAssignment(
1594void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1595 const llvm::MachineInstr &
MI) {
1596 Register DestReg =
MI.getOperand(0).getReg();
1597 Register ScratchReg =
MI.getOperand(1).getReg();
1599 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1600 Register TableReg =
MI.getOperand(2).getReg();
1601 Register EntryReg =
MI.getOperand(3).getReg();
1602 int JTIdx =
MI.getOperand(4).getIndex();
1608 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1619 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1621 .addExpr(LabelExpr));
1626 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1627 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1628 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1633 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1634 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1638 .addImm(
Size == 1 ? 0 : 1));
1642 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1646 .addImm(
Size == 4 ? 0 : 2));
1649void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1651 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1653 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1654 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1670 MachineOperand JTOp =
MI.getOperand(0);
1674 "unsupported compressed jump table");
1676 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1680 uint64_t MaxTableEntry = NumTableEntries - 1;
1682 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1683 .addReg(AArch64::XZR)
1684 .addReg(AArch64::X16)
1685 .addImm(MaxTableEntry)
1688 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1693 if ((MaxTableEntry >>
Offset) == 0)
1695 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1698 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1699 .addReg(AArch64::XZR)
1700 .addReg(AArch64::X16)
1701 .addReg(AArch64::X17)
1707 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1708 .addReg(AArch64::X16)
1709 .addReg(AArch64::X16)
1710 .addReg(AArch64::XZR)
1714 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1715 MCOperand JTMCHi, JTMCLo;
1725 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1727 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1728 .addReg(AArch64::X17)
1729 .addReg(AArch64::X17)
1733 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1734 .addReg(AArch64::X16)
1735 .addReg(AArch64::X17)
1736 .addReg(AArch64::X16)
1747 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1749 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1750 .addReg(AArch64::X16)
1751 .addReg(AArch64::X17)
1752 .addReg(AArch64::X16)
1755 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1758void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1759 const llvm::MachineInstr &
MI) {
1760 unsigned Opcode =
MI.getOpcode();
1762 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1764 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1765 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1766 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1767 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1768 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1769 if (Opcode == AArch64::MOPSMemorySetPseudo)
1770 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1771 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1772 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1775 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1776 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1778 for (
auto Op :
Ops) {
1780 auto MCIB = MCInstBuilder(
Op);
1782 MCIB.addReg(
MI.getOperand(i++).getReg());
1783 MCIB.addReg(
MI.getOperand(i++).getReg());
1785 MCIB.addReg(
MI.getOperand(i++).getReg());
1787 MCIB.addReg(
MI.getOperand(i++).getReg());
1788 MCIB.addReg(
MI.getOperand(i++).getReg());
1789 MCIB.addReg(
MI.getOperand(i++).getReg());
1791 EmitToStreamer(OutStreamer, MCIB);
1795void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1796 const MachineInstr &
MI) {
1797 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1800 MCSymbol *MILabel = Ctx.createTempSymbol();
1804 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1810 while (NumNOPBytes > 0) {
1811 if (MII ==
MBB.
end() || MII->isCall() ||
1812 MII->getOpcode() == AArch64::DBG_VALUE ||
1813 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1814 MII->getOpcode() == TargetOpcode::STACKMAP)
1821 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1822 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1827void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1828 const MachineInstr &
MI) {
1830 MCSymbol *MILabel = Ctx.createTempSymbol();
1834 PatchPointOpers Opers(&
MI);
1836 int64_t CallTarget = Opers.getCallTarget().getImm();
1837 unsigned EncodedBytes = 0;
1839 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1840 "High 16 bits of call target should be zero.");
1841 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1844 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1845 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1846 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1847 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1850 unsigned NumBytes = Opers.getNumPatchBytes();
1851 assert(NumBytes >= EncodedBytes &&
1852 "Patchpoint can't request size less than the length of a call.");
1853 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1854 "Invalid number of NOP bytes requested!");
1855 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1856 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1859void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1860 const MachineInstr &
MI) {
1861 StatepointOpers SOpers(&
MI);
1862 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1863 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1864 for (
unsigned i = 0; i < PatchBytes; i += 4)
1865 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1868 const MachineOperand &CallTarget = SOpers.getCallTarget();
1869 MCOperand CallTargetMCOp;
1870 unsigned CallOpcode;
1871 switch (CallTarget.
getType()) {
1874 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1875 CallOpcode = AArch64::BL;
1879 CallOpcode = AArch64::BL;
1883 CallOpcode = AArch64::BLR;
1890 EmitToStreamer(OutStreamer,
1891 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1895 MCSymbol *MILabel = Ctx.createTempSymbol();
1900void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1909 unsigned OperandsBeginIdx = 4;
1912 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1919 MI.setOpcode(Opcode);
1924 for (
const MachineOperand &MO :
1927 lowerOperand(MO, Dest);
1928 MI.addOperand(Dest);
1936 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1938 .addReg(AArch64::XZR)
1944 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1945 EmitToStreamer(*OutStreamer,
1946 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1953 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1954 EmitToStreamer(*OutStreamer,
1955 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1964 bool IsZeroDisc = Disc == AArch64::XZR;
1976 EmitToStreamer(AUTInst);
1981 bool IsZeroDisc = Disc == AArch64::XZR;
1993 EmitToStreamer(PACInst);
1998 bool IsZeroDisc = Disc == AArch64::XZR;
2008 EmitToStreamer(Inst);
2011void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
2012 Register DestReg =
MI.getOperand(0).getReg();
2013 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
2014 if (STI->hasZeroCycleZeroingFPR64()) {
2016 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2017 if (AArch64::FPR16RegClass.
contains(DestReg))
2018 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2019 &AArch64::FPR64RegClass);
2020 else if (AArch64::FPR32RegClass.
contains(DestReg))
2021 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2022 &AArch64::FPR64RegClass);
2030 EmitToStreamer(*OutStreamer, MOVI);
2031 ++NumZCZeroingInstrsFPR;
2032 }
else if (STI->hasZeroCycleZeroingFPR128()) {
2034 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2035 if (AArch64::FPR16RegClass.
contains(DestReg)) {
2036 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2037 &AArch64::FPR128RegClass);
2038 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
2039 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2040 &AArch64::FPR128RegClass);
2043 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
2044 &AArch64::FPR128RegClass);
2051 EmitToStreamer(*OutStreamer, MOVI);
2052 ++NumZCZeroingInstrsFPR;
2054 emitFMov0AsFMov(
MI, DestReg);
2057 emitFMov0AsFMov(
MI, DestReg);
2061void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
2064 switch (
MI.getOpcode()) {
2067 case AArch64::FMOVH0:
2068 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
2069 if (!STI->hasFullFP16())
2070 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
2074 case AArch64::FMOVS0:
2079 case AArch64::FMOVD0:
2085 EmitToStreamer(*OutStreamer, FMov);
2091 bool MayClobberAddrDisc) {
2092 assert(isPtrauthRegSafe(ScratchReg) &&
2093 "Safe scratch register must be provided by the caller");
2098 AddrDisc = AArch64::XZR;
2106 if (AddrDisc == AArch64::XZR) {
2107 emitMOVZ(ScratchReg, Disc, 0);
2114 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2115 ScratchReg = AddrDisc;
2117 emitMovXReg(ScratchReg, AddrDisc);
2118 assert(ScratchReg != AddrDisc &&
2119 "Forbidden to clobber AddrDisc, but have to");
2122 emitMOVK(ScratchReg, Disc, 48);
2136void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2168 if (Method == AuthCheckMethod::None)
2170 if (Method == AuthCheckMethod::DummyLoad) {
2171 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2175 assert(!OnFailure &&
"DummyLoad always traps on error");
2179 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2180 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2182 emitMovXReg(ScratchReg, TestedReg);
2184 if (Method == AuthCheckMethod::XPAC) {
2188 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2193 assert(TestedReg == AArch64::LR &&
2194 "XPACHint mode is only compatible with checking the LR register");
2196 "XPACHint mode is only compatible with I-keys");
2197 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2201 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2202 .addReg(AArch64::XZR)
2209 MCInstBuilder(AArch64::Bcc)
2212 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2214 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2221 MCInstBuilder(AArch64::TBZX)
2232 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2246 case AuthCheckMethod::XPACHint:
2249 case AuthCheckMethod::XPAC:
2251 emitMovXReg(TestedReg, ScratchReg);
2258 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2263 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2275void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2279 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2280 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2283 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2287 "Neither x16 nor x17 is available as a scratch register");
2290 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2294bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2300 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2303 MCSymbol *Dot = OutContext.createTempSymbol();
2308 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2314AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateImmReg(
2316 PtrAuthSchema Schema;
2318 Schema.IntDisc = IntDisc;
2319 Schema.AddrDisc = AddrDiscOp.
getReg();
2320 Schema.AddrDiscIsKilled = AddrDiscOp.
isKill();
2325AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateRegReg(
2327 assert(PCDisc.
isValid() &&
"Use CreateImmReg for non-PC schemas");
2328 PtrAuthSchema Schema;
2331 Schema.AddrDisc = AddrDisc;
2332 Schema.AddrDiscIsKilled =
false;
2333 Schema.PCDisc = PCDisc;
2337void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2342 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2352 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2354 MCInstBuilder(AArch64::ADDXri)
2357 .addImm((Addend >> BitPos) & 0xfff)
2363 emitMOVZ(Scratch, Addend & 0xffff, 0);
2370 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2377 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2383 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2394 if (std::optional<PtrauthCheckMode>
Mode =
2401 return PtrauthCheckMode::Unchecked;
2404 return ShouldTrap ? PtrauthCheckMode::Trap : PtrauthCheckMode::Poison;
2435void AArch64AsmPrinter::emitPtrauthAuthResign(
2437 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2440 const bool IsAuthWithPC = AuthSchema.PCDisc.isValid();
2441 assert(!SignSchema || !SignSchema->PCDisc.isValid());
2443 Register SignAddrDiscOrNone = SignSchema ? SignSchema->AddrDisc :
Register();
2449 assert(Pointer == AArch64::X17 && Scratch == AArch64::X16 &&
2450 "AUTPCPAC must use x17/x16 as Pointer/Scratch");
2452 assert(AuthSchema.AddrDisc == AArch64::X16 &&
2453 "AUTPCPAC requires address discriminator in X16");
2455 assert(AuthSchema.PCDisc == AArch64::X15 &&
2456 "AUTPCPAC requires PC discriminator in X15");
2458 assert(AuthSchema.IntDisc == 0 &&
"AUTPCPAC does not support IntDisc");
2462 "AUTPCPAC only supports AUT-ing with IA/IB");
2464 if (!emitDeactivationSymbolRelocation(DS)) {
2466 ? AArch64::AUTIB171615
2467 : AArch64::AUTIA171615;
2468 EmitToStreamer(MCInstBuilder(AutOpc));
2478 Register AUTDiscReg = emitPtrauthDiscriminator(
2479 AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2480 AuthSchema.addrDiscIsKilledAndNoneOf({Pointer, SignAddrDiscOrNone}));
2481 if (!emitDeactivationSymbolRelocation(DS))
2482 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2487 auto EmitCheck = [&](
MCSymbol *OnFailure =
nullptr) {
2488 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2489 AArch64PAuth::AuthCheckMethod::XPAC,
2493 auto EmitResignOnSuccess = [&]() {
2494 if (Addend.has_value())
2495 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2497 assert(Pointer != SignSchema->AddrDisc &&
"Pointer is early-clobbered");
2499 emitPtrauthDiscriminator(SignSchema->IntDisc, SignSchema->AddrDisc,
2500 Scratch, SignSchema->AddrDiscIsKilled);
2501 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2507 if (CheckMode == PtrauthCheckMode::Trap)
2513 switch (CheckMode) {
2514 case PtrauthCheckMode::Unchecked:
2515 EmitResignOnSuccess();
2517 case PtrauthCheckMode::Trap:
2519 EmitResignOnSuccess();
2521 case PtrauthCheckMode::Poison:
2522 MCSymbol *OnFailure = createTempSymbol(
"resign_end_");
2523 EmitCheck(OnFailure);
2524 EmitResignOnSuccess();
2530void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2534 Register AddrDisc =
MI->getOperand(4).getReg();
2535 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2539 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2540 assert(ScratchReg != AddrDisc &&
2541 "Neither X16 nor X17 is available as a scratch register");
2544 Register DiscReg = emitPtrauthDiscriminator(
2545 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2547 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2550 emitPAC(
Key, Val, DiscReg);
2553void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2554 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2555 unsigned BrTarget =
MI->getOperand(0).getReg();
2560 unsigned AddrDisc =
MI->getOperand(3).getReg();
2566 if (BrTarget == AddrDisc)
2583 bool AddrDiscIsImplicitDef =
2584 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2585 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2586 AddrDiscIsImplicitDef);
2587 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2590void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2594 const bool IsNeg = Addend < 0;
2596 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2599 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2602 .addImm((AbsOffset >> BitPos) & 0xfff)
2607 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2609 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2611 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2612 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2613 uint64_t Shifted = UAddend >> BitPos;
2615 return Shifted != 0;
2616 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2617 if (((Shifted >>
I) & 0xffff) != 0xffff)
2621 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2622 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2624 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2633void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2634 MCRegister Tmp,
bool DSOLocal,
2635 const MCSubtargetInfo &STI) {
2641 MCInstBuilder(AArch64::ADRP)
2645 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2655 MCInstBuilder(AArch64::ADRP)
2660 MCInstBuilder(AArch64::LDRXui)
2671 if (!TT.isOSBinFormatELF())
2675 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2676 TT.isOSDragonFly() || TT.isOSNetBSD();
2730const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2732 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2733 const Triple &
TT = TM.getTargetTriple();
2745 auto STI = std::make_unique<AArch64Subtarget>(
2746 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2748 this->STI = STI.get();
2754 const MCSymbolELF *Group =
2769 .addReg(AArch64::X0)
2774 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2776 if (HasAddressDiversity) {
2781 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2785 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2787 "' out of range [0, 0xFFFF]");
2789 emitMOVZ(AArch64::X1, Disc, 0);
2796 auto *PrePACInstExpr =
2808 const MCSymbolRefExpr *EmuPACRef =
2810 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2817 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2826AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2827 MCContext &Ctx = OutContext;
2832 getDataLayout(),
Offset,
true);
2852 const MCExpr *DSExpr =
nullptr;
2864 "' out of range [0, " +
2872 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2874 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2879 "' out of range [0, 0xFFFF]");
2885 "expressions on this target");
2892void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2893 unsigned DstReg =
MI.getOperand(0).getReg();
2894 const MachineOperand &GAOp =
MI.getOperand(1);
2895 const uint64_t KeyC =
MI.getOperand(2).getImm();
2897 "key is out of range [0, AArch64PACKey::LAST]");
2899 const uint64_t Disc =
MI.getOperand(3).getImm();
2901 "constant discriminator is out of range [0, 0xffff]");
2910 if (TM.getTargetTriple().isOSBinFormatELF()) {
2912 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2915 "non-zero offset for $auth_ptr$ stub slots is not supported");
2917 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2919 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2920 "LOADauthptrstatic is implemented only for MachO/ELF");
2922 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2923 getObjFileLowering());
2926 "non-zero offset for $auth_ptr$ stub slots is not supported");
2928 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2931 MachineOperand StubMOHi =
2935 MCOperand StubMCHi, StubMCLo;
2942 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2944 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2950void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2951 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2952 const bool IsELFSignedGOT =
MI.getParent()
2954 ->getInfo<AArch64FunctionInfo>()
2955 ->hasELFSignedGOT();
2956 MachineOperand GAOp =
MI.getOperand(0);
2957 const uint64_t KeyC =
MI.getOperand(1).getImm();
2959 "key is out of range [0, AArch64PACKey::LAST]");
2961 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2962 const uint64_t Disc =
MI.getOperand(3).getImm();
3009 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
3010 MCOperand GAMCHi, GAMCLo;
3023 MCInstBuilder(AArch64::ADRP)
3024 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
3028 if (IsELFSignedGOT) {
3029 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3030 .addReg(AArch64::X17)
3031 .addReg(AArch64::X17)
3035 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3036 .addReg(AArch64::X16)
3037 .addReg(AArch64::X17)
3045 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
3047 if (!STI->hasFPAC())
3048 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
3049 AArch64PAuth::AuthCheckMethod::XPAC);
3051 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3052 .addReg(AArch64::X16)
3053 .addReg(AArch64::X16)
3057 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3058 .addReg(AArch64::X16)
3059 .addReg(AArch64::X16)
3064 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
3065 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
3067 emitPAC(
Key, AArch64::X16, DiscReg);
3070void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
3072 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
3073 const MachineOperand &GAMO =
MI.getOperand(1);
3080 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
3081 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3082 .addReg(AuthResultReg)
3083 .addReg(AArch64::X17)
3086 MachineOperand GAHiOp(GAMO);
3087 MachineOperand GALoOp(GAMO);
3091 MCOperand GAMCHi, GAMCLo;
3096 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
3098 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3099 .addReg(AArch64::X17)
3100 .addReg(AArch64::X17)
3104 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3105 .addReg(AuthResultReg)
3106 .addReg(AArch64::X17)
3113 UndefWeakSym = createTempSymbol(
"undef_weak");
3115 MCInstBuilder(AArch64::CBZX)
3116 .addReg(AuthResultReg)
3124 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
3129 if (!STI->hasFPAC()) {
3130 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
3131 AArch64PAuth::AuthCheckMethod::XPAC);
3133 emitMovXReg(DstReg, AuthResultReg);
3138AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
3142 if (std::optional<uint16_t> BADisc =
3143 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3150void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3154 switch (
MI->getOpcode()) {
3157 case AArch64::CBBAssertExt:
3161 case AArch64::CBHAssertExt:
3165 case AArch64::CBWPrr:
3168 case AArch64::CBXPrr:
3171 case AArch64::CBWPri:
3175 case AArch64::CBXPri:
3183 bool NeedsRegSwap =
false;
3184 bool NeedsImmDec =
false;
3185 bool NeedsImmInc =
false;
3187#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3189 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3191 ? AArch64::CBB##RegCond##Wrr \
3192 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3193 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3194 : AArch64::CB##RegCond##Xrr))))
3210 NeedsImmDec = IsImm;
3214 NeedsRegSwap = !IsImm;
3221 NeedsRegSwap = !IsImm;
3222 NeedsImmInc = IsImm;
3226 NeedsImmDec = IsImm;
3230 NeedsRegSwap = !IsImm;
3237 NeedsRegSwap = !IsImm;
3238 NeedsImmInc = IsImm;
3246 MCOperand Lhs, Rhs, Trgt;
3247 lowerOperand(
MI->getOperand(1), Lhs);
3248 lowerOperand(
MI->getOperand(2), Rhs);
3249 lowerOperand(
MI->getOperand(3), Trgt);
3253 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3254 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3257 }
else if (NeedsImmDec) {
3261 }
else if (NeedsImmInc) {
3271 "CB immediate operand out-of-bounds");
3274 EmitToStreamer(*OutStreamer, Inst);
3277void AArch64AsmPrinter::emitAtomicHintPseudoExpansion(
const MachineInstr *
MI) {
3280 unsigned Relaxed =
MI->getOperand(2).getImm();
3281 assert(
Relaxed < 2 &&
"Atomic hint relaxed immediate out-of-bounds");
3282 switch (
MI->getOpcode()) {
3283 case AArch64::ATOMIC_STORE_HINT_B:
3284 StOpc =
Relaxed ? AArch64::STRBBui : AArch64::STLRB;
3286 case AArch64::ATOMIC_STORE_HINT_H:
3287 StOpc =
Relaxed ? AArch64::STRHHui : AArch64::STLRH;
3289 case AArch64::ATOMIC_STORE_HINT_W:
3290 StOpc =
Relaxed ? AArch64::STRWui : AArch64::STLRW;
3292 case AArch64::ATOMIC_STORE_HINT_X:
3293 StOpc =
Relaxed ? AArch64::STRXui : AArch64::STLRX;
3300 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(3).getImm()));
3303 Store.setOpcode(StOpc);
3306 Store.setFlags(
MI->getFlags());
3309 EmitToStreamer(*OutStreamer,
Store);
3312void AArch64AsmPrinter::emitAtomicHintPseudoExpansionRO(
3313 const MachineInstr *
MI) {
3315 assert(
MI->getOperand(5).getImm() == 1 &&
3316 "Atomic store addressing mode only supports relaxed stores");
3318 switch (
MI->getOpcode()) {
3319 case AArch64::ATOMIC_STORE_HINT_BroW:
3320 StOpc = AArch64::STRBBroW;
3322 case AArch64::ATOMIC_STORE_HINT_HroW:
3323 StOpc = AArch64::STRHHroW;
3325 case AArch64::ATOMIC_STORE_HINT_WroW:
3326 StOpc = AArch64::STRWroW;
3328 case AArch64::ATOMIC_STORE_HINT_XroW:
3329 StOpc = AArch64::STRXroW;
3331 case AArch64::ATOMIC_STORE_HINT_SroW:
3332 StOpc = AArch64::STRSroW;
3334 case AArch64::ATOMIC_STORE_HINT_DroW:
3335 StOpc = AArch64::STRDroW;
3337 case AArch64::ATOMIC_STORE_HINT_BroX:
3338 StOpc = AArch64::STRBBroX;
3340 case AArch64::ATOMIC_STORE_HINT_HroX:
3341 StOpc = AArch64::STRHHroX;
3343 case AArch64::ATOMIC_STORE_HINT_WroX:
3344 StOpc = AArch64::STRWroX;
3346 case AArch64::ATOMIC_STORE_HINT_XroX:
3347 StOpc = AArch64::STRXroX;
3349 case AArch64::ATOMIC_STORE_HINT_SroX:
3350 StOpc = AArch64::STRSroX;
3352 case AArch64::ATOMIC_STORE_HINT_DroX:
3353 StOpc = AArch64::STRDroX;
3360 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(6).getImm()));
3363 Store.setOpcode(StOpc);
3369 Store.setFlags(
MI->getFlags());
3370 EmitToStreamer(*OutStreamer,
Store);
3373void AArch64AsmPrinter::emitAtomicHintPseudoExpansionImm(
3374 const MachineInstr *
MI) {
3376 assert(
MI->getOperand(3).getImm() == 1 &&
3377 "Atomic store addressing mode only supports relaxed stores");
3379 switch (
MI->getOpcode()) {
3380 case AArch64::ATOMIC_STORE_HINT_Bui:
3381 StOpc = AArch64::STRBBui;
3383 case AArch64::ATOMIC_STORE_HINT_Hui:
3384 StOpc = AArch64::STRHHui;
3386 case AArch64::ATOMIC_STORE_HINT_Wui:
3387 StOpc = AArch64::STRWui;
3389 case AArch64::ATOMIC_STORE_HINT_Xui:
3390 StOpc = AArch64::STRXui;
3392 case AArch64::ATOMIC_STORE_HINT_Sui:
3393 StOpc = AArch64::STRSui;
3395 case AArch64::ATOMIC_STORE_HINT_Dui:
3396 StOpc = AArch64::STRDui;
3398 case AArch64::ATOMIC_STORE_HINT_Bi:
3399 StOpc = AArch64::STURBBi;
3401 case AArch64::ATOMIC_STORE_HINT_Hi:
3402 StOpc = AArch64::STURHHi;
3404 case AArch64::ATOMIC_STORE_HINT_Wi:
3405 StOpc = AArch64::STURWi;
3407 case AArch64::ATOMIC_STORE_HINT_Xi:
3408 StOpc = AArch64::STURXi;
3410 case AArch64::ATOMIC_STORE_HINT_Si:
3411 StOpc = AArch64::STURSi;
3413 case AArch64::ATOMIC_STORE_HINT_Di:
3414 StOpc = AArch64::STURDi;
3421 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(4).getImm()));
3424 Store.setOpcode(StOpc);
3428 Store.setFlags(
MI->getFlags());
3429 EmitToStreamer(*OutStreamer,
Store);
3432void AArch64AsmPrinter::emitAtomicFetchHintPseudoExpansion(
3433 const MachineInstr *
MI) {
3435 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(4).getImm()));
3443 EmitToStreamer(*OutStreamer, Fetch);
3448#include "AArch64GenMCPseudoLowering.inc"
3450void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3457void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3458 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3463 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3468 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3469 EmitToStreamer(*OutStreamer, OutInst);
3473 if (
MI->getOpcode() == AArch64::ADRP) {
3474 for (
auto &Opd :
MI->operands()) {
3475 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3476 "swift_async_extendedFramePointerFlags") {
3477 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3484 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3486 LOHInstToLabel[
MI] = LOHLabel;
3490 AArch64TargetStreamer *TS =
3493 switch (
MI->getOpcode()) {
3496 "Unhandled tail call instruction");
3498 case AArch64::READ_REGISTER_GPR64:
3502 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
3503 .addReg(
MI->getOperand(0).getReg())
3504 .addReg(AArch64::XZR)
3505 .addReg(
MI->getOperand(1).getImm())
3508 case AArch64::READ_REGISTER_FPR64:
3510 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::FMOVDr)
3511 .addReg(
MI->getOperand(0).getReg())
3512 .addReg(
MI->getOperand(1).getImm()));
3514 case AArch64::HINT: {
3519 if (CurrentPatchableFunctionEntrySym &&
3520 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3522 int64_t
Imm =
MI->getOperand(0).getImm();
3523 if (
Imm == 32 ||
Imm == 34 ||
Imm == 36 ||
Imm == 38) {
3525 MCInstLowering.
Lower(
MI, Inst);
3526 EmitToStreamer(*OutStreamer, Inst);
3527 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3528 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3534 case AArch64::MOVMCSym: {
3535 Register DestReg =
MI->getOperand(0).getReg();
3536 const MachineOperand &MO_Sym =
MI->getOperand(1);
3537 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3538 MCOperand Hi_MCSym, Lo_MCSym;
3551 EmitToStreamer(*OutStreamer, MovZ);
3559 EmitToStreamer(*OutStreamer, MovK);
3562 case AArch64::MOVIv2d_ns:
3570 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3571 MI->getOperand(1).getImm() == 0) {
3573 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3576 EmitToStreamer(*OutStreamer, TmpInst);
3581 case AArch64::DBG_VALUE:
3582 case AArch64::DBG_VALUE_LIST:
3584 SmallString<128> TmpStr;
3585 raw_svector_ostream OS(TmpStr);
3586 PrintDebugValueComment(
MI, OS);
3591 case AArch64::EMITBKEY: {
3593 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3594 ExceptionHandlingType != ExceptionHandling::ARM)
3597 if (getFunctionCFISectionType(*MF) == CFISection::None)
3604 case AArch64::EMITMTETAGGED: {
3606 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3607 ExceptionHandlingType != ExceptionHandling::ARM)
3610 if (getFunctionCFISectionType(*MF) != CFISection::None)
3615 case AArch64::AUTx16x17: {
3617 const Register Scratch = AArch64::X17;
3619 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3621 MI->getOperand(1).getImm(),
MI->getOperand(2));
3623 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3624 std::nullopt,
MI->getDeactivationSymbol());
3628 case AArch64::AUTxMxN: {
3630 const Register Scratch =
MI->getOperand(1).getReg();
3632 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3634 MI->getOperand(4).getImm(),
MI->getOperand(5));
3636 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3637 std::nullopt,
MI->getDeactivationSymbol());
3641 case AArch64::AUTPAC: {
3643 const Register Scratch = AArch64::X17;
3645 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3647 MI->getOperand(1).getImm(),
MI->getOperand(2));
3649 auto SignSchema = PtrAuthSchema::CreateImmReg(
3651 MI->getOperand(4).getImm(),
MI->getOperand(5));
3653 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3654 std::nullopt,
MI->getDeactivationSymbol());
3658 case AArch64::AUTPCPAC: {
3659 auto AuthSchema = PtrAuthSchema::CreateRegReg(
3663 auto SignSchema = PtrAuthSchema::CreateImmReg(
3665 MI->getOperand(2).getImm(),
MI->getOperand(3));
3667 emitPtrauthAuthResign(AArch64::X17, AArch64::X16,
3668 AuthSchema, SignSchema, std::nullopt,
3669 MI->getDeactivationSymbol());
3673 case AArch64::AUTRELLOADPAC: {
3675 const Register Scratch = AArch64::X17;
3677 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3679 MI->getOperand(1).getImm(),
MI->getOperand(2));
3681 auto SignSchema = PtrAuthSchema::CreateImmReg(
3683 MI->getOperand(4).getImm(),
MI->getOperand(5));
3685 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3686 MI->getOperand(6).getImm(),
3687 MI->getDeactivationSymbol());
3693 emitPtrauthSign(
MI);
3696 case AArch64::LOADauthptrstatic:
3697 LowerLOADauthptrstatic(*
MI);
3700 case AArch64::LOADgotPAC:
3701 case AArch64::MOVaddrPAC:
3702 LowerMOVaddrPAC(*
MI);
3705 case AArch64::LOADgotAUTH:
3706 LowerLOADgotAUTH(*
MI);
3711 emitPtrauthBranch(
MI);
3717 case AArch64::AUTH_TCRETURN:
3718 case AArch64::AUTH_TCRETURN_BTI: {
3721 const uint64_t Disc =
MI->getOperand(3).getImm();
3723 Register AddrDisc =
MI->getOperand(4).getReg();
3725 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3727 emitPtrauthTailCallHardening(
MI);
3730 if (Callee == AddrDisc)
3737 bool AddrDiscIsImplicitDef =
3738 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3739 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3740 AddrDiscIsImplicitDef);
3741 emitBLRA(
false,
Key, Callee, DiscReg);
3745 case AArch64::TCRETURNri:
3746 case AArch64::TCRETURNrix16x17:
3747 case AArch64::TCRETURNrix17:
3748 case AArch64::TCRETURNrinotx16:
3749 case AArch64::TCRETURNriALL: {
3750 emitPtrauthTailCallHardening(
MI);
3752 recordIfImportCall(
MI);
3756 EmitToStreamer(*OutStreamer, TmpInst);
3759 case AArch64::TCRETURNdi: {
3760 emitPtrauthTailCallHardening(
MI);
3764 recordIfImportCall(
MI);
3768 EmitToStreamer(*OutStreamer, TmpInst);
3771 case AArch64::SpeculationBarrierISBDSBEndBB: {
3776 EmitToStreamer(*OutStreamer, TmpInstDSB);
3780 EmitToStreamer(*OutStreamer, TmpInstISB);
3783 case AArch64::SpeculationBarrierSBEndBB: {
3787 EmitToStreamer(*OutStreamer, TmpInstSB);
3790 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3798 const MachineOperand &MO_Sym =
MI->getOperand(0);
3799 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3800 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3804 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3811 EmitToStreamer(*OutStreamer, Adrp);
3819 EmitToStreamer(*OutStreamer, Ldr);
3822 Add.setOpcode(AArch64::ADDXri);
3825 Add.addOperand(SymTLSDescLo12);
3827 EmitToStreamer(*OutStreamer,
Add);
3831 MCInst TLSAuthDescCall;
3832 TLSAuthDescCall.
setOpcode(AArch64::TLSAUTHDESCCALL);
3834 EmitToStreamer(*OutStreamer, TLSAuthDescCall);
3843 EmitToStreamer(*OutStreamer, Blraa);
3847 case AArch64::TLSDESC_CALLSEQ: {
3855 const MachineOperand &MO_Sym =
MI->getOperand(0);
3856 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3857 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3861 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3868 EmitToStreamer(*OutStreamer, Adrp);
3871 if (STI->isTargetILP32()) {
3881 EmitToStreamer(*OutStreamer, Ldr);
3884 if (STI->isTargetILP32()) {
3885 Add.setOpcode(AArch64::ADDWri);
3889 Add.setOpcode(AArch64::ADDXri);
3893 Add.addOperand(SymTLSDescLo12);
3895 EmitToStreamer(*OutStreamer,
Add);
3900 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3902 EmitToStreamer(*OutStreamer, TLSDescCall);
3910 EmitToStreamer(*OutStreamer, Blr);
3915 case AArch64::JumpTableDest32:
3916 case AArch64::JumpTableDest16:
3917 case AArch64::JumpTableDest8:
3918 LowerJumpTableDest(*OutStreamer, *
MI);
3921 case AArch64::BR_JumpTable:
3922 LowerHardenedBRJumpTable(*
MI);
3925 case AArch64::FMOVH0:
3926 case AArch64::FMOVS0:
3927 case AArch64::FMOVD0:
3931 case AArch64::MOPSMemoryCopyPseudo:
3932 case AArch64::MOPSMemoryMovePseudo:
3933 case AArch64::MOPSMemorySetPseudo:
3934 case AArch64::MOPSMemorySetTaggingPseudo:
3935 LowerMOPS(*OutStreamer, *
MI);
3938 case TargetOpcode::STACKMAP:
3939 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3941 case TargetOpcode::PATCHPOINT:
3942 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3944 case TargetOpcode::STATEPOINT:
3945 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3947 case TargetOpcode::FAULTING_OP:
3948 return LowerFAULTING_OP(*
MI);
3950 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3951 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3954 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3955 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3958 case TargetOpcode::PATCHABLE_TAIL_CALL:
3959 LowerPATCHABLE_TAIL_CALL(*
MI);
3961 case TargetOpcode::PATCHABLE_EVENT_CALL:
3962 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3963 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3964 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3966 case AArch64::KCFI_CHECK:
3967 LowerKCFI_CHECK(*
MI);
3970 case AArch64::HWASAN_CHECK_MEMACCESS:
3971 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3972 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3973 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3974 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3977 case AArch64::SEH_StackAlloc:
3981 case AArch64::SEH_SaveFPLR:
3985 case AArch64::SEH_SaveFPLR_X:
3986 assert(
MI->getOperand(0).getImm() < 0 &&
3987 "Pre increment SEH opcode must have a negative offset");
3991 case AArch64::SEH_SaveReg:
3993 MI->getOperand(1).getImm());
3996 case AArch64::SEH_SaveReg_X:
3997 assert(
MI->getOperand(1).getImm() < 0 &&
3998 "Pre increment SEH opcode must have a negative offset");
4000 -
MI->getOperand(1).getImm());
4003 case AArch64::SEH_SaveRegP:
4004 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
4005 MI->getOperand(0).getImm() <= 28) {
4006 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
4007 "Register paired with LR must be odd");
4009 MI->getOperand(2).getImm());
4012 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4013 "Non-consecutive registers not allowed for save_regp");
4015 MI->getOperand(2).getImm());
4018 case AArch64::SEH_SaveRegP_X:
4019 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4020 "Non-consecutive registers not allowed for save_regp_x");
4021 assert(
MI->getOperand(2).getImm() < 0 &&
4022 "Pre increment SEH opcode must have a negative offset");
4024 -
MI->getOperand(2).getImm());
4027 case AArch64::SEH_SaveFReg:
4029 MI->getOperand(1).getImm());
4032 case AArch64::SEH_SaveFReg_X:
4033 assert(
MI->getOperand(1).getImm() < 0 &&
4034 "Pre increment SEH opcode must have a negative offset");
4036 -
MI->getOperand(1).getImm());
4039 case AArch64::SEH_SaveFRegP:
4040 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4041 "Non-consecutive registers not allowed for save_regp");
4043 MI->getOperand(2).getImm());
4046 case AArch64::SEH_SaveFRegP_X:
4047 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4048 "Non-consecutive registers not allowed for save_regp_x");
4049 assert(
MI->getOperand(2).getImm() < 0 &&
4050 "Pre increment SEH opcode must have a negative offset");
4052 -
MI->getOperand(2).getImm());
4055 case AArch64::SEH_SetFP:
4059 case AArch64::SEH_AddFP:
4063 case AArch64::SEH_Nop:
4067 case AArch64::SEH_PrologEnd:
4071 case AArch64::SEH_EpilogStart:
4075 case AArch64::SEH_EpilogEnd:
4079 case AArch64::SEH_PACSignLR:
4083 case AArch64::SEH_SaveAnyRegI:
4084 assert(
MI->getOperand(1).getImm() <= 1008 &&
4085 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4087 MI->getOperand(1).getImm());
4090 case AArch64::SEH_SaveAnyRegIP:
4091 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4092 "Non-consecutive registers not allowed for save_any_reg");
4093 assert(
MI->getOperand(2).getImm() <= 1008 &&
4094 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4096 MI->getOperand(2).getImm());
4099 case AArch64::SEH_SaveAnyRegQP:
4100 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4101 "Non-consecutive registers not allowed for save_any_reg");
4102 assert(
MI->getOperand(2).getImm() >= 0 &&
4103 "SaveAnyRegQP SEH opcode offset must be non-negative");
4104 assert(
MI->getOperand(2).getImm() <= 1008 &&
4105 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4107 MI->getOperand(2).getImm());
4110 case AArch64::SEH_SaveAnyRegQPX:
4111 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4112 "Non-consecutive registers not allowed for save_any_reg");
4113 assert(
MI->getOperand(2).getImm() < 0 &&
4114 "SaveAnyRegQPX SEH opcode offset must be negative");
4115 assert(
MI->getOperand(2).getImm() >= -1008 &&
4116 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
4118 -
MI->getOperand(2).getImm());
4121 case AArch64::SEH_AllocZ:
4122 assert(
MI->getOperand(0).getImm() >= 0 &&
4123 "AllocZ SEH opcode offset must be non-negative");
4124 assert(
MI->getOperand(0).getImm() <= 255 &&
4125 "AllocZ SEH opcode offset must fit into 8 bits");
4129 case AArch64::SEH_SaveZReg:
4130 assert(
MI->getOperand(1).getImm() >= 0 &&
4131 "SaveZReg SEH opcode offset must be non-negative");
4132 assert(
MI->getOperand(1).getImm() <= 255 &&
4133 "SaveZReg SEH opcode offset must fit into 8 bits");
4135 MI->getOperand(1).getImm());
4138 case AArch64::SEH_SavePReg:
4139 assert(
MI->getOperand(1).getImm() >= 0 &&
4140 "SavePReg SEH opcode offset must be non-negative");
4141 assert(
MI->getOperand(1).getImm() <= 255 &&
4142 "SavePReg SEH opcode offset must fit into 8 bits");
4144 MI->getOperand(1).getImm());
4149 recordIfImportCall(
MI);
4151 MCInstLowering.
Lower(
MI, TmpInst);
4152 EmitToStreamer(*OutStreamer, TmpInst);
4155 case AArch64::CBWPri:
4156 case AArch64::CBXPri:
4157 case AArch64::CBBAssertExt:
4158 case AArch64::CBHAssertExt:
4159 case AArch64::CBWPrr:
4160 case AArch64::CBXPrr:
4161 emitCBPseudoExpansion(
MI);
4163 case AArch64::ATOMIC_STORE_HINT_B:
4164 case AArch64::ATOMIC_STORE_HINT_H:
4165 case AArch64::ATOMIC_STORE_HINT_W:
4166 case AArch64::ATOMIC_STORE_HINT_X:
4167 emitAtomicHintPseudoExpansion(
MI);
4169 case AArch64::ATOMIC_FETCH_HINT_W:
4170 case AArch64::ATOMIC_FETCH_HINT_X:
4171 emitAtomicFetchHintPseudoExpansion(
MI);
4173 case AArch64::ATOMIC_STORE_HINT_BroW:
4174 case AArch64::ATOMIC_STORE_HINT_HroW:
4175 case AArch64::ATOMIC_STORE_HINT_WroW:
4176 case AArch64::ATOMIC_STORE_HINT_XroW:
4177 case AArch64::ATOMIC_STORE_HINT_SroW:
4178 case AArch64::ATOMIC_STORE_HINT_DroW:
4179 case AArch64::ATOMIC_STORE_HINT_BroX:
4180 case AArch64::ATOMIC_STORE_HINT_HroX:
4181 case AArch64::ATOMIC_STORE_HINT_WroX:
4182 case AArch64::ATOMIC_STORE_HINT_XroX:
4183 case AArch64::ATOMIC_STORE_HINT_SroX:
4184 case AArch64::ATOMIC_STORE_HINT_DroX:
4185 emitAtomicHintPseudoExpansionRO(
MI);
4187 case AArch64::ATOMIC_STORE_HINT_Bui:
4188 case AArch64::ATOMIC_STORE_HINT_Hui:
4189 case AArch64::ATOMIC_STORE_HINT_Wui:
4190 case AArch64::ATOMIC_STORE_HINT_Xui:
4191 case AArch64::ATOMIC_STORE_HINT_Sui:
4192 case AArch64::ATOMIC_STORE_HINT_Dui:
4193 case AArch64::ATOMIC_STORE_HINT_Bi:
4194 case AArch64::ATOMIC_STORE_HINT_Hi:
4195 case AArch64::ATOMIC_STORE_HINT_Wi:
4196 case AArch64::ATOMIC_STORE_HINT_Xi:
4197 case AArch64::ATOMIC_STORE_HINT_Si:
4198 case AArch64::ATOMIC_STORE_HINT_Di:
4199 emitAtomicHintPseudoExpansionImm(
MI);
4203 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
4208 MCInstLowering.
Lower(
MI, TmpInst);
4209 EmitToStreamer(*OutStreamer, TmpInst);
4212void AArch64AsmPrinter::recordIfImportCall(
4213 const llvm::MachineInstr *BranchInst) {
4214 if (!EnableImportCallOptimization)
4218 if (GV && GV->hasDLLImportStorageClass()) {
4219 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
4224 .push_back({CallSiteSymbol, CalledSymbol});
4228void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
4229 MCSymbol *LazyPointer) {
4246 EmitToStreamer(Adrp);
4254 MCOperand SymPageOff;
4261 EmitToStreamer(Ldr);
4264 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
4265 .addReg(AArch64::X16)
4266 .addReg(AArch64::X16)
4269 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4271 .addReg(AArch64::X16));
4274void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
4275 const GlobalIFunc &GI,
4276 MCSymbol *LazyPointer) {
4308 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4309 .addReg(AArch64::SP)
4310 .addReg(AArch64::FP)
4311 .addReg(AArch64::LR)
4312 .addReg(AArch64::SP)
4315 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4316 .addReg(AArch64::FP)
4317 .addReg(AArch64::SP)
4321 for (
int I = 0;
I != 4; ++
I)
4322 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4323 .addReg(AArch64::SP)
4324 .addReg(AArch64::X1 + 2 *
I)
4325 .addReg(AArch64::X0 + 2 *
I)
4326 .addReg(AArch64::SP)
4329 for (
int I = 0;
I != 4; ++
I)
4330 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
4331 .addReg(AArch64::SP)
4332 .addReg(AArch64::D1 + 2 *
I)
4333 .addReg(AArch64::D0 + 2 *
I)
4334 .addReg(AArch64::SP)
4338 MCInstBuilder(AArch64::BL)
4351 EmitToStreamer(Adrp);
4359 MCOperand SymPageOff;
4366 EmitToStreamer(Ldr);
4369 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
4370 .addReg(AArch64::X0)
4371 .addReg(AArch64::X16)
4374 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4375 .addReg(AArch64::X16)
4376 .addReg(AArch64::X0)
4380 for (
int I = 3;
I != -1; --
I)
4381 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
4382 .addReg(AArch64::SP)
4383 .addReg(AArch64::D1 + 2 *
I)
4384 .addReg(AArch64::D0 + 2 *
I)
4385 .addReg(AArch64::SP)
4388 for (
int I = 3;
I != -1; --
I)
4389 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4390 .addReg(AArch64::SP)
4391 .addReg(AArch64::X1 + 2 *
I)
4392 .addReg(AArch64::X0 + 2 *
I)
4393 .addReg(AArch64::SP)
4396 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4397 .addReg(AArch64::SP)
4398 .addReg(AArch64::FP)
4399 .addReg(AArch64::LR)
4400 .addReg(AArch64::SP)
4403 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4405 .addReg(AArch64::X16));
4408const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4409 const Constant *BaseCV,
4419char AArch64AsmPrinter::ID = 0;
4422 "AArch64 Assembly Printer",
false,
false)
4426LLVMInitializeAArch64AsmPrinter() {
4436 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4446 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4457 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond)
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
static bool getOptionalBooleanModuleFlag(Module &M, StringRef Name)
static bool targetSupportsIRelativeRelocation(const Triple &TT)
static PtrauthCheckMode getCheckMode(const MachineFunction *MF)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
std::unique_ptr< MCStreamer > && Streamer
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool printAsmMRegister(const X86AsmPrinter &P, const MachineInstr &MI, const MachineOperand &MO, char Mode, raw_ostream &O)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static const AArch64AuthMCExpr * create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, bool HasAddressDiversity, MCContext &Ctx, SMLoc Loc=SMLoc())
const SetOfInstructions & getLOHRelated() const
unsigned getJumpTableEntrySize(int Idx) const
MCSymbol * getJumpTableEntryPCRelSymbol(int Idx) const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
std::optional< std::string > getOutliningStyle() const
const MILOHContainer & getLOHContainer() const
void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym)
bool shouldSignWithBKey() const
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MCSymbol * GetGlobalValueSymbol(const GlobalValue *GV, unsigned TargetFlags) const
void Lower(const MachineInstr *MI, MCInst &OutMI) const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
const AArch64Options & getCLOpts() const
virtual void emitARM64WinCFISaveRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset)
virtual void emitAttributesSubsection(StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, AArch64BuildAttributes::SubsectionType ParameterType)
Build attributes implementation.
virtual void emitARM64WinCFISavePReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPACSignLR()
virtual void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFIAllocStack(unsigned Size)
virtual void emitARM64WinCFISaveFPLRX(int Offset)
virtual void emitARM64WinCFIAllocZ(int Offset)
virtual void emitDirectiveVariantPCS(MCSymbol *Symbol)
Callback used to implement the .variant_pcs directive.
virtual void emitARM64WinCFIAddFP(unsigned Size)
virtual void emitARM64WinCFISaveFPLR(int Offset)
virtual void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISetFP()
virtual void emitARM64WinCFIEpilogEnd()
virtual void emitARM64WinCFISaveZReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPrologEnd()
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFINop()
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
virtual void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, std::string String)
virtual void emitARM64WinCFIEpilogStart()
virtual void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
void setPreservesAll()
Set by analyses that do not transform their input at all.
const T & front() const
Get the first element.
bool empty() const
Check if the array is empty.
This class is intended to be used as a driving class for all asm writers.
virtual void emitGlobalAlias(const Module &M, const GlobalAlias &GA)
virtual void emitBasicBlockEnd(const MachineBasicBlock &MBB)
Targets can override this to emit stuff at the end of a basic block.
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
virtual const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
virtual void emitXXStructor(const DataLayout &DL, const Constant *CV)
Targets can override this to change how global constants that are part of a C++ static/global constru...
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
virtual const MCExpr * lowerBlockAddressConstant(const BlockAddress &BA)
Lower the specified BlockAddress to an MCExpr.
Function * getFunction() const
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
@ AddrDiscriminator_CtorsDtors
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
static LLVM_ABI ConstantPtrAuth * get(Constant *Ptr, ConstantInt *Key, ConstantInt *Disc, Constant *AddrDisc, Constant *DeactivationSymbol)
Return a pointer signed with the specified parameters.
ConstantInt * getKey() const
The Key ID, an i32 constant.
Constant * getDeactivationSymbol() const
bool hasAddressDiscriminator() const
Whether there is any non-null address discriminator.
ConstantInt * getDiscriminator() const
The integer discriminator, an i64 constant, or 0.
LLVM_ABI void recordFaultingOp(FaultKind FaultTy, const MCSymbol *FaultingLabel, const MCSymbol *HandlerLabel)
LLVM_ABI void serializeToFaultMapSection()
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const Constant * getAliasee() const
const Constant * getResolver() const
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
bool hasLocalLinkage() const
bool hasExternalWeakLinkage() const
Type * getValueType() const
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
LLVM_ABI MCSymbol * createLinkerPrivateSymbol(const Twine &Name)
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
void setFlags(unsigned F)
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
MCSection * getDataSection() const
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
static constexpr unsigned NonUniqueID
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
virtual void emitCFIBKeyFrame()
virtual bool popSection()
Restore the current and previous section from the section stack.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc={})
Record a relocation described by the .reloc directive.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCFIMTETaggedFrame()
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
void pushSection()
Save the current and previous section on the section stack.
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
MCSection * getCurrentSectionOnly() const
void emitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ....
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
const MCSymbol * getAddSym() const
int64_t getConstant() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
CalledGlobalInfo tryGetCalledGlobal(const MachineInstr *MI) const
Tries to get the global and target flags for a call site, if the instruction is a call to a global.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
bool usesWindowsUnwindInfo() const
True if this function describes its unwind information with Windows SEH unwind opcodes (....
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.
self_iterator getIterator()
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI StringRef getVendorName(unsigned const Vendor)
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
PtrauthCheckMode
Ways to check pointer authentication auth/resign failures.
constexpr AArch64PACKey::ID InitFiniKey
PAuth key to be used with function pointers in .init_array and .fini_array.
AuthCheckMethod
Variants of check performed on an authenticated pointer.
constexpr unsigned InitFiniPointerConstantDiscriminator
Constant discriminator to be used with function pointers in .init_array and .fini_array.
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
SymbolStorageClass
Storage class tells where and what the symbol represents.
@ IMAGE_SYM_CLASS_EXTERNAL
External symbol.
@ IMAGE_SYM_CLASS_STATIC
Static.
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
@ SCT_COMPLEX_TYPE_SHIFT
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
@ AARCH64_PAUTH_PLATFORM_LLVM_LINUX
@ GNU_PROPERTY_AARCH64_FEATURE_1_BTI
@ GNU_PROPERTY_AARCH64_FEATURE_1_PAC
@ GNU_PROPERTY_AARCH64_FEATURE_1_GCS
@ S_REGULAR
S_REGULAR - Regular section.
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI std::optional< std::string > getArm64ECMangledFunctionName(StringRef Name)
Returns the ARM64EC mangled function name unless the input is already mangled.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
scope_exit(Callable) -> scope_exit< Callable >
@ Store
The extracted value is stored (ExtractElement only).
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
std::string utostr(uint64_t X, bool isNeg=false)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
static unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K, bool Zero)
Return B(L)RA opcode to be used for an authenticated branch or call using the given key,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Target & getTheAArch64leTarget()
auto dyn_cast_or_null(const Y &Val)
Target & getTheAArch64_32Target()
auto reverse(ContainerTy &&C)
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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,...