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->isDebugInstr()) {
1815 if (MII ==
MBB.
end() || MII->isCall() ||
1816 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1817 MII->getOpcode() == TargetOpcode::STACKMAP)
1824 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1825 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1830void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1831 const MachineInstr &
MI) {
1833 MCSymbol *MILabel = Ctx.createTempSymbol();
1837 PatchPointOpers Opers(&
MI);
1839 int64_t CallTarget = Opers.getCallTarget().getImm();
1840 unsigned EncodedBytes = 0;
1842 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1843 "High 16 bits of call target should be zero.");
1844 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1847 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1848 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1849 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1850 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1853 unsigned NumBytes = Opers.getNumPatchBytes();
1854 assert(NumBytes >= EncodedBytes &&
1855 "Patchpoint can't request size less than the length of a call.");
1856 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1857 "Invalid number of NOP bytes requested!");
1858 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1859 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1862void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1863 const MachineInstr &
MI) {
1864 StatepointOpers SOpers(&
MI);
1865 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1866 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1867 for (
unsigned i = 0; i < PatchBytes; i += 4)
1868 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1871 const MachineOperand &CallTarget = SOpers.getCallTarget();
1872 MCOperand CallTargetMCOp;
1873 unsigned CallOpcode;
1874 switch (CallTarget.
getType()) {
1877 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1878 CallOpcode = AArch64::BL;
1882 CallOpcode = AArch64::BL;
1886 CallOpcode = AArch64::BLR;
1893 EmitToStreamer(OutStreamer,
1894 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1898 MCSymbol *MILabel = Ctx.createTempSymbol();
1903void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1912 unsigned OperandsBeginIdx = 4;
1915 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1922 MI.setOpcode(Opcode);
1927 for (
const MachineOperand &MO :
1930 lowerOperand(MO, Dest);
1931 MI.addOperand(Dest);
1939 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1941 .addReg(AArch64::XZR)
1947 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1948 EmitToStreamer(*OutStreamer,
1949 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1956 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1957 EmitToStreamer(*OutStreamer,
1958 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1967 bool IsZeroDisc = Disc == AArch64::XZR;
1979 EmitToStreamer(AUTInst);
1984 bool IsZeroDisc = Disc == AArch64::XZR;
1996 EmitToStreamer(PACInst);
2001 bool IsZeroDisc = Disc == AArch64::XZR;
2011 EmitToStreamer(Inst);
2014void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
2015 Register DestReg =
MI.getOperand(0).getReg();
2016 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
2017 if (STI->hasZeroCycleZeroingFPR64()) {
2019 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2020 if (AArch64::FPR16RegClass.
contains(DestReg))
2021 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2022 &AArch64::FPR64RegClass);
2023 else if (AArch64::FPR32RegClass.
contains(DestReg))
2024 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2025 &AArch64::FPR64RegClass);
2033 EmitToStreamer(*OutStreamer, MOVI);
2034 ++NumZCZeroingInstrsFPR;
2035 }
else if (STI->hasZeroCycleZeroingFPR128()) {
2037 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2038 if (AArch64::FPR16RegClass.
contains(DestReg)) {
2039 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2040 &AArch64::FPR128RegClass);
2041 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
2042 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2043 &AArch64::FPR128RegClass);
2046 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
2047 &AArch64::FPR128RegClass);
2054 EmitToStreamer(*OutStreamer, MOVI);
2055 ++NumZCZeroingInstrsFPR;
2057 emitFMov0AsFMov(
MI, DestReg);
2060 emitFMov0AsFMov(
MI, DestReg);
2064void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
2067 switch (
MI.getOpcode()) {
2070 case AArch64::FMOVH0:
2071 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
2072 if (!STI->hasFullFP16())
2073 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
2077 case AArch64::FMOVS0:
2082 case AArch64::FMOVD0:
2088 EmitToStreamer(*OutStreamer, FMov);
2094 bool MayClobberAddrDisc) {
2095 assert(isPtrauthRegSafe(ScratchReg) &&
2096 "Safe scratch register must be provided by the caller");
2101 AddrDisc = AArch64::XZR;
2109 if (AddrDisc == AArch64::XZR) {
2110 emitMOVZ(ScratchReg, Disc, 0);
2117 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2118 ScratchReg = AddrDisc;
2120 emitMovXReg(ScratchReg, AddrDisc);
2121 assert(ScratchReg != AddrDisc &&
2122 "Forbidden to clobber AddrDisc, but have to");
2125 emitMOVK(ScratchReg, Disc, 48);
2139void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2171 if (Method == AuthCheckMethod::None)
2173 if (Method == AuthCheckMethod::DummyLoad) {
2174 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2178 assert(!OnFailure &&
"DummyLoad always traps on error");
2182 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2183 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2185 emitMovXReg(ScratchReg, TestedReg);
2187 if (Method == AuthCheckMethod::XPAC) {
2191 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2196 assert(TestedReg == AArch64::LR &&
2197 "XPACHint mode is only compatible with checking the LR register");
2199 "XPACHint mode is only compatible with I-keys");
2200 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2204 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2205 .addReg(AArch64::XZR)
2212 MCInstBuilder(AArch64::Bcc)
2215 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2217 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2224 MCInstBuilder(AArch64::TBZX)
2235 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2249 case AuthCheckMethod::XPACHint:
2252 case AuthCheckMethod::XPAC:
2254 emitMovXReg(TestedReg, ScratchReg);
2261 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2266 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2278void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2282 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2283 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2286 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2290 "Neither x16 nor x17 is available as a scratch register");
2293 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2297bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2303 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2306 MCSymbol *Dot = OutContext.createTempSymbol();
2311 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2317AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateImmReg(
2319 PtrAuthSchema Schema;
2321 Schema.IntDisc = IntDisc;
2322 Schema.AddrDisc = AddrDiscOp.
getReg();
2323 Schema.AddrDiscIsKilled = AddrDiscOp.
isKill();
2328AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateRegReg(
2330 assert(PCDisc.
isValid() &&
"Use CreateImmReg for non-PC schemas");
2331 PtrAuthSchema Schema;
2334 Schema.AddrDisc = AddrDisc;
2335 Schema.AddrDiscIsKilled =
false;
2336 Schema.PCDisc = PCDisc;
2340void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2345 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2355 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2357 MCInstBuilder(AArch64::ADDXri)
2360 .addImm((Addend >> BitPos) & 0xfff)
2366 emitMOVZ(Scratch, Addend & 0xffff, 0);
2373 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2380 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2386 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2397 if (std::optional<PtrauthCheckMode>
Mode =
2404 return PtrauthCheckMode::Unchecked;
2407 return ShouldTrap ? PtrauthCheckMode::Trap : PtrauthCheckMode::Poison;
2438void AArch64AsmPrinter::emitPtrauthAuthResign(
2440 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2443 const bool IsAuthWithPC = AuthSchema.PCDisc.isValid();
2444 assert(!SignSchema || !SignSchema->PCDisc.isValid());
2446 Register SignAddrDiscOrNone = SignSchema ? SignSchema->AddrDisc :
Register();
2452 assert(Pointer == AArch64::X17 && Scratch == AArch64::X16 &&
2453 "AUTPCPAC must use x17/x16 as Pointer/Scratch");
2455 assert(AuthSchema.AddrDisc == AArch64::X16 &&
2456 "AUTPCPAC requires address discriminator in X16");
2458 assert(AuthSchema.PCDisc == AArch64::X15 &&
2459 "AUTPCPAC requires PC discriminator in X15");
2461 assert(AuthSchema.IntDisc == 0 &&
"AUTPCPAC does not support IntDisc");
2465 "AUTPCPAC only supports AUT-ing with IA/IB");
2467 if (!emitDeactivationSymbolRelocation(DS)) {
2469 ? AArch64::AUTIB171615
2470 : AArch64::AUTIA171615;
2471 EmitToStreamer(MCInstBuilder(AutOpc));
2481 Register AUTDiscReg = emitPtrauthDiscriminator(
2482 AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2483 AuthSchema.addrDiscIsKilledAndNoneOf({Pointer, SignAddrDiscOrNone}));
2484 if (!emitDeactivationSymbolRelocation(DS))
2485 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2490 auto EmitCheck = [&](
MCSymbol *OnFailure =
nullptr) {
2491 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2492 AArch64PAuth::AuthCheckMethod::XPAC,
2496 auto EmitResignOnSuccess = [&]() {
2497 if (Addend.has_value())
2498 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2500 assert(Pointer != SignSchema->AddrDisc &&
"Pointer is early-clobbered");
2502 emitPtrauthDiscriminator(SignSchema->IntDisc, SignSchema->AddrDisc,
2503 Scratch, SignSchema->AddrDiscIsKilled);
2504 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2510 if (CheckMode == PtrauthCheckMode::Trap)
2516 switch (CheckMode) {
2517 case PtrauthCheckMode::Unchecked:
2518 EmitResignOnSuccess();
2520 case PtrauthCheckMode::Trap:
2522 EmitResignOnSuccess();
2524 case PtrauthCheckMode::Poison:
2525 MCSymbol *OnFailure = createTempSymbol(
"resign_end_");
2526 EmitCheck(OnFailure);
2527 EmitResignOnSuccess();
2533void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2537 Register AddrDisc =
MI->getOperand(4).getReg();
2538 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2542 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2543 assert(ScratchReg != AddrDisc &&
2544 "Neither X16 nor X17 is available as a scratch register");
2547 Register DiscReg = emitPtrauthDiscriminator(
2548 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2550 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2553 emitPAC(
Key, Val, DiscReg);
2556void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2557 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2558 unsigned BrTarget =
MI->getOperand(0).getReg();
2563 unsigned AddrDisc =
MI->getOperand(3).getReg();
2569 if (BrTarget == AddrDisc)
2586 bool AddrDiscIsImplicitDef =
2587 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2588 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2589 AddrDiscIsImplicitDef);
2590 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2593void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2597 const bool IsNeg = Addend < 0;
2599 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2602 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2605 .addImm((AbsOffset >> BitPos) & 0xfff)
2610 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2612 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2614 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2615 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2616 uint64_t Shifted = UAddend >> BitPos;
2618 return Shifted != 0;
2619 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2620 if (((Shifted >>
I) & 0xffff) != 0xffff)
2624 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2625 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2627 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2636void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2637 MCRegister Tmp,
bool DSOLocal,
2638 const MCSubtargetInfo &STI) {
2644 MCInstBuilder(AArch64::ADRP)
2648 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2658 MCInstBuilder(AArch64::ADRP)
2663 MCInstBuilder(AArch64::LDRXui)
2674 if (!TT.isOSBinFormatELF())
2678 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2679 TT.isOSDragonFly() || TT.isOSNetBSD();
2733const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2735 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2736 const Triple &
TT = TM.getTargetTriple();
2748 auto STI = std::make_unique<AArch64Subtarget>(
2749 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2751 this->STI = STI.get();
2757 const MCSymbolELF *Group =
2772 .addReg(AArch64::X0)
2777 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2779 if (HasAddressDiversity) {
2784 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2788 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2790 "' out of range [0, 0xFFFF]");
2792 emitMOVZ(AArch64::X1, Disc, 0);
2799 auto *PrePACInstExpr =
2811 const MCSymbolRefExpr *EmuPACRef =
2813 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2820 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2829AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2830 MCContext &Ctx = OutContext;
2835 getDataLayout(),
Offset,
true);
2855 const MCExpr *DSExpr =
nullptr;
2867 "' out of range [0, " +
2875 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2877 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2882 "' out of range [0, 0xFFFF]");
2888 "expressions on this target");
2895void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2896 unsigned DstReg =
MI.getOperand(0).getReg();
2897 const MachineOperand &GAOp =
MI.getOperand(1);
2898 const uint64_t KeyC =
MI.getOperand(2).getImm();
2900 "key is out of range [0, AArch64PACKey::LAST]");
2902 const uint64_t Disc =
MI.getOperand(3).getImm();
2904 "constant discriminator is out of range [0, 0xffff]");
2913 if (TM.getTargetTriple().isOSBinFormatELF()) {
2915 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2918 "non-zero offset for $auth_ptr$ stub slots is not supported");
2920 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2922 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2923 "LOADauthptrstatic is implemented only for MachO/ELF");
2925 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2926 getObjFileLowering());
2929 "non-zero offset for $auth_ptr$ stub slots is not supported");
2931 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2934 MachineOperand StubMOHi =
2938 MCOperand StubMCHi, StubMCLo;
2945 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2947 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2953void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2954 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2955 const bool IsELFSignedGOT =
MI.getParent()
2957 ->getInfo<AArch64FunctionInfo>()
2958 ->hasELFSignedGOT();
2959 MachineOperand GAOp =
MI.getOperand(0);
2960 const uint64_t KeyC =
MI.getOperand(1).getImm();
2962 "key is out of range [0, AArch64PACKey::LAST]");
2964 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2965 const uint64_t Disc =
MI.getOperand(3).getImm();
3012 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
3013 MCOperand GAMCHi, GAMCLo;
3026 MCInstBuilder(AArch64::ADRP)
3027 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
3031 if (IsELFSignedGOT) {
3032 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3033 .addReg(AArch64::X17)
3034 .addReg(AArch64::X17)
3038 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3039 .addReg(AArch64::X16)
3040 .addReg(AArch64::X17)
3048 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
3050 if (!STI->hasFPAC())
3051 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
3052 AArch64PAuth::AuthCheckMethod::XPAC);
3054 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3055 .addReg(AArch64::X16)
3056 .addReg(AArch64::X16)
3060 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3061 .addReg(AArch64::X16)
3062 .addReg(AArch64::X16)
3067 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
3068 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
3070 emitPAC(
Key, AArch64::X16, DiscReg);
3073void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
3075 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
3076 const MachineOperand &GAMO =
MI.getOperand(1);
3083 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
3084 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3085 .addReg(AuthResultReg)
3086 .addReg(AArch64::X17)
3089 MachineOperand GAHiOp(GAMO);
3090 MachineOperand GALoOp(GAMO);
3094 MCOperand GAMCHi, GAMCLo;
3099 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
3101 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3102 .addReg(AArch64::X17)
3103 .addReg(AArch64::X17)
3107 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3108 .addReg(AuthResultReg)
3109 .addReg(AArch64::X17)
3116 UndefWeakSym = createTempSymbol(
"undef_weak");
3118 MCInstBuilder(AArch64::CBZX)
3119 .addReg(AuthResultReg)
3127 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
3132 if (!STI->hasFPAC()) {
3133 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
3134 AArch64PAuth::AuthCheckMethod::XPAC);
3136 emitMovXReg(DstReg, AuthResultReg);
3141AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
3145 if (std::optional<uint16_t> BADisc =
3146 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3153void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3157 switch (
MI->getOpcode()) {
3160 case AArch64::CBBAssertExt:
3164 case AArch64::CBHAssertExt:
3168 case AArch64::CBWPrr:
3171 case AArch64::CBXPrr:
3174 case AArch64::CBWPri:
3178 case AArch64::CBXPri:
3186 bool NeedsRegSwap =
false;
3187 bool NeedsImmDec =
false;
3188 bool NeedsImmInc =
false;
3190#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3192 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3194 ? AArch64::CBB##RegCond##Wrr \
3195 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3196 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3197 : AArch64::CB##RegCond##Xrr))))
3213 NeedsImmDec = IsImm;
3217 NeedsRegSwap = !IsImm;
3224 NeedsRegSwap = !IsImm;
3225 NeedsImmInc = IsImm;
3229 NeedsImmDec = IsImm;
3233 NeedsRegSwap = !IsImm;
3240 NeedsRegSwap = !IsImm;
3241 NeedsImmInc = IsImm;
3249 MCOperand Lhs, Rhs, Trgt;
3250 lowerOperand(
MI->getOperand(1), Lhs);
3251 lowerOperand(
MI->getOperand(2), Rhs);
3252 lowerOperand(
MI->getOperand(3), Trgt);
3256 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3257 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3260 }
else if (NeedsImmDec) {
3264 }
else if (NeedsImmInc) {
3274 "CB immediate operand out-of-bounds");
3277 EmitToStreamer(*OutStreamer, Inst);
3280void AArch64AsmPrinter::emitAtomicHintPseudoExpansion(
const MachineInstr *
MI) {
3283 unsigned Relaxed =
MI->getOperand(2).getImm();
3284 assert(
Relaxed < 2 &&
"Atomic hint relaxed immediate out-of-bounds");
3285 switch (
MI->getOpcode()) {
3286 case AArch64::ATOMIC_STORE_HINT_B:
3287 StOpc =
Relaxed ? AArch64::STRBBui : AArch64::STLRB;
3289 case AArch64::ATOMIC_STORE_HINT_H:
3290 StOpc =
Relaxed ? AArch64::STRHHui : AArch64::STLRH;
3292 case AArch64::ATOMIC_STORE_HINT_W:
3293 StOpc =
Relaxed ? AArch64::STRWui : AArch64::STLRW;
3295 case AArch64::ATOMIC_STORE_HINT_X:
3296 StOpc =
Relaxed ? AArch64::STRXui : AArch64::STLRX;
3303 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(3).getImm()));
3306 Store.setOpcode(StOpc);
3309 Store.setFlags(
MI->getFlags());
3312 EmitToStreamer(*OutStreamer,
Store);
3315void AArch64AsmPrinter::emitAtomicHintPseudoExpansionRO(
3316 const MachineInstr *
MI) {
3318 assert(
MI->getOperand(5).getImm() == 1 &&
3319 "Atomic store addressing mode only supports relaxed stores");
3321 switch (
MI->getOpcode()) {
3322 case AArch64::ATOMIC_STORE_HINT_BroW:
3323 StOpc = AArch64::STRBBroW;
3325 case AArch64::ATOMIC_STORE_HINT_HroW:
3326 StOpc = AArch64::STRHHroW;
3328 case AArch64::ATOMIC_STORE_HINT_WroW:
3329 StOpc = AArch64::STRWroW;
3331 case AArch64::ATOMIC_STORE_HINT_XroW:
3332 StOpc = AArch64::STRXroW;
3334 case AArch64::ATOMIC_STORE_HINT_SroW:
3335 StOpc = AArch64::STRSroW;
3337 case AArch64::ATOMIC_STORE_HINT_DroW:
3338 StOpc = AArch64::STRDroW;
3340 case AArch64::ATOMIC_STORE_HINT_BroX:
3341 StOpc = AArch64::STRBBroX;
3343 case AArch64::ATOMIC_STORE_HINT_HroX:
3344 StOpc = AArch64::STRHHroX;
3346 case AArch64::ATOMIC_STORE_HINT_WroX:
3347 StOpc = AArch64::STRWroX;
3349 case AArch64::ATOMIC_STORE_HINT_XroX:
3350 StOpc = AArch64::STRXroX;
3352 case AArch64::ATOMIC_STORE_HINT_SroX:
3353 StOpc = AArch64::STRSroX;
3355 case AArch64::ATOMIC_STORE_HINT_DroX:
3356 StOpc = AArch64::STRDroX;
3363 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(6).getImm()));
3366 Store.setOpcode(StOpc);
3372 Store.setFlags(
MI->getFlags());
3373 EmitToStreamer(*OutStreamer,
Store);
3376void AArch64AsmPrinter::emitAtomicHintPseudoExpansionImm(
3377 const MachineInstr *
MI) {
3379 assert(
MI->getOperand(3).getImm() == 1 &&
3380 "Atomic store addressing mode only supports relaxed stores");
3382 switch (
MI->getOpcode()) {
3383 case AArch64::ATOMIC_STORE_HINT_Bui:
3384 StOpc = AArch64::STRBBui;
3386 case AArch64::ATOMIC_STORE_HINT_Hui:
3387 StOpc = AArch64::STRHHui;
3389 case AArch64::ATOMIC_STORE_HINT_Wui:
3390 StOpc = AArch64::STRWui;
3392 case AArch64::ATOMIC_STORE_HINT_Xui:
3393 StOpc = AArch64::STRXui;
3395 case AArch64::ATOMIC_STORE_HINT_Sui:
3396 StOpc = AArch64::STRSui;
3398 case AArch64::ATOMIC_STORE_HINT_Dui:
3399 StOpc = AArch64::STRDui;
3401 case AArch64::ATOMIC_STORE_HINT_Bi:
3402 StOpc = AArch64::STURBBi;
3404 case AArch64::ATOMIC_STORE_HINT_Hi:
3405 StOpc = AArch64::STURHHi;
3407 case AArch64::ATOMIC_STORE_HINT_Wi:
3408 StOpc = AArch64::STURWi;
3410 case AArch64::ATOMIC_STORE_HINT_Xi:
3411 StOpc = AArch64::STURXi;
3413 case AArch64::ATOMIC_STORE_HINT_Si:
3414 StOpc = AArch64::STURSi;
3416 case AArch64::ATOMIC_STORE_HINT_Di:
3417 StOpc = AArch64::STURDi;
3424 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(4).getImm()));
3427 Store.setOpcode(StOpc);
3431 Store.setFlags(
MI->getFlags());
3432 EmitToStreamer(*OutStreamer,
Store);
3435void AArch64AsmPrinter::emitAtomicFetchHintPseudoExpansion(
3436 const MachineInstr *
MI) {
3438 MCInstBuilder(AArch64::HINT).addImm(
MI->getOperand(4).getImm()));
3446 EmitToStreamer(*OutStreamer, Fetch);
3451#include "AArch64GenMCPseudoLowering.inc"
3453void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3460void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3461 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3466 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3471 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3472 EmitToStreamer(*OutStreamer, OutInst);
3476 if (
MI->getOpcode() == AArch64::ADRP) {
3477 for (
auto &Opd :
MI->operands()) {
3478 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3479 "swift_async_extendedFramePointerFlags") {
3480 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3487 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3489 LOHInstToLabel[
MI] = LOHLabel;
3493 AArch64TargetStreamer *TS =
3496 switch (
MI->getOpcode()) {
3499 "Unhandled tail call instruction");
3501 case AArch64::READ_REGISTER_GPR64:
3505 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
3506 .addReg(
MI->getOperand(0).getReg())
3507 .addReg(AArch64::XZR)
3508 .addReg(
MI->getOperand(1).getImm())
3511 case AArch64::READ_REGISTER_FPR64:
3513 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::FMOVDr)
3514 .addReg(
MI->getOperand(0).getReg())
3515 .addReg(
MI->getOperand(1).getImm()));
3517 case AArch64::HINT: {
3522 if (CurrentPatchableFunctionEntrySym &&
3523 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3525 int64_t
Imm =
MI->getOperand(0).getImm();
3526 if (
Imm == 32 ||
Imm == 34 ||
Imm == 36 ||
Imm == 38) {
3528 MCInstLowering.
Lower(
MI, Inst);
3529 EmitToStreamer(*OutStreamer, Inst);
3530 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3531 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3537 case AArch64::MOVMCSym: {
3538 Register DestReg =
MI->getOperand(0).getReg();
3539 const MachineOperand &MO_Sym =
MI->getOperand(1);
3540 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3541 MCOperand Hi_MCSym, Lo_MCSym;
3554 EmitToStreamer(*OutStreamer, MovZ);
3562 EmitToStreamer(*OutStreamer, MovK);
3565 case AArch64::MOVIv2d_ns:
3573 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3574 MI->getOperand(1).getImm() == 0) {
3576 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3579 EmitToStreamer(*OutStreamer, TmpInst);
3584 case AArch64::DBG_VALUE:
3585 case AArch64::DBG_VALUE_LIST:
3587 SmallString<128> TmpStr;
3588 raw_svector_ostream OS(TmpStr);
3589 PrintDebugValueComment(
MI, OS);
3594 case AArch64::EMITBKEY:
3595 case AArch64::EMITNONHINTED: {
3597 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3598 ExceptionHandlingType != ExceptionHandling::ARM)
3601 if (getFunctionCFISectionType(*MF) == CFISection::None)
3604 if (
MI->getOpcode() == AArch64::EMITBKEY)
3612 case AArch64::EMITMTETAGGED: {
3614 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3615 ExceptionHandlingType != ExceptionHandling::ARM)
3618 if (getFunctionCFISectionType(*MF) != CFISection::None)
3623 case AArch64::AUTx16x17: {
3625 const Register Scratch = AArch64::X17;
3627 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3629 MI->getOperand(1).getImm(),
MI->getOperand(2));
3631 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3632 std::nullopt,
MI->getDeactivationSymbol());
3636 case AArch64::AUTxMxN: {
3638 const Register Scratch =
MI->getOperand(1).getReg();
3640 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3642 MI->getOperand(4).getImm(),
MI->getOperand(5));
3644 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3645 std::nullopt,
MI->getDeactivationSymbol());
3649 case AArch64::AUTPAC: {
3651 const Register Scratch = AArch64::X17;
3653 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3655 MI->getOperand(1).getImm(),
MI->getOperand(2));
3657 auto SignSchema = PtrAuthSchema::CreateImmReg(
3659 MI->getOperand(4).getImm(),
MI->getOperand(5));
3661 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3662 std::nullopt,
MI->getDeactivationSymbol());
3666 case AArch64::AUTPCPAC: {
3667 auto AuthSchema = PtrAuthSchema::CreateRegReg(
3671 auto SignSchema = PtrAuthSchema::CreateImmReg(
3673 MI->getOperand(2).getImm(),
MI->getOperand(3));
3675 emitPtrauthAuthResign(AArch64::X17, AArch64::X16,
3676 AuthSchema, SignSchema, std::nullopt,
3677 MI->getDeactivationSymbol());
3681 case AArch64::AUTRELLOADPAC: {
3683 const Register Scratch = AArch64::X17;
3685 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3687 MI->getOperand(1).getImm(),
MI->getOperand(2));
3689 auto SignSchema = PtrAuthSchema::CreateImmReg(
3691 MI->getOperand(4).getImm(),
MI->getOperand(5));
3693 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3694 MI->getOperand(6).getImm(),
3695 MI->getDeactivationSymbol());
3701 emitPtrauthSign(
MI);
3704 case AArch64::LOADauthptrstatic:
3705 LowerLOADauthptrstatic(*
MI);
3708 case AArch64::LOADgotPAC:
3709 case AArch64::MOVaddrPAC:
3710 LowerMOVaddrPAC(*
MI);
3713 case AArch64::LOADgotAUTH:
3714 LowerLOADgotAUTH(*
MI);
3719 emitPtrauthBranch(
MI);
3725 case AArch64::AUTH_TCRETURN:
3726 case AArch64::AUTH_TCRETURN_BTI: {
3729 const uint64_t Disc =
MI->getOperand(3).getImm();
3731 Register AddrDisc =
MI->getOperand(4).getReg();
3733 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3735 emitPtrauthTailCallHardening(
MI);
3738 if (Callee == AddrDisc)
3745 bool AddrDiscIsImplicitDef =
3746 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3747 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3748 AddrDiscIsImplicitDef);
3749 emitBLRA(
false,
Key, Callee, DiscReg);
3753 case AArch64::TCRETURNri:
3754 case AArch64::TCRETURNrix16x17:
3755 case AArch64::TCRETURNrix17:
3756 case AArch64::TCRETURNrinotx16:
3757 case AArch64::TCRETURNriALL: {
3758 emitPtrauthTailCallHardening(
MI);
3760 recordIfImportCall(
MI);
3764 EmitToStreamer(*OutStreamer, TmpInst);
3767 case AArch64::TCRETURNdi: {
3768 emitPtrauthTailCallHardening(
MI);
3772 recordIfImportCall(
MI);
3776 EmitToStreamer(*OutStreamer, TmpInst);
3779 case AArch64::SpeculationBarrierISBDSBEndBB: {
3784 EmitToStreamer(*OutStreamer, TmpInstDSB);
3788 EmitToStreamer(*OutStreamer, TmpInstISB);
3791 case AArch64::SpeculationBarrierSBEndBB: {
3795 EmitToStreamer(*OutStreamer, TmpInstSB);
3798 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3806 const MachineOperand &MO_Sym =
MI->getOperand(0);
3807 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3808 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3812 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3819 EmitToStreamer(*OutStreamer, Adrp);
3827 EmitToStreamer(*OutStreamer, Ldr);
3830 Add.setOpcode(AArch64::ADDXri);
3833 Add.addOperand(SymTLSDescLo12);
3835 EmitToStreamer(*OutStreamer,
Add);
3839 MCInst TLSAuthDescCall;
3840 TLSAuthDescCall.
setOpcode(AArch64::TLSAUTHDESCCALL);
3842 EmitToStreamer(*OutStreamer, TLSAuthDescCall);
3851 EmitToStreamer(*OutStreamer, Blraa);
3855 case AArch64::TLSDESC_CALLSEQ: {
3863 const MachineOperand &MO_Sym =
MI->getOperand(0);
3864 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3865 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3869 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3876 EmitToStreamer(*OutStreamer, Adrp);
3879 if (STI->isTargetILP32()) {
3889 EmitToStreamer(*OutStreamer, Ldr);
3892 if (STI->isTargetILP32()) {
3893 Add.setOpcode(AArch64::ADDWri);
3897 Add.setOpcode(AArch64::ADDXri);
3901 Add.addOperand(SymTLSDescLo12);
3903 EmitToStreamer(*OutStreamer,
Add);
3908 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3910 EmitToStreamer(*OutStreamer, TLSDescCall);
3918 EmitToStreamer(*OutStreamer, Blr);
3923 case AArch64::JumpTableDest32:
3924 case AArch64::JumpTableDest16:
3925 case AArch64::JumpTableDest8:
3926 LowerJumpTableDest(*OutStreamer, *
MI);
3929 case AArch64::BR_JumpTable:
3930 LowerHardenedBRJumpTable(*
MI);
3933 case AArch64::FMOVH0:
3934 case AArch64::FMOVS0:
3935 case AArch64::FMOVD0:
3939 case AArch64::MOPSMemoryCopyPseudo:
3940 case AArch64::MOPSMemoryMovePseudo:
3941 case AArch64::MOPSMemorySetPseudo:
3942 case AArch64::MOPSMemorySetTaggingPseudo:
3943 LowerMOPS(*OutStreamer, *
MI);
3946 case TargetOpcode::STACKMAP:
3947 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3949 case TargetOpcode::PATCHPOINT:
3950 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3952 case TargetOpcode::STATEPOINT:
3953 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3955 case TargetOpcode::FAULTING_OP:
3956 return LowerFAULTING_OP(*
MI);
3958 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3959 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3962 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3963 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3966 case TargetOpcode::PATCHABLE_TAIL_CALL:
3967 LowerPATCHABLE_TAIL_CALL(*
MI);
3969 case TargetOpcode::PATCHABLE_EVENT_CALL:
3970 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3971 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3972 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3974 case AArch64::KCFI_CHECK:
3975 LowerKCFI_CHECK(*
MI);
3978 case AArch64::HWASAN_CHECK_MEMACCESS:
3979 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3980 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3981 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3982 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3985 case AArch64::SEH_EndC:
3989 case AArch64::SEH_StackAlloc:
3993 case AArch64::SEH_SaveFPLR:
3997 case AArch64::SEH_SaveFPLR_X:
3998 assert(
MI->getOperand(0).getImm() < 0 &&
3999 "Pre increment SEH opcode must have a negative offset");
4003 case AArch64::SEH_SaveReg:
4005 MI->getOperand(1).getImm());
4008 case AArch64::SEH_SaveReg_X:
4009 assert(
MI->getOperand(1).getImm() < 0 &&
4010 "Pre increment SEH opcode must have a negative offset");
4012 -
MI->getOperand(1).getImm());
4015 case AArch64::SEH_SaveRegP:
4016 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
4017 MI->getOperand(0).getImm() <= 28) {
4018 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
4019 "Register paired with LR must be odd");
4021 MI->getOperand(2).getImm());
4024 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4025 "Non-consecutive registers not allowed for save_regp");
4027 MI->getOperand(2).getImm());
4030 case AArch64::SEH_SaveRegP_X:
4031 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4032 "Non-consecutive registers not allowed for save_regp_x");
4033 assert(
MI->getOperand(2).getImm() < 0 &&
4034 "Pre increment SEH opcode must have a negative offset");
4036 -
MI->getOperand(2).getImm());
4039 case AArch64::SEH_SaveFReg:
4041 MI->getOperand(1).getImm());
4044 case AArch64::SEH_SaveFReg_X:
4045 assert(
MI->getOperand(1).getImm() < 0 &&
4046 "Pre increment SEH opcode must have a negative offset");
4048 -
MI->getOperand(1).getImm());
4051 case AArch64::SEH_SaveFRegP:
4052 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4053 "Non-consecutive registers not allowed for save_regp");
4055 MI->getOperand(2).getImm());
4058 case AArch64::SEH_SaveFRegP_X:
4059 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
4060 "Non-consecutive registers not allowed for save_regp_x");
4061 assert(
MI->getOperand(2).getImm() < 0 &&
4062 "Pre increment SEH opcode must have a negative offset");
4064 -
MI->getOperand(2).getImm());
4067 case AArch64::SEH_SetFP:
4071 case AArch64::SEH_AddFP:
4075 case AArch64::SEH_Nop:
4079 case AArch64::SEH_PrologEnd:
4083 case AArch64::SEH_EpilogStart:
4087 case AArch64::SEH_EpilogEnd:
4091 case AArch64::SEH_PACSignLR:
4095 case AArch64::SEH_SaveAnyRegI:
4097 "SaveAnyRegI SEH opcode offset must fit into 6 bits");
4099 MI->getOperand(1).getImm());
4102 case AArch64::SEH_SaveAnyRegIP:
4103 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4104 "Non-consecutive registers not allowed for save_any_reg");
4106 "SaveAnyRegIP SEH opcode offset must fit into 6 bits");
4108 MI->getOperand(2).getImm());
4111 case AArch64::SEH_SaveAnyRegQ:
4113 "SaveAnyRegQ SEH opcode offset must fit into 6 bits");
4115 MI->getOperand(1).getImm());
4118 case AArch64::SEH_SaveAnyRegQX:
4120 "SaveAnyRegQX SEH opcode offset must fit into 6 bits");
4122 -
MI->getOperand(1).getImm());
4125 case AArch64::SEH_SaveAnyRegQP:
4126 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4127 "Non-consecutive registers not allowed for save_any_reg");
4129 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
4131 MI->getOperand(2).getImm());
4134 case AArch64::SEH_SaveAnyRegQPX:
4135 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
4136 "Non-consecutive registers not allowed for save_any_reg");
4138 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
4140 -
MI->getOperand(2).getImm());
4143 case AArch64::SEH_AllocZ:
4144 assert(
MI->getOperand(0).getImm() >= 0 &&
4145 "AllocZ SEH opcode offset must be non-negative");
4146 assert(
MI->getOperand(0).getImm() <= 255 &&
4147 "AllocZ SEH opcode offset must fit into 8 bits");
4151 case AArch64::SEH_SaveZReg:
4152 assert(
MI->getOperand(1).getImm() >= 0 &&
4153 "SaveZReg SEH opcode offset must be non-negative");
4154 assert(
MI->getOperand(1).getImm() <= 255 &&
4155 "SaveZReg SEH opcode offset must fit into 8 bits");
4157 MI->getOperand(1).getImm());
4160 case AArch64::SEH_SavePReg:
4161 assert(
MI->getOperand(1).getImm() >= 0 &&
4162 "SavePReg SEH opcode offset must be non-negative");
4163 assert(
MI->getOperand(1).getImm() <= 255 &&
4164 "SavePReg SEH opcode offset must fit into 8 bits");
4166 MI->getOperand(1).getImm());
4171 recordIfImportCall(
MI);
4173 MCInstLowering.
Lower(
MI, TmpInst);
4174 EmitToStreamer(*OutStreamer, TmpInst);
4177 case AArch64::CBWPri:
4178 case AArch64::CBXPri:
4179 case AArch64::CBBAssertExt:
4180 case AArch64::CBHAssertExt:
4181 case AArch64::CBWPrr:
4182 case AArch64::CBXPrr:
4183 emitCBPseudoExpansion(
MI);
4185 case AArch64::ATOMIC_STORE_HINT_B:
4186 case AArch64::ATOMIC_STORE_HINT_H:
4187 case AArch64::ATOMIC_STORE_HINT_W:
4188 case AArch64::ATOMIC_STORE_HINT_X:
4189 emitAtomicHintPseudoExpansion(
MI);
4191 case AArch64::ATOMIC_FETCH_HINT_W:
4192 case AArch64::ATOMIC_FETCH_HINT_X:
4193 emitAtomicFetchHintPseudoExpansion(
MI);
4195 case AArch64::ATOMIC_STORE_HINT_BroW:
4196 case AArch64::ATOMIC_STORE_HINT_HroW:
4197 case AArch64::ATOMIC_STORE_HINT_WroW:
4198 case AArch64::ATOMIC_STORE_HINT_XroW:
4199 case AArch64::ATOMIC_STORE_HINT_SroW:
4200 case AArch64::ATOMIC_STORE_HINT_DroW:
4201 case AArch64::ATOMIC_STORE_HINT_BroX:
4202 case AArch64::ATOMIC_STORE_HINT_HroX:
4203 case AArch64::ATOMIC_STORE_HINT_WroX:
4204 case AArch64::ATOMIC_STORE_HINT_XroX:
4205 case AArch64::ATOMIC_STORE_HINT_SroX:
4206 case AArch64::ATOMIC_STORE_HINT_DroX:
4207 emitAtomicHintPseudoExpansionRO(
MI);
4209 case AArch64::ATOMIC_STORE_HINT_Bui:
4210 case AArch64::ATOMIC_STORE_HINT_Hui:
4211 case AArch64::ATOMIC_STORE_HINT_Wui:
4212 case AArch64::ATOMIC_STORE_HINT_Xui:
4213 case AArch64::ATOMIC_STORE_HINT_Sui:
4214 case AArch64::ATOMIC_STORE_HINT_Dui:
4215 case AArch64::ATOMIC_STORE_HINT_Bi:
4216 case AArch64::ATOMIC_STORE_HINT_Hi:
4217 case AArch64::ATOMIC_STORE_HINT_Wi:
4218 case AArch64::ATOMIC_STORE_HINT_Xi:
4219 case AArch64::ATOMIC_STORE_HINT_Si:
4220 case AArch64::ATOMIC_STORE_HINT_Di:
4221 emitAtomicHintPseudoExpansionImm(
MI);
4225 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
4230 MCInstLowering.
Lower(
MI, TmpInst);
4231 EmitToStreamer(*OutStreamer, TmpInst);
4234void AArch64AsmPrinter::recordIfImportCall(
4235 const llvm::MachineInstr *BranchInst) {
4236 if (!EnableImportCallOptimization)
4240 if (GV && GV->hasDLLImportStorageClass()) {
4241 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
4246 .push_back({CallSiteSymbol, CalledSymbol});
4250void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
4251 MCSymbol *LazyPointer) {
4268 EmitToStreamer(Adrp);
4276 MCOperand SymPageOff;
4283 EmitToStreamer(Ldr);
4286 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
4287 .addReg(AArch64::X16)
4288 .addReg(AArch64::X16)
4291 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4293 .addReg(AArch64::X16));
4296void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
4297 const GlobalIFunc &GI,
4298 MCSymbol *LazyPointer) {
4330 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4331 .addReg(AArch64::SP)
4332 .addReg(AArch64::FP)
4333 .addReg(AArch64::LR)
4334 .addReg(AArch64::SP)
4337 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4338 .addReg(AArch64::FP)
4339 .addReg(AArch64::SP)
4343 for (
int I = 0;
I != 4; ++
I)
4344 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4345 .addReg(AArch64::SP)
4346 .addReg(AArch64::X1 + 2 *
I)
4347 .addReg(AArch64::X0 + 2 *
I)
4348 .addReg(AArch64::SP)
4351 for (
int I = 0;
I != 4; ++
I)
4352 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
4353 .addReg(AArch64::SP)
4354 .addReg(AArch64::D1 + 2 *
I)
4355 .addReg(AArch64::D0 + 2 *
I)
4356 .addReg(AArch64::SP)
4360 MCInstBuilder(AArch64::BL)
4373 EmitToStreamer(Adrp);
4381 MCOperand SymPageOff;
4388 EmitToStreamer(Ldr);
4391 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
4392 .addReg(AArch64::X0)
4393 .addReg(AArch64::X16)
4396 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4397 .addReg(AArch64::X16)
4398 .addReg(AArch64::X0)
4402 for (
int I = 3;
I != -1; --
I)
4403 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
4404 .addReg(AArch64::SP)
4405 .addReg(AArch64::D1 + 2 *
I)
4406 .addReg(AArch64::D0 + 2 *
I)
4407 .addReg(AArch64::SP)
4410 for (
int I = 3;
I != -1; --
I)
4411 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4412 .addReg(AArch64::SP)
4413 .addReg(AArch64::X1 + 2 *
I)
4414 .addReg(AArch64::X0 + 2 *
I)
4415 .addReg(AArch64::SP)
4418 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4419 .addReg(AArch64::SP)
4420 .addReg(AArch64::FP)
4421 .addReg(AArch64::LR)
4422 .addReg(AArch64::SP)
4425 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4427 .addReg(AArch64::X16));
4430const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4431 const Constant *BaseCV,
4441char AArch64AsmPrinter::ID = 0;
4444 "AArch64 Assembly Printer",
false,
false)
4448LLVMInitializeAArch64AsmPrinter() {
4458 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4468 AArch64AsmPrinter &
AsmPrinter =
static_cast<AArch64AsmPrinter &
>(
4479 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 emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQ(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 emitARM64WinCFIEndC()
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 ....
virtual void emitCFINonHintPAuthFrame()
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'...
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
@ 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,...