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");
691 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
692 "patchable-function-prefix");
695 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
696 .addReg(ScratchRegs[0])
698 .addImm(-(PrefixNops * 4 + 4)));
702 const int64_t
Type =
MI.getOperand(1).getImm();
703 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
704 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
707 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
708 .addReg(AArch64::WZR)
709 .addReg(ScratchRegs[0])
710 .addReg(ScratchRegs[1])
714 EmitToStreamer(*OutStreamer,
715 MCInstBuilder(AArch64::Bcc)
724 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
728 AddrIndex = AddrReg - AArch64::X0;
738 assert(AddrIndex < 31 && TypeIndex < 31);
740 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
741 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
742 OutStreamer->emitLabel(
Pass);
745void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
753 if (
Reg == AArch64::XZR)
757 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
759 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
760 uint32_t AccessInfo =
MI.getOperand(1).getImm();
762 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
764 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
765 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
767 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
768 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
771 if (!TM.getTargetTriple().isOSBinFormatELF())
774 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
777 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
779 SymName +=
"_short_v2";
780 Sym = OutContext.getOrCreateSymbol(SymName);
783 EmitToStreamer(*OutStreamer,
784 MCInstBuilder(AArch64::BL)
788void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
789 if (HwasanMemaccessSymbols.empty())
792 const Triple &
TT = TM.getTargetTriple();
796 auto STI = std::make_unique<AArch64Subtarget>(
797 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
799 this->STI = STI.get();
802 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
804 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
806 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
808 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
811 for (
auto &
P : HwasanMemaccessSymbols) {
812 unsigned Reg = std::get<0>(
P.first);
813 bool IsShort = std::get<1>(
P.first);
814 uint32_t AccessInfo = std::get<2>(
P.first);
815 bool IsFixedShadow = std::get<3>(
P.first);
816 uint64_t FixedShadowOffset = std::get<4>(
P.first);
817 const MCSymbolRefExpr *HwasanTagMismatchRef =
818 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
821 bool HasMatchAllTag =
823 uint8_t MatchAllTag =
830 OutStreamer->switchSection(OutContext.getELFSection(
836 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
837 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
838 OutStreamer->emitLabel(Sym);
840 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
841 .addReg(AArch64::X16)
851 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
852 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
853 .addReg(AArch64::W16)
854 .addReg(AArch64::X17)
855 .addReg(AArch64::X16)
859 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
860 .addReg(AArch64::W16)
861 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
862 .addReg(AArch64::X16)
867 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
868 .addReg(AArch64::XZR)
869 .addReg(AArch64::X16)
872 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
873 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
876 HandleMismatchOrPartialSym, OutContext)));
877 MCSymbol *ReturnSym = OutContext.createTempSymbol();
878 OutStreamer->emitLabel(ReturnSym);
879 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
880 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
882 if (HasMatchAllTag) {
883 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
884 .addReg(AArch64::X17)
888 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
889 .addReg(AArch64::XZR)
890 .addReg(AArch64::X17)
894 MCInstBuilder(AArch64::Bcc)
900 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
901 .addReg(AArch64::WZR)
902 .addReg(AArch64::W16)
905 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
907 MCInstBuilder(AArch64::Bcc)
911 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
912 .addReg(AArch64::X17)
916 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
917 .addReg(AArch64::X17)
918 .addReg(AArch64::X17)
921 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
922 .addReg(AArch64::WZR)
923 .addReg(AArch64::W16)
924 .addReg(AArch64::W17)
927 MCInstBuilder(AArch64::Bcc)
931 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
932 .addReg(AArch64::X16)
935 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
936 .addReg(AArch64::W16)
937 .addReg(AArch64::X16)
940 MCInstBuilder(AArch64::SUBSXrs)
941 .addReg(AArch64::XZR)
942 .addReg(AArch64::X16)
946 MCInstBuilder(AArch64::Bcc)
950 OutStreamer->emitLabel(HandleMismatchSym);
953 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
959 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
965 if (
Reg != AArch64::X0)
966 emitMovXReg(AArch64::X0,
Reg);
973 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
978 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
979 .addReg(AArch64::X16)
983 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
984 .addReg(AArch64::X16)
985 .addReg(AArch64::X16)
989 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
997 const MCExpr *StubAuthPtrRef) {
1000 OutStreamer.
emitValue(StubAuthPtrRef, 8);
1003void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
1004 emitHwasanMemaccessSymbols(M);
1006 const Triple &
TT = TM.getTargetTriple();
1007 if (
TT.isOSBinFormatMachO()) {
1009 MachineModuleInfoMachO &MMIMacho =
1010 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1014 if (!Stubs.empty()) {
1016 OutStreamer->switchSection(
1019 emitAlignment(
Align(8));
1021 for (
const auto &Stub : Stubs)
1024 OutStreamer->addBlankLine();
1032 OutStreamer->emitSubsectionsViaSymbols();
1035 if (
TT.isOSBinFormatELF()) {
1037 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1041 if (!Stubs.empty()) {
1042 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1044 emitAlignment(
Align(8));
1046 for (
const auto &Stub : Stubs)
1049 OutStreamer->addBlankLine();
1060 M.getModuleFlag(
"ptrauth-elf-got"));
1061 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1062 for (
const GlobalValue &GV :
M.global_values())
1064 !GV.getName().starts_with(
"llvm."))
1065 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1074 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1075 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1078 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1079 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1090 for (
auto &[Section, CallsToImportedFuncs] :
1091 SectionToImportedFunctionCalls) {
1093 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1094 OutStreamer->emitInt32(SectionSize);
1095 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1096 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1098 OutStreamer->emitInt32(0x13);
1099 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1100 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1106void AArch64AsmPrinter::emitLOHs() {
1110 for (
const MachineInstr *
MI :
D.getArgs()) {
1111 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1112 assert(LabelIt != LOHInstToLabel.end() &&
1113 "Label hasn't been inserted for LOH related instruction");
1116 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1121void AArch64AsmPrinter::emitFunctionBodyEnd() {
1127MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1131 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1132 return OutContext.getOrCreateSymbol(
1133 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1134 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1139void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1141 const MachineOperand &MO =
MI->getOperand(OpNum);
1157 PrintSymbolOperand(MO, O);
1168bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1192bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1193 const TargetRegisterClass *RC,
1194 unsigned AltName, raw_ostream &O) {
1195 assert(MO.
isReg() &&
"Should only get here with a register!");
1196 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1205bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1206 const char *ExtraCode, raw_ostream &O) {
1207 const MachineOperand &MO =
MI->getOperand(OpNum);
1214 if (ExtraCode && ExtraCode[0]) {
1215 if (ExtraCode[1] != 0)
1218 switch (ExtraCode[0]) {
1226 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1239 const TargetRegisterClass *RC;
1240 switch (ExtraCode[0]) {
1242 RC = &AArch64::FPR8RegClass;
1245 RC = &AArch64::FPR16RegClass;
1248 RC = &AArch64::FPR32RegClass;
1251 RC = &AArch64::FPR64RegClass;
1254 RC = &AArch64::FPR128RegClass;
1257 RC = &AArch64::ZPRRegClass;
1262 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1283 unsigned AltName = AArch64::NoRegAltName;
1284 const TargetRegisterClass *RegClass;
1286 RegClass = &AArch64::ZPRRegClass;
1288 RegClass = &AArch64::PPRRegClass;
1290 RegClass = &AArch64::PNRRegClass;
1292 RegClass = &AArch64::FPR128RegClass;
1293 AltName = AArch64::vreg;
1297 return printAsmRegInClass(MO, RegClass, AltName, O);
1304bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1306 const char *ExtraCode,
1308 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1311 const MachineOperand &MO =
MI->getOperand(OpNum);
1312 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1317void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1319 unsigned NOps =
MI->getNumOperands();
1321 OS <<
'\t' << MAI.getCommentString() <<
"DEBUG_VALUE: ";
1323 OS <<
MI->getDebugVariable()->getName();
1326 assert(
MI->isIndirectDebugValue());
1338void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1339 ArrayRef<unsigned> JumpTableIndices) {
1341 if (JumpTableIndices.
empty())
1343 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1347 MCSection *ReadOnlySec =
nullptr;
1348 if (TM.Options.EnableStaticDataPartitioning) {
1354 OutStreamer->switchSection(ReadOnlySec);
1356 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1357 for (
unsigned JTI : JumpTableIndices) {
1358 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1361 if (JTBBs.empty())
continue;
1363 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1365 OutStreamer->emitLabel(GetJTISymbol(JTI));
1370 for (
auto *JTBB : JTBBs) {
1371 const MCExpr *
Value =
1390AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1391 const MachineInstr *BranchInstr,
1392 const MCSymbol *BranchLabel)
const {
1393 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1396 switch (AFI->getJumpTableEntrySize(JTI)) {
1398 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1401 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1404 EntrySize = codeview::JumpTableEntrySize::Int32;
1409 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1412void AArch64AsmPrinter::emitFunctionEntryLabel() {
1413 const Triple &
TT = TM.getTargetTriple();
1414 if (
TT.isOSBinFormatELF() &&
1417 CallingConv::AArch64_SVE_VectorCall ||
1418 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1420 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1431 OutStreamer->emitAssignment(
1435 auto getSymbolFromMetadata = [&](StringRef
Name) {
1439 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1446 for (MDNode *Node : UnmangledNames) {
1448 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1449 if (std::optional<std::string> MangledName =
1452 MMI->getContext().getOrCreateSymbol(*MangledName);
1453 emitFunctionAlias(UnmangledSym, ECMangledSym);
1456 if (MCSymbol *ECMangledSym =
1457 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1458 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1462void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1463 const Constant *CV) {
1465 if (CPA->hasAddressDiscriminator() &&
1466 !CPA->hasSpecialAddressDiscriminator(
1469 "unexpected address discrimination value for ctors/dtors entry, only "
1470 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1479void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1480 const GlobalAlias &GA) {
1486 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1488 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1491 OutStreamer->beginCOFFSymbolDef(ExpSym);
1495 OutStreamer->endCOFFSymbolDef();
1497 OutStreamer->beginCOFFSymbolDef(Sym);
1501 OutStreamer->endCOFFSymbolDef();
1502 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1503 OutStreamer->emitAssignment(
1520void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1521 const llvm::MachineInstr &
MI) {
1522 Register DestReg =
MI.getOperand(0).getReg();
1523 Register ScratchReg =
MI.getOperand(1).getReg();
1525 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1526 Register TableReg =
MI.getOperand(2).getReg();
1527 Register EntryReg =
MI.getOperand(3).getReg();
1528 int JTIdx =
MI.getOperand(4).getIndex();
1534 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1545 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1547 .addExpr(LabelExpr));
1552 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1553 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1554 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1559 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1560 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1564 .addImm(
Size == 1 ? 0 : 1));
1568 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1572 .addImm(
Size == 4 ? 0 : 2));
1575void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1577 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1579 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1580 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1596 MachineOperand JTOp =
MI.getOperand(0);
1600 "unsupported compressed jump table");
1602 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1606 uint64_t MaxTableEntry = NumTableEntries - 1;
1608 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1609 .addReg(AArch64::XZR)
1610 .addReg(AArch64::X16)
1611 .addImm(MaxTableEntry)
1614 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1619 if ((MaxTableEntry >>
Offset) == 0)
1621 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1624 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1625 .addReg(AArch64::XZR)
1626 .addReg(AArch64::X16)
1627 .addReg(AArch64::X17)
1633 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1634 .addReg(AArch64::X16)
1635 .addReg(AArch64::X16)
1636 .addReg(AArch64::XZR)
1640 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1641 MCOperand JTMCHi, JTMCLo;
1651 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1653 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1654 .addReg(AArch64::X17)
1655 .addReg(AArch64::X17)
1659 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1660 .addReg(AArch64::X16)
1661 .addReg(AArch64::X17)
1662 .addReg(AArch64::X16)
1673 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1675 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1676 .addReg(AArch64::X16)
1677 .addReg(AArch64::X17)
1678 .addReg(AArch64::X16)
1681 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1684void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1685 const llvm::MachineInstr &
MI) {
1686 unsigned Opcode =
MI.getOpcode();
1688 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1690 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1691 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1692 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1693 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1694 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1695 if (Opcode == AArch64::MOPSMemorySetPseudo)
1696 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1697 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1698 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1701 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1702 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1704 for (
auto Op :
Ops) {
1706 auto MCIB = MCInstBuilder(
Op);
1708 MCIB.addReg(
MI.getOperand(i++).getReg());
1709 MCIB.addReg(
MI.getOperand(i++).getReg());
1711 MCIB.addReg(
MI.getOperand(i++).getReg());
1713 MCIB.addReg(
MI.getOperand(i++).getReg());
1714 MCIB.addReg(
MI.getOperand(i++).getReg());
1715 MCIB.addReg(
MI.getOperand(i++).getReg());
1717 EmitToStreamer(OutStreamer, MCIB);
1721void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &
SM,
1722 const MachineInstr &
MI) {
1723 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1726 MCSymbol *MILabel = Ctx.createTempSymbol();
1729 SM.recordStackMap(*MILabel,
MI);
1730 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1733 const MachineBasicBlock &
MBB = *
MI.getParent();
1736 while (NumNOPBytes > 0) {
1737 if (MII ==
MBB.
end() || MII->isCall() ||
1738 MII->getOpcode() == AArch64::DBG_VALUE ||
1739 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1740 MII->getOpcode() == TargetOpcode::STACKMAP)
1747 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1748 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1753void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
1754 const MachineInstr &
MI) {
1756 MCSymbol *MILabel = Ctx.createTempSymbol();
1758 SM.recordPatchPoint(*MILabel,
MI);
1760 PatchPointOpers Opers(&
MI);
1762 int64_t CallTarget = Opers.getCallTarget().getImm();
1763 unsigned EncodedBytes = 0;
1765 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1766 "High 16 bits of call target should be zero.");
1767 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1770 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1771 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1772 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1773 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1776 unsigned NumBytes = Opers.getNumPatchBytes();
1777 assert(NumBytes >= EncodedBytes &&
1778 "Patchpoint can't request size less than the length of a call.");
1779 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1780 "Invalid number of NOP bytes requested!");
1781 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1782 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1785void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
1786 const MachineInstr &
MI) {
1787 StatepointOpers SOpers(&
MI);
1788 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1789 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1790 for (
unsigned i = 0; i < PatchBytes; i += 4)
1791 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1794 const MachineOperand &CallTarget = SOpers.getCallTarget();
1795 MCOperand CallTargetMCOp;
1796 unsigned CallOpcode;
1797 switch (CallTarget.
getType()) {
1800 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1801 CallOpcode = AArch64::BL;
1805 CallOpcode = AArch64::BL;
1809 CallOpcode = AArch64::BLR;
1816 EmitToStreamer(OutStreamer,
1817 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1821 MCSymbol *MILabel = Ctx.createTempSymbol();
1823 SM.recordStatepoint(*MILabel,
MI);
1826void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1835 unsigned OperandsBeginIdx = 4;
1838 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1845 MI.setOpcode(Opcode);
1850 for (
const MachineOperand &MO :
1853 lowerOperand(MO, Dest);
1854 MI.addOperand(Dest);
1862 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1864 .addReg(AArch64::XZR)
1869void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1870 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1871 EmitToStreamer(*OutStreamer,
1872 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1878void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1879 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1880 EmitToStreamer(*OutStreamer,
1881 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1890 bool IsZeroDisc = Disc == AArch64::XZR;
1902 EmitToStreamer(AUTInst);
1907 bool IsZeroDisc = Disc == AArch64::XZR;
1919 EmitToStreamer(PACInst);
1924 bool IsZeroDisc = Disc == AArch64::XZR;
1934 EmitToStreamer(Inst);
1937void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1938 Register DestReg =
MI.getOperand(0).getReg();
1939 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1940 if (STI->hasZeroCycleZeroingFPR64()) {
1942 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1943 if (AArch64::FPR16RegClass.
contains(DestReg))
1944 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1945 &AArch64::FPR64RegClass);
1946 else if (AArch64::FPR32RegClass.
contains(DestReg))
1947 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1948 &AArch64::FPR64RegClass);
1956 EmitToStreamer(*OutStreamer, MOVI);
1957 ++NumZCZeroingInstrsFPR;
1958 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1960 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1961 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1962 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1963 &AArch64::FPR128RegClass);
1964 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1965 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1966 &AArch64::FPR128RegClass);
1969 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1970 &AArch64::FPR128RegClass);
1977 EmitToStreamer(*OutStreamer, MOVI);
1978 ++NumZCZeroingInstrsFPR;
1980 emitFMov0AsFMov(
MI, DestReg);
1983 emitFMov0AsFMov(
MI, DestReg);
1987void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1990 switch (
MI.getOpcode()) {
1993 case AArch64::FMOVH0:
1994 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1995 if (!STI->hasFullFP16())
1996 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
2000 case AArch64::FMOVS0:
2005 case AArch64::FMOVD0:
2011 EmitToStreamer(*OutStreamer, FMov);
2014Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint64_t Disc,
2017 bool MayClobberAddrDisc) {
2018 assert(isPtrauthRegSafe(ScratchReg) &&
2019 "Safe scratch register must be provided by the caller");
2023 if (AddrDisc == AArch64::NoRegister)
2024 AddrDisc = AArch64::XZR;
2032 if (AddrDisc == AArch64::XZR) {
2033 emitMOVZ(ScratchReg, Disc, 0);
2040 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2041 ScratchReg = AddrDisc;
2043 emitMovXReg(ScratchReg, AddrDisc);
2044 assert(ScratchReg != AddrDisc &&
2045 "Forbidden to clobber AddrDisc, but have to");
2048 emitMOVK(ScratchReg, Disc, 48);
2062void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2094 if (Method == AuthCheckMethod::None)
2096 if (Method == AuthCheckMethod::DummyLoad) {
2097 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2101 assert(!OnFailure &&
"DummyLoad always traps on error");
2105 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2106 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2108 emitMovXReg(ScratchReg, TestedReg);
2110 if (Method == AuthCheckMethod::XPAC) {
2114 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2119 assert(TestedReg == AArch64::LR &&
2120 "XPACHint mode is only compatible with checking the LR register");
2122 "XPACHint mode is only compatible with I-keys");
2123 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2127 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2128 .addReg(AArch64::XZR)
2135 MCInstBuilder(AArch64::Bcc)
2138 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2140 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2147 MCInstBuilder(AArch64::TBZX)
2158 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2172 case AuthCheckMethod::XPACHint:
2175 case AuthCheckMethod::XPAC:
2177 emitMovXReg(TestedReg, ScratchReg);
2184 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2189 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2201void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2205 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2206 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2209 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2213 "Neither x16 nor x17 is available as a scratch register");
2216 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2220bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2226 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2229 MCSymbol *Dot = OutContext.createTempSymbol();
2234 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2240AArch64AsmPrinter::PtrAuthSchema::PtrAuthSchema(
2242 :
Key(
Key), IntDisc(IntDisc), AddrDisc(AddrDiscOp.
getReg()),
2243 AddrDiscIsKilled(AddrDiscOp.isKill()) {}
2245void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2250 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2260 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2262 MCInstBuilder(AArch64::ADDXri)
2265 .addImm((Addend >> BitPos) & 0xfff)
2271 emitMOVZ(Scratch, Addend & 0xffff, 0);
2273 if (
unsigned Fragment = (Addend >>
Offset) & 0xffff)
2274 emitMOVK(Scratch, Fragment,
Offset);
2278 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2285 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2291 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2298void AArch64AsmPrinter::emitPtrauthAuthResign(
2300 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2302 const bool IsResign = SignSchema.has_value();
2315 bool ShouldCheck =
true;
2322 ShouldCheck = ShouldTrap =
false;
2329 ShouldCheck = ShouldTrap =
false;
2336 ShouldCheck = ShouldTrap =
true;
2342 emitPtrauthDiscriminator(AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2343 AuthSchema.AddrDiscIsKilled);
2345 if (!emitDeactivationSymbolRelocation(DS))
2346 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2349 if (!IsResign && (!ShouldCheck || !ShouldTrap))
2355 if (IsResign && !ShouldTrap)
2356 EndSym = createTempSymbol(
"resign_end_");
2358 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2359 AArch64PAuth::AuthCheckMethod::XPAC,
2369 if (Addend.has_value())
2370 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2373 Register PACDiscReg = emitPtrauthDiscriminator(SignSchema->IntDisc,
2374 SignSchema->AddrDisc, Scratch);
2375 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2382void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2385 uint64_t Disc =
MI->getOperand(3).getImm();
2386 Register AddrDisc =
MI->getOperand(4).getReg();
2387 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2391 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2392 assert(ScratchReg != AddrDisc &&
2393 "Neither X16 nor X17 is available as a scratch register");
2396 Register DiscReg = emitPtrauthDiscriminator(
2397 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2399 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2402 emitPAC(
Key, Val, DiscReg);
2405void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2406 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2407 unsigned BrTarget =
MI->getOperand(0).getReg();
2410 uint64_t Disc =
MI->getOperand(2).getImm();
2412 unsigned AddrDisc =
MI->getOperand(3).getReg();
2418 if (BrTarget == AddrDisc)
2435 bool AddrDiscIsImplicitDef =
2436 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2437 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2438 AddrDiscIsImplicitDef);
2439 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2442void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2445 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2446 const bool IsNeg = Addend < 0;
2448 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2451 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2454 .addImm((AbsOffset >> BitPos) & 0xfff)
2458 const uint64_t UAddend = Addend;
2459 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2461 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2463 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2464 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2465 uint64_t Shifted = UAddend >> BitPos;
2467 return Shifted != 0;
2468 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2469 if (((Shifted >>
I) & 0xffff) != 0xffff)
2473 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2474 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2476 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2485void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2486 MCRegister Tmp,
bool DSOLocal,
2487 const MCSubtargetInfo &STI) {
2493 MCInstBuilder(AArch64::ADRP)
2497 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2507 MCInstBuilder(AArch64::ADRP)
2512 MCInstBuilder(AArch64::LDRXui)
2523 if (!TT.isOSBinFormatELF())
2527 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2528 TT.isOSDragonFly() || TT.isOSNetBSD();
2582const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2584 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2585 const Triple &
TT = TM.getTargetTriple();
2597 auto STI = std::make_unique<AArch64Subtarget>(
2598 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2600 this->STI = STI.get();
2606 const MCSymbolELF *Group =
2621 .addReg(AArch64::X0)
2626 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2628 if (HasAddressDiversity) {
2633 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2637 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2639 "' out of range [0, 0xFFFF]");
2641 emitMOVZ(AArch64::X1, Disc, 0);
2648 auto *PrePACInstExpr =
2660 const MCSymbolRefExpr *EmuPACRef =
2662 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2669 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2678AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2679 MCContext &Ctx = OutContext;
2684 getDataLayout(),
Offset,
true);
2704 const MCExpr *DSExpr =
nullptr;
2716 "' out of range [0, " +
2724 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2726 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2731 "' out of range [0, 0xFFFF]");
2737 "expressions on this target");
2744void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2745 unsigned DstReg =
MI.getOperand(0).getReg();
2746 const MachineOperand &GAOp =
MI.getOperand(1);
2747 const uint64_t KeyC =
MI.getOperand(2).getImm();
2749 "key is out of range [0, AArch64PACKey::LAST]");
2751 const uint64_t Disc =
MI.getOperand(3).getImm();
2753 "constant discriminator is out of range [0, 0xffff]");
2762 if (TM.getTargetTriple().isOSBinFormatELF()) {
2764 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2767 "non-zero offset for $auth_ptr$ stub slots is not supported");
2769 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2771 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2772 "LOADauthptrstatic is implemented only for MachO/ELF");
2774 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2775 getObjFileLowering());
2778 "non-zero offset for $auth_ptr$ stub slots is not supported");
2780 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2783 MachineOperand StubMOHi =
2787 MCOperand StubMCHi, StubMCLo;
2794 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2796 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2802void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2803 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2804 const bool IsELFSignedGOT =
MI.getParent()
2806 ->getInfo<AArch64FunctionInfo>()
2807 ->hasELFSignedGOT();
2808 MachineOperand GAOp =
MI.getOperand(0);
2809 const uint64_t KeyC =
MI.getOperand(1).getImm();
2811 "key is out of range [0, AArch64PACKey::LAST]");
2813 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2814 const uint64_t Disc =
MI.getOperand(3).getImm();
2861 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2862 MCOperand GAMCHi, GAMCLo;
2875 MCInstBuilder(AArch64::ADRP)
2876 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2880 if (IsELFSignedGOT) {
2881 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2882 .addReg(AArch64::X17)
2883 .addReg(AArch64::X17)
2887 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2888 .addReg(AArch64::X16)
2889 .addReg(AArch64::X17)
2897 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2899 if (!STI->hasFPAC())
2900 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2901 AArch64PAuth::AuthCheckMethod::XPAC);
2903 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2904 .addReg(AArch64::X16)
2905 .addReg(AArch64::X16)
2909 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2910 .addReg(AArch64::X16)
2911 .addReg(AArch64::X16)
2916 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2917 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2919 emitPAC(
Key, AArch64::X16, DiscReg);
2922void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2924 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2925 const MachineOperand &GAMO =
MI.getOperand(1);
2932 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2933 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2934 .addReg(AuthResultReg)
2935 .addReg(AArch64::X17)
2938 MachineOperand GAHiOp(GAMO);
2939 MachineOperand GALoOp(GAMO);
2943 MCOperand GAMCHi, GAMCLo;
2948 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2950 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2951 .addReg(AArch64::X17)
2952 .addReg(AArch64::X17)
2956 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2957 .addReg(AuthResultReg)
2958 .addReg(AArch64::X17)
2965 UndefWeakSym = createTempSymbol(
"undef_weak");
2967 MCInstBuilder(AArch64::CBZX)
2968 .addReg(AuthResultReg)
2976 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2981 if (!STI->hasFPAC()) {
2982 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2983 AArch64PAuth::AuthCheckMethod::XPAC);
2985 emitMovXReg(DstReg, AuthResultReg);
2990AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2994 if (std::optional<uint16_t> BADisc =
2995 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3002void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3006 switch (
MI->getOpcode()) {
3009 case AArch64::CBBAssertExt:
3013 case AArch64::CBHAssertExt:
3017 case AArch64::CBWPrr:
3020 case AArch64::CBXPrr:
3023 case AArch64::CBWPri:
3027 case AArch64::CBXPri:
3035 bool NeedsRegSwap =
false;
3036 bool NeedsImmDec =
false;
3037 bool NeedsImmInc =
false;
3039#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3041 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3043 ? AArch64::CBB##RegCond##Wrr \
3044 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3045 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3046 : AArch64::CB##RegCond##Xrr))))
3062 NeedsImmDec = IsImm;
3066 NeedsRegSwap = !IsImm;
3073 NeedsRegSwap = !IsImm;
3074 NeedsImmInc = IsImm;
3078 NeedsImmDec = IsImm;
3082 NeedsRegSwap = !IsImm;
3089 NeedsRegSwap = !IsImm;
3090 NeedsImmInc = IsImm;
3098 MCOperand Lhs, Rhs, Trgt;
3099 lowerOperand(
MI->getOperand(1), Lhs);
3100 lowerOperand(
MI->getOperand(2), Rhs);
3101 lowerOperand(
MI->getOperand(3), Trgt);
3105 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3106 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3109 }
else if (NeedsImmDec) {
3113 }
else if (NeedsImmInc) {
3123 "CB immediate operand out-of-bounds");
3126 EmitToStreamer(*OutStreamer, Inst);
3131#include "AArch64GenMCPseudoLowering.inc"
3133void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3140void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3141 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3146 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3151 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3152 EmitToStreamer(*OutStreamer, OutInst);
3156 if (
MI->getOpcode() == AArch64::ADRP) {
3157 for (
auto &Opd :
MI->operands()) {
3158 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3159 "swift_async_extendedFramePointerFlags") {
3160 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3167 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3169 LOHInstToLabel[
MI] = LOHLabel;
3173 AArch64TargetStreamer *TS =
3176 switch (
MI->getOpcode()) {
3179 "Unhandled tail call instruction");
3181 case AArch64::HINT: {
3186 if (CurrentPatchableFunctionEntrySym &&
3187 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3189 int64_t
Imm =
MI->getOperand(0).getImm();
3190 if ((Imm & 32) && (Imm & 6)) {
3192 MCInstLowering.
Lower(
MI, Inst);
3193 EmitToStreamer(*OutStreamer, Inst);
3194 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3195 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3201 case AArch64::MOVMCSym: {
3202 Register DestReg =
MI->getOperand(0).getReg();
3203 const MachineOperand &MO_Sym =
MI->getOperand(1);
3204 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3205 MCOperand Hi_MCSym, Lo_MCSym;
3218 EmitToStreamer(*OutStreamer, MovZ);
3226 EmitToStreamer(*OutStreamer, MovK);
3229 case AArch64::MOVIv2d_ns:
3237 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3238 MI->getOperand(1).getImm() == 0) {
3240 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3243 EmitToStreamer(*OutStreamer, TmpInst);
3248 case AArch64::DBG_VALUE:
3249 case AArch64::DBG_VALUE_LIST:
3251 SmallString<128> TmpStr;
3252 raw_svector_ostream OS(TmpStr);
3253 PrintDebugValueComment(
MI, OS);
3258 case AArch64::EMITBKEY: {
3260 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3261 ExceptionHandlingType != ExceptionHandling::ARM)
3264 if (getFunctionCFISectionType(*MF) == CFISection::None)
3271 case AArch64::EMITMTETAGGED: {
3273 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3274 ExceptionHandlingType != ExceptionHandling::ARM)
3277 if (getFunctionCFISectionType(*MF) != CFISection::None)
3282 case AArch64::AUTx16x17: {
3284 const Register Scratch = AArch64::X17;
3287 MI->getOperand(1).getImm(),
MI->getOperand(2));
3289 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3290 std::nullopt,
MI->getDeactivationSymbol());
3294 case AArch64::AUTxMxN: {
3296 const Register Scratch =
MI->getOperand(1).getReg();
3299 MI->getOperand(4).getImm(),
MI->getOperand(5));
3301 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3302 std::nullopt,
MI->getDeactivationSymbol());
3306 case AArch64::AUTPAC: {
3308 const Register Scratch = AArch64::X17;
3311 MI->getOperand(1).getImm(),
MI->getOperand(2));
3314 MI->getOperand(4).getImm(),
MI->getOperand(5));
3316 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3317 std::nullopt,
MI->getDeactivationSymbol());
3321 case AArch64::AUTRELLOADPAC: {
3323 const Register Scratch = AArch64::X17;
3326 MI->getOperand(1).getImm(),
MI->getOperand(2));
3329 MI->getOperand(4).getImm(),
MI->getOperand(5));
3331 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3332 MI->getOperand(6).getImm(),
3333 MI->getDeactivationSymbol());
3339 emitPtrauthSign(
MI);
3342 case AArch64::LOADauthptrstatic:
3343 LowerLOADauthptrstatic(*
MI);
3346 case AArch64::LOADgotPAC:
3347 case AArch64::MOVaddrPAC:
3348 LowerMOVaddrPAC(*
MI);
3351 case AArch64::LOADgotAUTH:
3352 LowerLOADgotAUTH(*
MI);
3357 emitPtrauthBranch(
MI);
3363 case AArch64::AUTH_TCRETURN:
3364 case AArch64::AUTH_TCRETURN_BTI: {
3367 const uint64_t Disc =
MI->getOperand(3).getImm();
3369 Register AddrDisc =
MI->getOperand(4).getReg();
3371 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3373 emitPtrauthTailCallHardening(
MI);
3376 if (Callee == AddrDisc)
3383 bool AddrDiscIsImplicitDef =
3384 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3385 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3386 AddrDiscIsImplicitDef);
3387 emitBLRA(
false,
Key, Callee, DiscReg);
3391 case AArch64::TCRETURNri:
3392 case AArch64::TCRETURNrix16x17:
3393 case AArch64::TCRETURNrix17:
3394 case AArch64::TCRETURNrinotx16:
3395 case AArch64::TCRETURNriALL: {
3396 emitPtrauthTailCallHardening(
MI);
3398 recordIfImportCall(
MI);
3402 EmitToStreamer(*OutStreamer, TmpInst);
3405 case AArch64::TCRETURNdi: {
3406 emitPtrauthTailCallHardening(
MI);
3410 recordIfImportCall(
MI);
3414 EmitToStreamer(*OutStreamer, TmpInst);
3417 case AArch64::SpeculationBarrierISBDSBEndBB: {
3422 EmitToStreamer(*OutStreamer, TmpInstDSB);
3426 EmitToStreamer(*OutStreamer, TmpInstISB);
3429 case AArch64::SpeculationBarrierSBEndBB: {
3433 EmitToStreamer(*OutStreamer, TmpInstSB);
3436 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3443 const MachineOperand &MO_Sym =
MI->getOperand(0);
3444 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3445 MCOperand SymTLSDescLo12, SymTLSDesc;
3448 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3455 EmitToStreamer(*OutStreamer, Adrp);
3463 EmitToStreamer(*OutStreamer, Ldr);
3466 Add.setOpcode(AArch64::ADDXri);
3469 Add.addOperand(SymTLSDescLo12);
3471 EmitToStreamer(*OutStreamer,
Add);
3480 EmitToStreamer(*OutStreamer, Blraa);
3484 case AArch64::TLSDESC_CALLSEQ: {
3492 const MachineOperand &MO_Sym =
MI->getOperand(0);
3493 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3494 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3498 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3505 EmitToStreamer(*OutStreamer, Adrp);
3508 if (STI->isTargetILP32()) {
3518 EmitToStreamer(*OutStreamer, Ldr);
3521 if (STI->isTargetILP32()) {
3522 Add.setOpcode(AArch64::ADDWri);
3526 Add.setOpcode(AArch64::ADDXri);
3530 Add.addOperand(SymTLSDescLo12);
3532 EmitToStreamer(*OutStreamer,
Add);
3537 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3539 EmitToStreamer(*OutStreamer, TLSDescCall);
3547 EmitToStreamer(*OutStreamer, Blr);
3552 case AArch64::JumpTableDest32:
3553 case AArch64::JumpTableDest16:
3554 case AArch64::JumpTableDest8:
3555 LowerJumpTableDest(*OutStreamer, *
MI);
3558 case AArch64::BR_JumpTable:
3559 LowerHardenedBRJumpTable(*
MI);
3562 case AArch64::FMOVH0:
3563 case AArch64::FMOVS0:
3564 case AArch64::FMOVD0:
3568 case AArch64::MOPSMemoryCopyPseudo:
3569 case AArch64::MOPSMemoryMovePseudo:
3570 case AArch64::MOPSMemorySetPseudo:
3571 case AArch64::MOPSMemorySetTaggingPseudo:
3572 LowerMOPS(*OutStreamer, *
MI);
3575 case TargetOpcode::STACKMAP:
3576 return LowerSTACKMAP(*OutStreamer,
SM, *
MI);
3578 case TargetOpcode::PATCHPOINT:
3579 return LowerPATCHPOINT(*OutStreamer,
SM, *
MI);
3581 case TargetOpcode::STATEPOINT:
3582 return LowerSTATEPOINT(*OutStreamer,
SM, *
MI);
3584 case TargetOpcode::FAULTING_OP:
3585 return LowerFAULTING_OP(*
MI);
3587 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3588 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3591 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3592 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3595 case TargetOpcode::PATCHABLE_TAIL_CALL:
3596 LowerPATCHABLE_TAIL_CALL(*
MI);
3598 case TargetOpcode::PATCHABLE_EVENT_CALL:
3599 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3600 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3601 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3603 case AArch64::KCFI_CHECK:
3604 LowerKCFI_CHECK(*
MI);
3607 case AArch64::HWASAN_CHECK_MEMACCESS:
3608 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3609 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3610 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3611 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3614 case AArch64::SEH_StackAlloc:
3618 case AArch64::SEH_SaveFPLR:
3622 case AArch64::SEH_SaveFPLR_X:
3623 assert(
MI->getOperand(0).getImm() < 0 &&
3624 "Pre increment SEH opcode must have a negative offset");
3628 case AArch64::SEH_SaveReg:
3630 MI->getOperand(1).getImm());
3633 case AArch64::SEH_SaveReg_X:
3634 assert(
MI->getOperand(1).getImm() < 0 &&
3635 "Pre increment SEH opcode must have a negative offset");
3637 -
MI->getOperand(1).getImm());
3640 case AArch64::SEH_SaveRegP:
3641 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3642 MI->getOperand(0).getImm() <= 28) {
3643 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3644 "Register paired with LR must be odd");
3646 MI->getOperand(2).getImm());
3649 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3650 "Non-consecutive registers not allowed for save_regp");
3652 MI->getOperand(2).getImm());
3655 case AArch64::SEH_SaveRegP_X:
3656 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3657 "Non-consecutive registers not allowed for save_regp_x");
3658 assert(
MI->getOperand(2).getImm() < 0 &&
3659 "Pre increment SEH opcode must have a negative offset");
3661 -
MI->getOperand(2).getImm());
3664 case AArch64::SEH_SaveFReg:
3666 MI->getOperand(1).getImm());
3669 case AArch64::SEH_SaveFReg_X:
3670 assert(
MI->getOperand(1).getImm() < 0 &&
3671 "Pre increment SEH opcode must have a negative offset");
3673 -
MI->getOperand(1).getImm());
3676 case AArch64::SEH_SaveFRegP:
3677 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3678 "Non-consecutive registers not allowed for save_regp");
3680 MI->getOperand(2).getImm());
3683 case AArch64::SEH_SaveFRegP_X:
3684 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3685 "Non-consecutive registers not allowed for save_regp_x");
3686 assert(
MI->getOperand(2).getImm() < 0 &&
3687 "Pre increment SEH opcode must have a negative offset");
3689 -
MI->getOperand(2).getImm());
3692 case AArch64::SEH_SetFP:
3696 case AArch64::SEH_AddFP:
3700 case AArch64::SEH_Nop:
3704 case AArch64::SEH_PrologEnd:
3708 case AArch64::SEH_EpilogStart:
3712 case AArch64::SEH_EpilogEnd:
3716 case AArch64::SEH_PACSignLR:
3720 case AArch64::SEH_SaveAnyRegI:
3721 assert(
MI->getOperand(1).getImm() <= 1008 &&
3722 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3724 MI->getOperand(1).getImm());
3727 case AArch64::SEH_SaveAnyRegIP:
3728 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3729 "Non-consecutive registers not allowed for save_any_reg");
3730 assert(
MI->getOperand(2).getImm() <= 1008 &&
3731 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3733 MI->getOperand(2).getImm());
3736 case AArch64::SEH_SaveAnyRegQP:
3737 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3738 "Non-consecutive registers not allowed for save_any_reg");
3739 assert(
MI->getOperand(2).getImm() >= 0 &&
3740 "SaveAnyRegQP SEH opcode offset must be non-negative");
3741 assert(
MI->getOperand(2).getImm() <= 1008 &&
3742 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3744 MI->getOperand(2).getImm());
3747 case AArch64::SEH_SaveAnyRegQPX:
3748 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3749 "Non-consecutive registers not allowed for save_any_reg");
3750 assert(
MI->getOperand(2).getImm() < 0 &&
3751 "SaveAnyRegQPX SEH opcode offset must be negative");
3752 assert(
MI->getOperand(2).getImm() >= -1008 &&
3753 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3755 -
MI->getOperand(2).getImm());
3758 case AArch64::SEH_AllocZ:
3759 assert(
MI->getOperand(0).getImm() >= 0 &&
3760 "AllocZ SEH opcode offset must be non-negative");
3761 assert(
MI->getOperand(0).getImm() <= 255 &&
3762 "AllocZ SEH opcode offset must fit into 8 bits");
3766 case AArch64::SEH_SaveZReg:
3767 assert(
MI->getOperand(1).getImm() >= 0 &&
3768 "SaveZReg SEH opcode offset must be non-negative");
3769 assert(
MI->getOperand(1).getImm() <= 255 &&
3770 "SaveZReg SEH opcode offset must fit into 8 bits");
3772 MI->getOperand(1).getImm());
3775 case AArch64::SEH_SavePReg:
3776 assert(
MI->getOperand(1).getImm() >= 0 &&
3777 "SavePReg SEH opcode offset must be non-negative");
3778 assert(
MI->getOperand(1).getImm() <= 255 &&
3779 "SavePReg SEH opcode offset must fit into 8 bits");
3781 MI->getOperand(1).getImm());
3786 recordIfImportCall(
MI);
3788 MCInstLowering.
Lower(
MI, TmpInst);
3789 EmitToStreamer(*OutStreamer, TmpInst);
3792 case AArch64::CBWPri:
3793 case AArch64::CBXPri:
3794 case AArch64::CBBAssertExt:
3795 case AArch64::CBHAssertExt:
3796 case AArch64::CBWPrr:
3797 case AArch64::CBXPrr:
3798 emitCBPseudoExpansion(
MI);
3802 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3807 MCInstLowering.
Lower(
MI, TmpInst);
3808 EmitToStreamer(*OutStreamer, TmpInst);
3811void AArch64AsmPrinter::recordIfImportCall(
3812 const llvm::MachineInstr *BranchInst) {
3813 if (!EnableImportCallOptimization)
3817 if (GV && GV->hasDLLImportStorageClass()) {
3818 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3823 .push_back({CallSiteSymbol, CalledSymbol});
3827void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3828 MCSymbol *LazyPointer) {
3845 EmitToStreamer(Adrp);
3853 MCOperand SymPageOff;
3860 EmitToStreamer(Ldr);
3863 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3864 .addReg(AArch64::X16)
3865 .addReg(AArch64::X16)
3868 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3870 .addReg(AArch64::X16));
3873void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3874 const GlobalIFunc &GI,
3875 MCSymbol *LazyPointer) {
3907 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3908 .addReg(AArch64::SP)
3909 .addReg(AArch64::FP)
3910 .addReg(AArch64::LR)
3911 .addReg(AArch64::SP)
3914 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3915 .addReg(AArch64::FP)
3916 .addReg(AArch64::SP)
3920 for (
int I = 0;
I != 4; ++
I)
3921 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3922 .addReg(AArch64::SP)
3923 .addReg(AArch64::X1 + 2 *
I)
3924 .addReg(AArch64::X0 + 2 *
I)
3925 .addReg(AArch64::SP)
3928 for (
int I = 0;
I != 4; ++
I)
3929 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3930 .addReg(AArch64::SP)
3931 .addReg(AArch64::D1 + 2 *
I)
3932 .addReg(AArch64::D0 + 2 *
I)
3933 .addReg(AArch64::SP)
3937 MCInstBuilder(AArch64::BL)
3950 EmitToStreamer(Adrp);
3958 MCOperand SymPageOff;
3965 EmitToStreamer(Ldr);
3968 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3969 .addReg(AArch64::X0)
3970 .addReg(AArch64::X16)
3973 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3974 .addReg(AArch64::X16)
3975 .addReg(AArch64::X0)
3979 for (
int I = 3;
I != -1; --
I)
3980 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3981 .addReg(AArch64::SP)
3982 .addReg(AArch64::D1 + 2 *
I)
3983 .addReg(AArch64::D0 + 2 *
I)
3984 .addReg(AArch64::SP)
3987 for (
int I = 3;
I != -1; --
I)
3988 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3989 .addReg(AArch64::SP)
3990 .addReg(AArch64::X1 + 2 *
I)
3991 .addReg(AArch64::X0 + 2 *
I)
3992 .addReg(AArch64::SP)
3995 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3996 .addReg(AArch64::SP)
3997 .addReg(AArch64::FP)
3998 .addReg(AArch64::LR)
3999 .addReg(AArch64::SP)
4002 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4004 .addReg(AArch64::X16));
4007const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4008 const Constant *BaseCV,
4018char AArch64AsmPrinter::ID = 0;
4021 "AArch64 Assembly Printer",
false,
false)
4025LLVMInitializeAArch64AsmPrinter() {
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
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,...