77#define DEBUG_TYPE "AArch64AsmPrinter"
82 "Number of zero-cycle FPR zeroing instructions expanded from "
83 "canonical pseudo instructions");
91 cl::desc(
"Check pointer authentication auth/resign failures"),
100 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
102 unsigned InstsEmitted;
104 bool EnableImportCallOptimization =
false;
106 SectionToImportedFunctionCalls;
107 unsigned PAuthIFuncNextUniqueID = 1;
112 AArch64AsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
114 MCInstLowering(OutContext, *this), FM(*this) {}
116 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
120 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const {
121 return MCInstLowering.lowerOperand(MO, MCOp);
124 const MCExpr *lowerConstantPtrAuth(
const ConstantPtrAuth &CPA)
override;
126 const MCExpr *lowerBlockAddressConstant(
const BlockAddress &BA)
override;
128 void emitStartOfAsmFile(
Module &M)
override;
129 void emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
130 ArrayRef<unsigned> JumpTableIndices)
override;
133 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
134 const MCSymbol *BranchLabel)
const override;
136 void emitFunctionEntryLabel()
override;
138 void emitXXStructor(
const DataLayout &
DL,
const Constant *CV)
override;
140 void LowerJumpTableDest(MCStreamer &OutStreamer,
const MachineInstr &
MI);
142 void LowerHardenedBRJumpTable(
const MachineInstr &
MI);
144 void LowerMOPS(MCStreamer &OutStreamer,
const MachineInstr &
MI);
146 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &
SM,
147 const MachineInstr &
MI);
148 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
149 const MachineInstr &
MI);
150 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
151 const MachineInstr &
MI);
152 void LowerFAULTING_OP(
const MachineInstr &
MI);
154 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI);
155 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI);
156 void LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI);
157 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
159 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
160 HwasanMemaccessTuple;
161 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
162 void LowerKCFI_CHECK(
const MachineInstr &
MI);
163 void LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI);
164 void emitHwasanMemaccessSymbols(
Module &M);
166 void emitSled(
const MachineInstr &
MI, SledKind Kind);
174 if (STI->isX16X17Safer())
175 return Reg == AArch64::X16 ||
Reg == AArch64::X17;
181 void emitPtrauthBranch(
const MachineInstr *
MI);
183 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
187 const MCSymbol *OnFailure =
nullptr);
190 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
192 struct PtrAuthSchema {
194 const MachineOperand &AddrDiscOp);
199 bool AddrDiscIsKilled;
214 PtrAuthSchema AuthSchema,
215 std::optional<PtrAuthSchema> SignSchema,
216 std::optional<int64_t> Addend,
Value *DS);
221 bool emitDeactivationSymbolRelocation(
Value *DS);
224 void emitPtrauthSign(
const MachineInstr *
MI);
248 bool MayClobberAddrDisc =
false);
251 void LowerLOADauthptrstatic(
const MachineInstr &
MI);
255 void LowerMOVaddrPAC(
const MachineInstr &
MI);
260 void LowerLOADgotAUTH(
const MachineInstr &
MI);
262 void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
263 void emitAddress(MCRegister
Reg,
const MCExpr *Expr, MCRegister Tmp,
264 bool DSOLocal,
const MCSubtargetInfo &STI);
266 const MCExpr *emitPAuthRelocationAsIRelative(
268 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
272 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
275 void emitAttributes(
unsigned Flags, uint64_t PAuthABIPlatform,
276 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
279 void emitCBPseudoExpansion(
const MachineInstr *
MI);
281 void EmitToStreamer(MCStreamer &S,
const MCInst &Inst);
282 void EmitToStreamer(
const MCInst &Inst) {
283 EmitToStreamer(*OutStreamer, Inst);
288 void emitFunctionHeaderComment()
override;
290 void getAnalysisUsage(AnalysisUsage &AU)
const override {
295 bool runOnMachineFunction(MachineFunction &MF)
override {
296 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
297 PSI = &PSIW->getPSI();
299 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
300 SDPI = &SDPIW->getStaticDataProfileInfo();
302 AArch64FI = MF.
getInfo<AArch64FunctionInfo>();
305 SetupMachineFunction(MF);
307 if (STI->isTargetCOFF()) {
314 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
315 OutStreamer->emitCOFFSymbolStorageClass(Scl);
316 OutStreamer->emitCOFFSymbolType(
Type);
317 OutStreamer->endCOFFSymbolDef();
331 const Constant *BaseCV =
nullptr,
332 uint64_t
Offset = 0)
override;
335 void printOperand(
const MachineInstr *
MI,
unsigned OpNum, raw_ostream &O);
337 bool printAsmRegInClass(
const MachineOperand &MO,
338 const TargetRegisterClass *RC,
unsigned AltName,
341 bool PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
342 const char *ExtraCode, raw_ostream &O)
override;
343 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
344 const char *ExtraCode, raw_ostream &O)
override;
346 void PrintDebugValueComment(
const MachineInstr *
MI, raw_ostream &OS);
348 void emitFunctionBodyEnd()
override;
349 void emitGlobalAlias(
const Module &M,
const GlobalAlias &GA)
override;
351 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
352 void emitEndOfAsmFile(
Module &M)
override;
354 AArch64FunctionInfo *AArch64FI =
nullptr;
360 void emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift);
361 void emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift);
369 void emitFMov0(
const MachineInstr &
MI);
370 void emitFMov0AsFMov(
const MachineInstr &
MI,
Register DestReg);
372 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
374 MInstToMCSymbol LOHInstToLabel;
376 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
377 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
380 const MCSubtargetInfo *getIFuncMCSubtargetInfo()
const override {
384 void emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
385 MCSymbol *LazyPointer)
override;
386 void emitMachOIFuncStubHelperBody(
Module &M,
const GlobalIFunc &GI,
387 MCSymbol *LazyPointer)
override;
392 void recordIfImportCall(
const MachineInstr *BranchInst);
397void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
398 const Triple &
TT = TM.getTargetTriple();
400 if (
TT.isOSBinFormatCOFF()) {
401 emitCOFFFeatureSymbol(M);
402 emitCOFFReplaceableFunctionData(M);
404 if (
M.getModuleFlag(
"import-call-optimization"))
405 EnableImportCallOptimization =
true;
408 if (!
TT.isOSBinFormatELF())
413 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
416 unsigned BAFlags = 0;
417 unsigned GNUFlags = 0;
419 M.getModuleFlag(
"branch-target-enforcement"))) {
420 if (!BTE->isZero()) {
421 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
427 M.getModuleFlag(
"guarded-control-stack"))) {
428 if (!GCS->isZero()) {
429 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
435 M.getModuleFlag(
"sign-return-address"))) {
436 if (!Sign->isZero()) {
437 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
442 uint64_t PAuthABIPlatform = -1;
444 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
445 PAuthABIPlatform = PAP->getZExtValue();
448 uint64_t PAuthABIVersion = -1;
450 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
451 PAuthABIVersion = PAV->getZExtValue();
455 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
457 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
460void AArch64AsmPrinter::emitFunctionHeaderComment() {
461 const AArch64FunctionInfo *FI = MF->
getInfo<AArch64FunctionInfo>();
463 if (OutlinerString != std::nullopt)
464 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
467void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
470 if (
F.hasFnAttribute(
"patchable-function-entry")) {
472 if (
F.getFnAttribute(
"patchable-function-entry")
474 .getAsInteger(10, Num))
480 emitSled(
MI, SledKind::FUNCTION_ENTER);
483void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
484 emitSled(
MI, SledKind::FUNCTION_EXIT);
487void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
488 emitSled(
MI, SledKind::TAIL_CALL);
491void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
492 static const int8_t NoopsInSledCount = 7;
513 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
514 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
515 OutStreamer->emitLabel(CurSled);
516 auto Target = OutContext.createTempSymbol();
521 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
523 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
524 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
526 OutStreamer->emitLabel(Target);
527 recordSled(CurSled,
MI, Kind, 2);
530void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
531 uint64_t PAuthABIPlatform,
532 uint64_t PAuthABIVersion,
533 AArch64TargetStreamer *TS) {
535 PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
536 PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
538 if (PAuthABIPlatform || PAuthABIVersion) {
542 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
543 AArch64BuildAttributes::SubsectionType::ULEB128);
547 PAuthABIPlatform,
"");
561 if (BTIValue || PACValue || GCSValue) {
565 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
566 AArch64BuildAttributes::SubsectionType::ULEB128);
594void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
596 auto &
O = *OutStreamer;
597 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
598 O.emitLabel(CurSled);
599 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
601 OutContext.getOrCreateSymbol(
602 Twine(MachO ?
"_" :
"") +
603 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
606 O.AddComment(
"Begin XRay typed event");
607 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
608 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
614 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
618 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
619 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
620 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
621 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
622 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
626 O.AddComment(
"End XRay typed event");
627 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
634 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
636 O.AddComment(
"Begin XRay custom event");
637 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
638 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
644 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
645 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
646 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
647 O.AddComment(
"End XRay custom event");
648 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
655 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
659void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
661 assert(std::next(
MI.getIterator())->isCall() &&
662 "KCFI_CHECK not followed by a call instruction");
663 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
664 "KCFI_CHECK call target doesn't match call operand");
668 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
669 if (AddrReg == AArch64::XZR) {
673 emitMovXReg(AddrReg, AArch64::XZR);
679 for (
auto &
Reg : ScratchRegs) {
685 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
686 "Invalid scratch registers for KCFI_CHECK");
690 int64_t PrefixNops = 0;
693 .getFnAttribute(
"patchable-function-prefix")
695 .getAsInteger(10, PrefixNops);
698 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
699 .addReg(ScratchRegs[0])
701 .addImm(-(PrefixNops * 4 + 4)));
705 const int64_t
Type =
MI.getOperand(1).getImm();
706 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
707 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
710 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
711 .addReg(AArch64::WZR)
712 .addReg(ScratchRegs[0])
713 .addReg(ScratchRegs[1])
717 EmitToStreamer(*OutStreamer,
718 MCInstBuilder(AArch64::Bcc)
727 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
731 AddrIndex = AddrReg - AArch64::X0;
741 assert(AddrIndex < 31 && TypeIndex < 31);
743 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
744 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
745 OutStreamer->emitLabel(
Pass);
748void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
756 if (
Reg == AArch64::XZR)
760 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
762 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
763 uint32_t AccessInfo =
MI.getOperand(1).getImm();
765 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
767 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
768 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
770 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
771 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
774 if (!TM.getTargetTriple().isOSBinFormatELF())
777 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
780 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
782 SymName +=
"_short_v2";
783 Sym = OutContext.getOrCreateSymbol(SymName);
786 EmitToStreamer(*OutStreamer,
787 MCInstBuilder(AArch64::BL)
791void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
792 if (HwasanMemaccessSymbols.empty())
795 const Triple &
TT = TM.getTargetTriple();
799 auto STI = std::make_unique<AArch64Subtarget>(
800 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
802 this->STI = STI.get();
805 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
807 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
809 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
811 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
814 for (
auto &
P : HwasanMemaccessSymbols) {
815 unsigned Reg = std::get<0>(
P.first);
816 bool IsShort = std::get<1>(
P.first);
817 uint32_t AccessInfo = std::get<2>(
P.first);
818 bool IsFixedShadow = std::get<3>(
P.first);
819 uint64_t FixedShadowOffset = std::get<4>(
P.first);
820 const MCSymbolRefExpr *HwasanTagMismatchRef =
821 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
824 bool HasMatchAllTag =
826 uint8_t MatchAllTag =
833 OutStreamer->switchSection(OutContext.getELFSection(
839 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
840 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
841 OutStreamer->emitLabel(Sym);
843 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
844 .addReg(AArch64::X16)
854 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
855 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
856 .addReg(AArch64::W16)
857 .addReg(AArch64::X17)
858 .addReg(AArch64::X16)
862 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
863 .addReg(AArch64::W16)
864 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
865 .addReg(AArch64::X16)
870 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
871 .addReg(AArch64::XZR)
872 .addReg(AArch64::X16)
875 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
876 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
879 HandleMismatchOrPartialSym, OutContext)));
880 MCSymbol *ReturnSym = OutContext.createTempSymbol();
881 OutStreamer->emitLabel(ReturnSym);
882 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
883 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
885 if (HasMatchAllTag) {
886 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
887 .addReg(AArch64::X17)
891 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
892 .addReg(AArch64::XZR)
893 .addReg(AArch64::X17)
897 MCInstBuilder(AArch64::Bcc)
903 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
904 .addReg(AArch64::WZR)
905 .addReg(AArch64::W16)
908 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
910 MCInstBuilder(AArch64::Bcc)
914 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
915 .addReg(AArch64::X17)
919 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
920 .addReg(AArch64::X17)
921 .addReg(AArch64::X17)
924 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
925 .addReg(AArch64::WZR)
926 .addReg(AArch64::W16)
927 .addReg(AArch64::W17)
930 MCInstBuilder(AArch64::Bcc)
934 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
935 .addReg(AArch64::X16)
938 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
939 .addReg(AArch64::W16)
940 .addReg(AArch64::X16)
943 MCInstBuilder(AArch64::SUBSXrs)
944 .addReg(AArch64::XZR)
945 .addReg(AArch64::X16)
949 MCInstBuilder(AArch64::Bcc)
953 OutStreamer->emitLabel(HandleMismatchSym);
956 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
962 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
968 if (
Reg != AArch64::X0)
969 emitMovXReg(AArch64::X0,
Reg);
976 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
981 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
982 .addReg(AArch64::X16)
986 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
987 .addReg(AArch64::X16)
988 .addReg(AArch64::X16)
992 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1000 const MCExpr *StubAuthPtrRef) {
1003 OutStreamer.
emitValue(StubAuthPtrRef, 8);
1006void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
1007 emitHwasanMemaccessSymbols(M);
1009 const Triple &
TT = TM.getTargetTriple();
1010 if (
TT.isOSBinFormatMachO()) {
1012 MachineModuleInfoMachO &MMIMacho =
1013 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1017 if (!Stubs.empty()) {
1019 OutStreamer->switchSection(
1022 emitAlignment(
Align(8));
1024 for (
const auto &Stub : Stubs)
1027 OutStreamer->addBlankLine();
1035 OutStreamer->emitSubsectionsViaSymbols();
1038 if (
TT.isOSBinFormatELF()) {
1040 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1044 if (!Stubs.empty()) {
1045 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1047 emitAlignment(
Align(8));
1049 for (
const auto &Stub : Stubs)
1052 OutStreamer->addBlankLine();
1063 M.getModuleFlag(
"ptrauth-elf-got"));
1064 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1065 for (
const GlobalValue &GV :
M.global_values())
1067 !GV.getName().starts_with(
"llvm."))
1068 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1077 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1078 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1081 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1082 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1093 for (
auto &[Section, CallsToImportedFuncs] :
1094 SectionToImportedFunctionCalls) {
1096 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1097 OutStreamer->emitInt32(SectionSize);
1098 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1099 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1101 OutStreamer->emitInt32(0x13);
1102 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1103 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1109void AArch64AsmPrinter::emitLOHs() {
1113 for (
const MachineInstr *
MI :
D.getArgs()) {
1114 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1115 assert(LabelIt != LOHInstToLabel.end() &&
1116 "Label hasn't been inserted for LOH related instruction");
1119 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1124void AArch64AsmPrinter::emitFunctionBodyEnd() {
1130MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1134 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1135 return OutContext.getOrCreateSymbol(
1136 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1137 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1142void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1144 const MachineOperand &MO =
MI->getOperand(OpNum);
1160 PrintSymbolOperand(MO, O);
1171bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1195bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1196 const TargetRegisterClass *RC,
1197 unsigned AltName, raw_ostream &O) {
1198 assert(MO.
isReg() &&
"Should only get here with a register!");
1199 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1208bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1209 const char *ExtraCode, raw_ostream &O) {
1210 const MachineOperand &MO =
MI->getOperand(OpNum);
1217 if (ExtraCode && ExtraCode[0]) {
1218 if (ExtraCode[1] != 0)
1221 switch (ExtraCode[0]) {
1229 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1242 const TargetRegisterClass *RC;
1243 switch (ExtraCode[0]) {
1245 RC = &AArch64::FPR8RegClass;
1248 RC = &AArch64::FPR16RegClass;
1251 RC = &AArch64::FPR32RegClass;
1254 RC = &AArch64::FPR64RegClass;
1257 RC = &AArch64::FPR128RegClass;
1260 RC = &AArch64::ZPRRegClass;
1265 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1286 unsigned AltName = AArch64::NoRegAltName;
1287 const TargetRegisterClass *RegClass;
1289 RegClass = &AArch64::ZPRRegClass;
1291 RegClass = &AArch64::PPRRegClass;
1293 RegClass = &AArch64::PNRRegClass;
1295 RegClass = &AArch64::FPR128RegClass;
1296 AltName = AArch64::vreg;
1300 return printAsmRegInClass(MO, RegClass, AltName, O);
1307bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1309 const char *ExtraCode,
1311 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1314 const MachineOperand &MO =
MI->getOperand(OpNum);
1315 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1320void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1322 unsigned NOps =
MI->getNumOperands();
1324 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1326 OS <<
MI->getDebugVariable()->getName();
1329 assert(
MI->isIndirectDebugValue());
1341void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1342 ArrayRef<unsigned> JumpTableIndices) {
1344 if (JumpTableIndices.
empty())
1346 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1350 MCSection *ReadOnlySec =
nullptr;
1351 if (TM.Options.EnableStaticDataPartitioning) {
1357 OutStreamer->switchSection(ReadOnlySec);
1359 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1360 for (
unsigned JTI : JumpTableIndices) {
1361 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1364 if (JTBBs.empty())
continue;
1366 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1368 OutStreamer->emitLabel(GetJTISymbol(JTI));
1373 for (
auto *JTBB : JTBBs) {
1374 const MCExpr *
Value =
1393AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1394 const MachineInstr *BranchInstr,
1395 const MCSymbol *BranchLabel)
const {
1396 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1399 switch (AFI->getJumpTableEntrySize(JTI)) {
1401 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1404 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1407 EntrySize = codeview::JumpTableEntrySize::Int32;
1412 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1415void AArch64AsmPrinter::emitFunctionEntryLabel() {
1416 const Triple &
TT = TM.getTargetTriple();
1417 if (
TT.isOSBinFormatELF() &&
1420 CallingConv::AArch64_SVE_VectorCall ||
1421 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1423 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1434 OutStreamer->emitAssignment(
1438 auto getSymbolFromMetadata = [&](StringRef
Name) {
1442 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1449 for (MDNode *Node : UnmangledNames) {
1451 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1452 if (std::optional<std::string> MangledName =
1455 MMI->getContext().getOrCreateSymbol(*MangledName);
1456 emitFunctionAlias(UnmangledSym, ECMangledSym);
1459 if (MCSymbol *ECMangledSym =
1460 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1461 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1465void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1466 const Constant *CV) {
1468 if (CPA->hasAddressDiscriminator() &&
1469 !CPA->hasSpecialAddressDiscriminator(
1472 "unexpected address discrimination value for ctors/dtors entry, only "
1473 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1482void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1483 const GlobalAlias &GA) {
1489 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1491 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1494 OutStreamer->beginCOFFSymbolDef(ExpSym);
1498 OutStreamer->endCOFFSymbolDef();
1500 OutStreamer->beginCOFFSymbolDef(Sym);
1504 OutStreamer->endCOFFSymbolDef();
1505 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1506 OutStreamer->emitAssignment(
1523void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1524 const llvm::MachineInstr &
MI) {
1525 Register DestReg =
MI.getOperand(0).getReg();
1526 Register ScratchReg =
MI.getOperand(1).getReg();
1528 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1529 Register TableReg =
MI.getOperand(2).getReg();
1530 Register EntryReg =
MI.getOperand(3).getReg();
1531 int JTIdx =
MI.getOperand(4).getIndex();
1537 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1548 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1550 .addExpr(LabelExpr));
1555 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1556 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1557 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1562 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1563 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1567 .addImm(
Size == 1 ? 0 : 1));
1571 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1575 .addImm(
Size == 4 ? 0 : 2));
1578void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1580 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1582 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1583 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1599 MachineOperand JTOp =
MI.getOperand(0);
1603 "unsupported compressed jump table");
1605 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1609 uint64_t MaxTableEntry = NumTableEntries - 1;
1611 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1612 .addReg(AArch64::XZR)
1613 .addReg(AArch64::X16)
1614 .addImm(MaxTableEntry)
1617 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1622 if ((MaxTableEntry >>
Offset) == 0)
1624 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1627 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1628 .addReg(AArch64::XZR)
1629 .addReg(AArch64::X16)
1630 .addReg(AArch64::X17)
1636 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1637 .addReg(AArch64::X16)
1638 .addReg(AArch64::X16)
1639 .addReg(AArch64::XZR)
1643 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1644 MCOperand JTMCHi, JTMCLo;
1654 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1656 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1657 .addReg(AArch64::X17)
1658 .addReg(AArch64::X17)
1662 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1663 .addReg(AArch64::X16)
1664 .addReg(AArch64::X17)
1665 .addReg(AArch64::X16)
1676 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1678 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1679 .addReg(AArch64::X16)
1680 .addReg(AArch64::X17)
1681 .addReg(AArch64::X16)
1684 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1687void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1688 const llvm::MachineInstr &
MI) {
1689 unsigned Opcode =
MI.getOpcode();
1691 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1693 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1694 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1695 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1696 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1697 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1698 if (Opcode == AArch64::MOPSMemorySetPseudo)
1699 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1700 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1701 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1704 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1705 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1707 for (
auto Op :
Ops) {
1709 auto MCIB = MCInstBuilder(
Op);
1711 MCIB.addReg(
MI.getOperand(i++).getReg());
1712 MCIB.addReg(
MI.getOperand(i++).getReg());
1714 MCIB.addReg(
MI.getOperand(i++).getReg());
1716 MCIB.addReg(
MI.getOperand(i++).getReg());
1717 MCIB.addReg(
MI.getOperand(i++).getReg());
1718 MCIB.addReg(
MI.getOperand(i++).getReg());
1720 EmitToStreamer(OutStreamer, MCIB);
1724void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &
SM,
1725 const MachineInstr &
MI) {
1726 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1729 MCSymbol *MILabel = Ctx.createTempSymbol();
1732 SM.recordStackMap(*MILabel,
MI);
1733 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1736 const MachineBasicBlock &
MBB = *
MI.getParent();
1739 while (NumNOPBytes > 0) {
1740 if (MII ==
MBB.
end() || MII->isCall() ||
1741 MII->getOpcode() == AArch64::DBG_VALUE ||
1742 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1743 MII->getOpcode() == TargetOpcode::STACKMAP)
1750 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1751 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1756void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
1757 const MachineInstr &
MI) {
1759 MCSymbol *MILabel = Ctx.createTempSymbol();
1761 SM.recordPatchPoint(*MILabel,
MI);
1763 PatchPointOpers Opers(&
MI);
1765 int64_t CallTarget = Opers.getCallTarget().getImm();
1766 unsigned EncodedBytes = 0;
1768 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1769 "High 16 bits of call target should be zero.");
1770 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1773 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1774 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1775 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1776 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1779 unsigned NumBytes = Opers.getNumPatchBytes();
1780 assert(NumBytes >= EncodedBytes &&
1781 "Patchpoint can't request size less than the length of a call.");
1782 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1783 "Invalid number of NOP bytes requested!");
1784 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1785 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1788void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
1789 const MachineInstr &
MI) {
1790 StatepointOpers SOpers(&
MI);
1791 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1792 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1793 for (
unsigned i = 0; i < PatchBytes; i += 4)
1794 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1797 const MachineOperand &CallTarget = SOpers.getCallTarget();
1798 MCOperand CallTargetMCOp;
1799 unsigned CallOpcode;
1800 switch (CallTarget.
getType()) {
1803 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1804 CallOpcode = AArch64::BL;
1808 CallOpcode = AArch64::BL;
1812 CallOpcode = AArch64::BLR;
1819 EmitToStreamer(OutStreamer,
1820 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1824 MCSymbol *MILabel = Ctx.createTempSymbol();
1826 SM.recordStatepoint(*MILabel,
MI);
1829void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1838 unsigned OperandsBeginIdx = 4;
1841 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1848 MI.setOpcode(Opcode);
1853 for (
const MachineOperand &MO :
1856 lowerOperand(MO, Dest);
1857 MI.addOperand(Dest);
1865 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1867 .addReg(AArch64::XZR)
1872void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1873 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1874 EmitToStreamer(*OutStreamer,
1875 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1881void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1882 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1883 EmitToStreamer(*OutStreamer,
1884 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1893 bool IsZeroDisc = Disc == AArch64::XZR;
1905 EmitToStreamer(AUTInst);
1910 bool IsZeroDisc = Disc == AArch64::XZR;
1922 EmitToStreamer(PACInst);
1927 bool IsZeroDisc = Disc == AArch64::XZR;
1937 EmitToStreamer(Inst);
1940void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1941 Register DestReg =
MI.getOperand(0).getReg();
1942 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1943 if (STI->hasZeroCycleZeroingFPR64()) {
1945 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1946 if (AArch64::FPR16RegClass.
contains(DestReg))
1947 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1948 &AArch64::FPR64RegClass);
1949 else if (AArch64::FPR32RegClass.
contains(DestReg))
1950 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1951 &AArch64::FPR64RegClass);
1959 EmitToStreamer(*OutStreamer, MOVI);
1960 ++NumZCZeroingInstrsFPR;
1961 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1963 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1964 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1965 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1966 &AArch64::FPR128RegClass);
1967 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1968 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1969 &AArch64::FPR128RegClass);
1972 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1973 &AArch64::FPR128RegClass);
1980 EmitToStreamer(*OutStreamer, MOVI);
1981 ++NumZCZeroingInstrsFPR;
1983 emitFMov0AsFMov(
MI, DestReg);
1986 emitFMov0AsFMov(
MI, DestReg);
1990void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1993 switch (
MI.getOpcode()) {
1996 case AArch64::FMOVH0:
1997 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1998 if (!STI->hasFullFP16())
1999 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
2003 case AArch64::FMOVS0:
2008 case AArch64::FMOVD0:
2014 EmitToStreamer(*OutStreamer, FMov);
2017Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint64_t Disc,
2020 bool MayClobberAddrDisc) {
2021 assert(isPtrauthRegSafe(ScratchReg) &&
2022 "Safe scratch register must be provided by the caller");
2026 if (AddrDisc == AArch64::NoRegister)
2027 AddrDisc = AArch64::XZR;
2035 if (AddrDisc == AArch64::XZR) {
2036 emitMOVZ(ScratchReg, Disc, 0);
2043 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2044 ScratchReg = AddrDisc;
2046 emitMovXReg(ScratchReg, AddrDisc);
2047 assert(ScratchReg != AddrDisc &&
2048 "Forbidden to clobber AddrDisc, but have to");
2051 emitMOVK(ScratchReg, Disc, 48);
2065void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2097 if (Method == AuthCheckMethod::None)
2099 if (Method == AuthCheckMethod::DummyLoad) {
2100 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2104 assert(!OnFailure &&
"DummyLoad always traps on error");
2108 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2109 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2111 emitMovXReg(ScratchReg, TestedReg);
2113 if (Method == AuthCheckMethod::XPAC) {
2117 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2122 assert(TestedReg == AArch64::LR &&
2123 "XPACHint mode is only compatible with checking the LR register");
2125 "XPACHint mode is only compatible with I-keys");
2126 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2130 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2131 .addReg(AArch64::XZR)
2138 MCInstBuilder(AArch64::Bcc)
2141 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2143 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2150 MCInstBuilder(AArch64::TBZX)
2161 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2175 case AuthCheckMethod::XPACHint:
2178 case AuthCheckMethod::XPAC:
2180 emitMovXReg(TestedReg, ScratchReg);
2187 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2192 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2204void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2208 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2209 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2212 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2216 "Neither x16 nor x17 is available as a scratch register");
2219 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2223bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2229 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2232 MCSymbol *Dot = OutContext.createTempSymbol();
2237 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2243AArch64AsmPrinter::PtrAuthSchema::PtrAuthSchema(
2245 :
Key(
Key), IntDisc(IntDisc), AddrDisc(AddrDiscOp.
getReg()),
2246 AddrDiscIsKilled(AddrDiscOp.isKill()) {}
2248void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2253 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2263 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2265 MCInstBuilder(AArch64::ADDXri)
2268 .addImm((Addend >> BitPos) & 0xfff)
2274 emitMOVZ(Scratch, Addend & 0xffff, 0);
2276 if (
unsigned Fragment = (Addend >>
Offset) & 0xffff)
2277 emitMOVK(Scratch, Fragment,
Offset);
2281 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2288 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2294 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2301void AArch64AsmPrinter::emitPtrauthAuthResign(
2303 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2305 const bool IsResign = SignSchema.has_value();
2318 bool ShouldCheck =
true;
2325 ShouldCheck = ShouldTrap =
false;
2332 ShouldCheck = ShouldTrap =
false;
2339 ShouldCheck = ShouldTrap =
true;
2345 emitPtrauthDiscriminator(AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2346 AuthSchema.AddrDiscIsKilled);
2348 if (!emitDeactivationSymbolRelocation(DS))
2349 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2352 if (!IsResign && (!ShouldCheck || !ShouldTrap))
2358 if (IsResign && !ShouldTrap)
2359 EndSym = createTempSymbol(
"resign_end_");
2361 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2362 AArch64PAuth::AuthCheckMethod::XPAC,
2372 if (Addend.has_value())
2373 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2376 Register PACDiscReg = emitPtrauthDiscriminator(SignSchema->IntDisc,
2377 SignSchema->AddrDisc, Scratch);
2378 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2385void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2388 uint64_t Disc =
MI->getOperand(3).getImm();
2389 Register AddrDisc =
MI->getOperand(4).getReg();
2390 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2394 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2395 assert(ScratchReg != AddrDisc &&
2396 "Neither X16 nor X17 is available as a scratch register");
2399 Register DiscReg = emitPtrauthDiscriminator(
2400 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2402 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2405 emitPAC(
Key, Val, DiscReg);
2408void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2409 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2410 unsigned BrTarget =
MI->getOperand(0).getReg();
2413 uint64_t Disc =
MI->getOperand(2).getImm();
2415 unsigned AddrDisc =
MI->getOperand(3).getReg();
2421 if (BrTarget == AddrDisc)
2438 bool AddrDiscIsImplicitDef =
2439 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2440 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2441 AddrDiscIsImplicitDef);
2442 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2445void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2448 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2449 const bool IsNeg = Addend < 0;
2451 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2454 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2457 .addImm((AbsOffset >> BitPos) & 0xfff)
2461 const uint64_t UAddend = Addend;
2462 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2464 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2466 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2467 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2468 uint64_t Shifted = UAddend >> BitPos;
2470 return Shifted != 0;
2471 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2472 if (((Shifted >>
I) & 0xffff) != 0xffff)
2476 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2477 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2479 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2488void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2489 MCRegister Tmp,
bool DSOLocal,
2490 const MCSubtargetInfo &STI) {
2496 MCInstBuilder(AArch64::ADRP)
2500 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2510 MCInstBuilder(AArch64::ADRP)
2515 MCInstBuilder(AArch64::LDRXui)
2526 if (!TT.isOSBinFormatELF())
2530 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2531 TT.isOSDragonFly() || TT.isOSNetBSD();
2585const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2587 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2588 const Triple &
TT = TM.getTargetTriple();
2600 auto STI = std::make_unique<AArch64Subtarget>(
2601 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2603 this->STI = STI.get();
2609 const MCSymbolELF *Group =
2624 .addReg(AArch64::X0)
2629 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2631 if (HasAddressDiversity) {
2636 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2640 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2642 "' out of range [0, 0xFFFF]");
2644 emitMOVZ(AArch64::X1, Disc, 0);
2651 auto *PrePACInstExpr =
2663 const MCSymbolRefExpr *EmuPACRef =
2665 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2672 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2681AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2682 MCContext &Ctx = OutContext;
2687 getDataLayout(),
Offset,
true);
2707 const MCExpr *DSExpr =
nullptr;
2719 "' out of range [0, " +
2727 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2729 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2734 "' out of range [0, 0xFFFF]");
2740 "expressions on this target");
2747void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2748 unsigned DstReg =
MI.getOperand(0).getReg();
2749 const MachineOperand &GAOp =
MI.getOperand(1);
2750 const uint64_t KeyC =
MI.getOperand(2).getImm();
2752 "key is out of range [0, AArch64PACKey::LAST]");
2754 const uint64_t Disc =
MI.getOperand(3).getImm();
2756 "constant discriminator is out of range [0, 0xffff]");
2765 if (TM.getTargetTriple().isOSBinFormatELF()) {
2767 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2770 "non-zero offset for $auth_ptr$ stub slots is not supported");
2772 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2774 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2775 "LOADauthptrstatic is implemented only for MachO/ELF");
2777 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2778 getObjFileLowering());
2781 "non-zero offset for $auth_ptr$ stub slots is not supported");
2783 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2786 MachineOperand StubMOHi =
2790 MCOperand StubMCHi, StubMCLo;
2797 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2799 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2805void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2806 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2807 const bool IsELFSignedGOT =
MI.getParent()
2809 ->getInfo<AArch64FunctionInfo>()
2810 ->hasELFSignedGOT();
2811 MachineOperand GAOp =
MI.getOperand(0);
2812 const uint64_t KeyC =
MI.getOperand(1).getImm();
2814 "key is out of range [0, AArch64PACKey::LAST]");
2816 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2817 const uint64_t Disc =
MI.getOperand(3).getImm();
2864 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2865 MCOperand GAMCHi, GAMCLo;
2878 MCInstBuilder(AArch64::ADRP)
2879 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2883 if (IsELFSignedGOT) {
2884 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2885 .addReg(AArch64::X17)
2886 .addReg(AArch64::X17)
2890 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2891 .addReg(AArch64::X16)
2892 .addReg(AArch64::X17)
2900 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2902 if (!STI->hasFPAC())
2903 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2904 AArch64PAuth::AuthCheckMethod::XPAC);
2906 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2907 .addReg(AArch64::X16)
2908 .addReg(AArch64::X16)
2912 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2913 .addReg(AArch64::X16)
2914 .addReg(AArch64::X16)
2919 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2920 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2922 emitPAC(
Key, AArch64::X16, DiscReg);
2925void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2927 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2928 const MachineOperand &GAMO =
MI.getOperand(1);
2935 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2936 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2937 .addReg(AuthResultReg)
2938 .addReg(AArch64::X17)
2941 MachineOperand GAHiOp(GAMO);
2942 MachineOperand GALoOp(GAMO);
2946 MCOperand GAMCHi, GAMCLo;
2951 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2953 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2954 .addReg(AArch64::X17)
2955 .addReg(AArch64::X17)
2959 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2960 .addReg(AuthResultReg)
2961 .addReg(AArch64::X17)
2968 UndefWeakSym = createTempSymbol(
"undef_weak");
2970 MCInstBuilder(AArch64::CBZX)
2971 .addReg(AuthResultReg)
2979 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2984 if (!STI->hasFPAC()) {
2985 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2986 AArch64PAuth::AuthCheckMethod::XPAC);
2988 emitMovXReg(DstReg, AuthResultReg);
2993AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2997 if (std::optional<uint16_t> BADisc =
2998 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3005void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3009 switch (
MI->getOpcode()) {
3012 case AArch64::CBBAssertExt:
3016 case AArch64::CBHAssertExt:
3020 case AArch64::CBWPrr:
3023 case AArch64::CBXPrr:
3026 case AArch64::CBWPri:
3030 case AArch64::CBXPri:
3038 bool NeedsRegSwap =
false;
3039 bool NeedsImmDec =
false;
3040 bool NeedsImmInc =
false;
3042#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3044 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3046 ? AArch64::CBB##RegCond##Wrr \
3047 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3048 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3049 : AArch64::CB##RegCond##Xrr))))
3065 NeedsImmDec = IsImm;
3069 NeedsRegSwap = !IsImm;
3076 NeedsRegSwap = !IsImm;
3077 NeedsImmInc = IsImm;
3081 NeedsImmDec = IsImm;
3085 NeedsRegSwap = !IsImm;
3092 NeedsRegSwap = !IsImm;
3093 NeedsImmInc = IsImm;
3101 MCOperand Lhs, Rhs, Trgt;
3102 lowerOperand(
MI->getOperand(1), Lhs);
3103 lowerOperand(
MI->getOperand(2), Rhs);
3104 lowerOperand(
MI->getOperand(3), Trgt);
3108 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3109 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3112 }
else if (NeedsImmDec) {
3116 }
else if (NeedsImmInc) {
3126 "CB immediate operand out-of-bounds");
3129 EmitToStreamer(*OutStreamer, Inst);
3134#include "AArch64GenMCPseudoLowering.inc"
3136void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3143void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3144 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3149 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3154 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3155 EmitToStreamer(*OutStreamer, OutInst);
3159 if (
MI->getOpcode() == AArch64::ADRP) {
3160 for (
auto &Opd :
MI->operands()) {
3161 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3162 "swift_async_extendedFramePointerFlags") {
3163 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3170 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3172 LOHInstToLabel[
MI] = LOHLabel;
3176 AArch64TargetStreamer *TS =
3179 switch (
MI->getOpcode()) {
3182 "Unhandled tail call instruction");
3184 case AArch64::HINT: {
3189 if (CurrentPatchableFunctionEntrySym &&
3190 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3192 int64_t
Imm =
MI->getOperand(0).getImm();
3193 if ((Imm & 32) && (Imm & 6)) {
3195 MCInstLowering.
Lower(
MI, Inst);
3196 EmitToStreamer(*OutStreamer, Inst);
3197 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3198 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3204 case AArch64::MOVMCSym: {
3205 Register DestReg =
MI->getOperand(0).getReg();
3206 const MachineOperand &MO_Sym =
MI->getOperand(1);
3207 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3208 MCOperand Hi_MCSym, Lo_MCSym;
3221 EmitToStreamer(*OutStreamer, MovZ);
3229 EmitToStreamer(*OutStreamer, MovK);
3232 case AArch64::MOVIv2d_ns:
3240 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3241 MI->getOperand(1).getImm() == 0) {
3243 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3246 EmitToStreamer(*OutStreamer, TmpInst);
3251 case AArch64::DBG_VALUE:
3252 case AArch64::DBG_VALUE_LIST:
3254 SmallString<128> TmpStr;
3255 raw_svector_ostream OS(TmpStr);
3256 PrintDebugValueComment(
MI, OS);
3261 case AArch64::EMITBKEY: {
3263 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3264 ExceptionHandlingType != ExceptionHandling::ARM)
3267 if (getFunctionCFISectionType(*MF) == CFISection::None)
3274 case AArch64::EMITMTETAGGED: {
3276 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3277 ExceptionHandlingType != ExceptionHandling::ARM)
3280 if (getFunctionCFISectionType(*MF) != CFISection::None)
3285 case AArch64::AUTx16x17: {
3287 const Register Scratch = AArch64::X17;
3290 MI->getOperand(1).getImm(),
MI->getOperand(2));
3292 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3293 std::nullopt,
MI->getDeactivationSymbol());
3297 case AArch64::AUTxMxN: {
3299 const Register Scratch =
MI->getOperand(1).getReg();
3302 MI->getOperand(4).getImm(),
MI->getOperand(5));
3304 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3305 std::nullopt,
MI->getDeactivationSymbol());
3309 case AArch64::AUTPAC: {
3311 const Register Scratch = AArch64::X17;
3314 MI->getOperand(1).getImm(),
MI->getOperand(2));
3317 MI->getOperand(4).getImm(),
MI->getOperand(5));
3319 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3320 std::nullopt,
MI->getDeactivationSymbol());
3324 case AArch64::AUTRELLOADPAC: {
3326 const Register Scratch = AArch64::X17;
3329 MI->getOperand(1).getImm(),
MI->getOperand(2));
3332 MI->getOperand(4).getImm(),
MI->getOperand(5));
3334 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3335 MI->getOperand(6).getImm(),
3336 MI->getDeactivationSymbol());
3342 emitPtrauthSign(
MI);
3345 case AArch64::LOADauthptrstatic:
3346 LowerLOADauthptrstatic(*
MI);
3349 case AArch64::LOADgotPAC:
3350 case AArch64::MOVaddrPAC:
3351 LowerMOVaddrPAC(*
MI);
3354 case AArch64::LOADgotAUTH:
3355 LowerLOADgotAUTH(*
MI);
3360 emitPtrauthBranch(
MI);
3366 case AArch64::AUTH_TCRETURN:
3367 case AArch64::AUTH_TCRETURN_BTI: {
3370 const uint64_t Disc =
MI->getOperand(3).getImm();
3372 Register AddrDisc =
MI->getOperand(4).getReg();
3374 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3376 emitPtrauthTailCallHardening(
MI);
3379 if (Callee == AddrDisc)
3386 bool AddrDiscIsImplicitDef =
3387 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3388 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3389 AddrDiscIsImplicitDef);
3390 emitBLRA(
false,
Key, Callee, DiscReg);
3394 case AArch64::TCRETURNri:
3395 case AArch64::TCRETURNrix16x17:
3396 case AArch64::TCRETURNrix17:
3397 case AArch64::TCRETURNrinotx16:
3398 case AArch64::TCRETURNriALL: {
3399 emitPtrauthTailCallHardening(
MI);
3401 recordIfImportCall(
MI);
3405 EmitToStreamer(*OutStreamer, TmpInst);
3408 case AArch64::TCRETURNdi: {
3409 emitPtrauthTailCallHardening(
MI);
3413 recordIfImportCall(
MI);
3417 EmitToStreamer(*OutStreamer, TmpInst);
3420 case AArch64::SpeculationBarrierISBDSBEndBB: {
3425 EmitToStreamer(*OutStreamer, TmpInstDSB);
3429 EmitToStreamer(*OutStreamer, TmpInstISB);
3432 case AArch64::SpeculationBarrierSBEndBB: {
3436 EmitToStreamer(*OutStreamer, TmpInstSB);
3439 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3446 const MachineOperand &MO_Sym =
MI->getOperand(0);
3447 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3448 MCOperand SymTLSDescLo12, SymTLSDesc;
3451 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3458 EmitToStreamer(*OutStreamer, Adrp);
3466 EmitToStreamer(*OutStreamer, Ldr);
3469 Add.setOpcode(AArch64::ADDXri);
3472 Add.addOperand(SymTLSDescLo12);
3474 EmitToStreamer(*OutStreamer,
Add);
3483 EmitToStreamer(*OutStreamer, Blraa);
3487 case AArch64::TLSDESC_CALLSEQ: {
3495 const MachineOperand &MO_Sym =
MI->getOperand(0);
3496 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3497 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3501 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3508 EmitToStreamer(*OutStreamer, Adrp);
3511 if (STI->isTargetILP32()) {
3521 EmitToStreamer(*OutStreamer, Ldr);
3524 if (STI->isTargetILP32()) {
3525 Add.setOpcode(AArch64::ADDWri);
3529 Add.setOpcode(AArch64::ADDXri);
3533 Add.addOperand(SymTLSDescLo12);
3535 EmitToStreamer(*OutStreamer,
Add);
3540 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3542 EmitToStreamer(*OutStreamer, TLSDescCall);
3550 EmitToStreamer(*OutStreamer, Blr);
3555 case AArch64::JumpTableDest32:
3556 case AArch64::JumpTableDest16:
3557 case AArch64::JumpTableDest8:
3558 LowerJumpTableDest(*OutStreamer, *
MI);
3561 case AArch64::BR_JumpTable:
3562 LowerHardenedBRJumpTable(*
MI);
3565 case AArch64::FMOVH0:
3566 case AArch64::FMOVS0:
3567 case AArch64::FMOVD0:
3571 case AArch64::MOPSMemoryCopyPseudo:
3572 case AArch64::MOPSMemoryMovePseudo:
3573 case AArch64::MOPSMemorySetPseudo:
3574 case AArch64::MOPSMemorySetTaggingPseudo:
3575 LowerMOPS(*OutStreamer, *
MI);
3578 case TargetOpcode::STACKMAP:
3579 return LowerSTACKMAP(*OutStreamer,
SM, *
MI);
3581 case TargetOpcode::PATCHPOINT:
3582 return LowerPATCHPOINT(*OutStreamer,
SM, *
MI);
3584 case TargetOpcode::STATEPOINT:
3585 return LowerSTATEPOINT(*OutStreamer,
SM, *
MI);
3587 case TargetOpcode::FAULTING_OP:
3588 return LowerFAULTING_OP(*
MI);
3590 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3591 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3594 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3595 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3598 case TargetOpcode::PATCHABLE_TAIL_CALL:
3599 LowerPATCHABLE_TAIL_CALL(*
MI);
3601 case TargetOpcode::PATCHABLE_EVENT_CALL:
3602 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3603 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3604 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3606 case AArch64::KCFI_CHECK:
3607 LowerKCFI_CHECK(*
MI);
3610 case AArch64::HWASAN_CHECK_MEMACCESS:
3611 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3612 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3613 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3614 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3617 case AArch64::SEH_StackAlloc:
3621 case AArch64::SEH_SaveFPLR:
3625 case AArch64::SEH_SaveFPLR_X:
3626 assert(
MI->getOperand(0).getImm() < 0 &&
3627 "Pre increment SEH opcode must have a negative offset");
3631 case AArch64::SEH_SaveReg:
3633 MI->getOperand(1).getImm());
3636 case AArch64::SEH_SaveReg_X:
3637 assert(
MI->getOperand(1).getImm() < 0 &&
3638 "Pre increment SEH opcode must have a negative offset");
3640 -
MI->getOperand(1).getImm());
3643 case AArch64::SEH_SaveRegP:
3644 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3645 MI->getOperand(0).getImm() <= 28) {
3646 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3647 "Register paired with LR must be odd");
3649 MI->getOperand(2).getImm());
3652 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3653 "Non-consecutive registers not allowed for save_regp");
3655 MI->getOperand(2).getImm());
3658 case AArch64::SEH_SaveRegP_X:
3659 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3660 "Non-consecutive registers not allowed for save_regp_x");
3661 assert(
MI->getOperand(2).getImm() < 0 &&
3662 "Pre increment SEH opcode must have a negative offset");
3664 -
MI->getOperand(2).getImm());
3667 case AArch64::SEH_SaveFReg:
3669 MI->getOperand(1).getImm());
3672 case AArch64::SEH_SaveFReg_X:
3673 assert(
MI->getOperand(1).getImm() < 0 &&
3674 "Pre increment SEH opcode must have a negative offset");
3676 -
MI->getOperand(1).getImm());
3679 case AArch64::SEH_SaveFRegP:
3680 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3681 "Non-consecutive registers not allowed for save_regp");
3683 MI->getOperand(2).getImm());
3686 case AArch64::SEH_SaveFRegP_X:
3687 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3688 "Non-consecutive registers not allowed for save_regp_x");
3689 assert(
MI->getOperand(2).getImm() < 0 &&
3690 "Pre increment SEH opcode must have a negative offset");
3692 -
MI->getOperand(2).getImm());
3695 case AArch64::SEH_SetFP:
3699 case AArch64::SEH_AddFP:
3703 case AArch64::SEH_Nop:
3707 case AArch64::SEH_PrologEnd:
3711 case AArch64::SEH_EpilogStart:
3715 case AArch64::SEH_EpilogEnd:
3719 case AArch64::SEH_PACSignLR:
3723 case AArch64::SEH_SaveAnyRegI:
3724 assert(
MI->getOperand(1).getImm() <= 1008 &&
3725 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3727 MI->getOperand(1).getImm());
3730 case AArch64::SEH_SaveAnyRegIP:
3731 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3732 "Non-consecutive registers not allowed for save_any_reg");
3733 assert(
MI->getOperand(2).getImm() <= 1008 &&
3734 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3736 MI->getOperand(2).getImm());
3739 case AArch64::SEH_SaveAnyRegQP:
3740 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3741 "Non-consecutive registers not allowed for save_any_reg");
3742 assert(
MI->getOperand(2).getImm() >= 0 &&
3743 "SaveAnyRegQP SEH opcode offset must be non-negative");
3744 assert(
MI->getOperand(2).getImm() <= 1008 &&
3745 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3747 MI->getOperand(2).getImm());
3750 case AArch64::SEH_SaveAnyRegQPX:
3751 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3752 "Non-consecutive registers not allowed for save_any_reg");
3753 assert(
MI->getOperand(2).getImm() < 0 &&
3754 "SaveAnyRegQPX SEH opcode offset must be negative");
3755 assert(
MI->getOperand(2).getImm() >= -1008 &&
3756 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3758 -
MI->getOperand(2).getImm());
3761 case AArch64::SEH_AllocZ:
3762 assert(
MI->getOperand(0).getImm() >= 0 &&
3763 "AllocZ SEH opcode offset must be non-negative");
3764 assert(
MI->getOperand(0).getImm() <= 255 &&
3765 "AllocZ SEH opcode offset must fit into 8 bits");
3769 case AArch64::SEH_SaveZReg:
3770 assert(
MI->getOperand(1).getImm() >= 0 &&
3771 "SaveZReg SEH opcode offset must be non-negative");
3772 assert(
MI->getOperand(1).getImm() <= 255 &&
3773 "SaveZReg SEH opcode offset must fit into 8 bits");
3775 MI->getOperand(1).getImm());
3778 case AArch64::SEH_SavePReg:
3779 assert(
MI->getOperand(1).getImm() >= 0 &&
3780 "SavePReg SEH opcode offset must be non-negative");
3781 assert(
MI->getOperand(1).getImm() <= 255 &&
3782 "SavePReg SEH opcode offset must fit into 8 bits");
3784 MI->getOperand(1).getImm());
3789 recordIfImportCall(
MI);
3791 MCInstLowering.
Lower(
MI, TmpInst);
3792 EmitToStreamer(*OutStreamer, TmpInst);
3795 case AArch64::CBWPri:
3796 case AArch64::CBXPri:
3797 case AArch64::CBBAssertExt:
3798 case AArch64::CBHAssertExt:
3799 case AArch64::CBWPrr:
3800 case AArch64::CBXPrr:
3801 emitCBPseudoExpansion(
MI);
3805 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3810 MCInstLowering.
Lower(
MI, TmpInst);
3811 EmitToStreamer(*OutStreamer, TmpInst);
3814void AArch64AsmPrinter::recordIfImportCall(
3815 const llvm::MachineInstr *BranchInst) {
3816 if (!EnableImportCallOptimization)
3820 if (GV && GV->hasDLLImportStorageClass()) {
3821 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3826 .push_back({CallSiteSymbol, CalledSymbol});
3830void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3831 MCSymbol *LazyPointer) {
3848 EmitToStreamer(Adrp);
3856 MCOperand SymPageOff;
3863 EmitToStreamer(Ldr);
3866 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3867 .addReg(AArch64::X16)
3868 .addReg(AArch64::X16)
3871 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3873 .addReg(AArch64::X16));
3876void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3877 const GlobalIFunc &GI,
3878 MCSymbol *LazyPointer) {
3910 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3911 .addReg(AArch64::SP)
3912 .addReg(AArch64::FP)
3913 .addReg(AArch64::LR)
3914 .addReg(AArch64::SP)
3917 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3918 .addReg(AArch64::FP)
3919 .addReg(AArch64::SP)
3923 for (
int I = 0;
I != 4; ++
I)
3924 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3925 .addReg(AArch64::SP)
3926 .addReg(AArch64::X1 + 2 *
I)
3927 .addReg(AArch64::X0 + 2 *
I)
3928 .addReg(AArch64::SP)
3931 for (
int I = 0;
I != 4; ++
I)
3932 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3933 .addReg(AArch64::SP)
3934 .addReg(AArch64::D1 + 2 *
I)
3935 .addReg(AArch64::D0 + 2 *
I)
3936 .addReg(AArch64::SP)
3940 MCInstBuilder(AArch64::BL)
3953 EmitToStreamer(Adrp);
3961 MCOperand SymPageOff;
3968 EmitToStreamer(Ldr);
3971 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3972 .addReg(AArch64::X0)
3973 .addReg(AArch64::X16)
3976 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3977 .addReg(AArch64::X16)
3978 .addReg(AArch64::X0)
3982 for (
int I = 3;
I != -1; --
I)
3983 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3984 .addReg(AArch64::SP)
3985 .addReg(AArch64::D1 + 2 *
I)
3986 .addReg(AArch64::D0 + 2 *
I)
3987 .addReg(AArch64::SP)
3990 for (
int I = 3;
I != -1; --
I)
3991 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3992 .addReg(AArch64::SP)
3993 .addReg(AArch64::X1 + 2 *
I)
3994 .addReg(AArch64::X0 + 2 *
I)
3995 .addReg(AArch64::SP)
3998 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3999 .addReg(AArch64::SP)
4000 .addReg(AArch64::FP)
4001 .addReg(AArch64::LR)
4002 .addReg(AArch64::SP)
4005 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4007 .addReg(AArch64::X16));
4010const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4011 const Constant *BaseCV,
4021char AArch64AsmPrinter::ID = 0;
4024 "AArch64 Assembly Printer",
false,
false)
4028LLVMInitializeAArch64AsmPrinter() {
static cl::opt< PtrauthCheckMode > PtrauthAuthChecks("aarch64-ptrauth-auth-checks", cl::Hidden, cl::values(clEnumValN(Unchecked, "none", "don't test for failure"), clEnumValN(Poison, "poison", "poison on failure"), clEnumValN(Trap, "trap", "trap on failure")), cl::desc("Check pointer authentication auth/resign failures"), cl::init(Default))
#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond)
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
static bool targetSupportsIRelativeRelocation(const Triple &TT)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_EXTERNAL_VISIBILITY
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
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
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr unsigned SM(unsigned Version)
#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 make_scope_exit function, which executes user-defined cleanup logic at scope ex...
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)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool printAsmMRegister(const X86AsmPrinter &P, const MachineOperand &MO, char Mode, raw_ostream &O)
static const AArch64AuthMCExpr * create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, bool HasAddressDiversity, MCContext &Ctx, SMLoc Loc=SMLoc())
const SetOfInstructions & getLOHRelated() const
unsigned getJumpTableEntrySize(int Idx) const
MCSymbol * getJumpTableEntryPCRelSymbol(int Idx) const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
std::optional< std::string > getOutliningStyle() const
const MILOHContainer & getLOHContainer() const
void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym)
bool shouldSignWithBKey() const
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MCSymbol * GetGlobalValueSymbol(const GlobalValue *GV, unsigned TargetFlags) const
void Lower(const MachineInstr *MI, MCInst &OutMI) const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
virtual void emitARM64WinCFISaveRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset)
virtual void emitAttributesSubsection(StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, AArch64BuildAttributes::SubsectionType ParameterType)
Build attributes implementation.
virtual void emitARM64WinCFISavePReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPACSignLR()
virtual void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFIAllocStack(unsigned Size)
virtual void emitARM64WinCFISaveFPLRX(int Offset)
virtual void emitARM64WinCFIAllocZ(int Offset)
virtual void emitDirectiveVariantPCS(MCSymbol *Symbol)
Callback used to implement the .variant_pcs directive.
virtual void emitARM64WinCFIAddFP(unsigned Size)
virtual void emitARM64WinCFISaveFPLR(int Offset)
virtual void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISetFP()
virtual void emitARM64WinCFIEpilogEnd()
virtual void emitARM64WinCFISaveZReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPrologEnd()
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFINop()
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
virtual void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, std::string String)
virtual void emitARM64WinCFIEpilogStart()
virtual void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset)
void setPreservesAll()
Set by analyses that do not transform their input at all.
const T & front() const
front - Get the first element.
bool empty() const
empty - Check if the array is empty.
This class is intended to be used as a driving class for all asm writers.
virtual void emitGlobalAlias(const Module &M, const GlobalAlias &GA)
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
virtual const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
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
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
@ AddrDiscriminator_CtorsDtors
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
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.
void recordFaultingOp(FaultKind FaultTy, const MCSymbol *FaultingLabel, const MCSymbol *HandlerLabel)
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
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
LLVM_ABI MCSymbol * createLinkerPrivateSymbol(const Twine &Name)
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
MCSection * getDataSection() const
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
static constexpr unsigned NonUniqueID
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
virtual void emitCFIBKeyFrame()
virtual bool popSection()
Restore the current and previous section from the section stack.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc={})
Record a relocation described by the .reloc directive.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCFIMTETaggedFrame()
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
void pushSection()
Save the current and previous section on the section stack.
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
MCSection * getCurrentSectionOnly() const
void emitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ....
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
const MCSymbol * getAddSym() const
int64_t getConstant() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
CalledGlobalInfo tryGetCalledGlobal(const MachineInstr *MI) const
Tries to get the global and target flags for a call site, if the instruction is a call to a global.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
ExprStubListTy getAuthGVStubList()
ExprStubListTy getAuthGVStubList()
unsigned getSubReg() const
static MachineOperand CreateMCSymbol(MCSymbol *Sym, unsigned TargetFlags=0)
const GlobalValue * getGlobal() const
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const BlockAddress * getBlockAddress() const
void setOffset(int64_t Offset)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
int64_t getOffset() const
Return the offset from the symbol in this operand.
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
Wrapper class representing virtual and physical registers.
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)
constexpr const char * data() const
data - 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.
MCRegister getRegister(unsigned i) const
Return the specified register in the class.
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.
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
AuthCheckMethod
Variants of check performed on an authenticated pointer.
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))
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ GNU_PROPERTY_AARCH64_FEATURE_1_BTI
@ GNU_PROPERTY_AARCH64_FEATURE_1_PAC
@ GNU_PROPERTY_AARCH64_FEATURE_1_GCS
@ S_REGULAR
S_REGULAR - Regular section.
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
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.
FunctionAddr VTableAddr Value
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
scope_exit(Callable) -> scope_exit< Callable >
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
std::string utostr(uint64_t X, bool isNeg=false)
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,...
Target & getTheAArch64leTarget()
auto dyn_cast_or_null(const Y &Val)
Target & getTheAArch64_32Target()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static unsigned getAUTOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return AUT opcode to be used for a ptrauth auth using the given key, or its AUT*Z variant that doesn'...
@ MCSA_WeakAntiDep
.weak_anti_dep (COFF)
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
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,...