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);
195 const MachineOperand *AUTAddrDisc,
197 std::optional<AArch64PACKey::ID> PACKey,
203 bool emitDeactivationSymbolRelocation(
Value *DS);
206 void emitPtrauthSign(
const MachineInstr *
MI);
230 bool MayClobberAddrDisc =
false);
233 void LowerLOADauthptrstatic(
const MachineInstr &
MI);
237 void LowerMOVaddrPAC(
const MachineInstr &
MI);
242 void LowerLOADgotAUTH(
const MachineInstr &
MI);
244 void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
245 void emitAddress(MCRegister
Reg,
const MCExpr *Expr, MCRegister Tmp,
246 bool DSOLocal,
const MCSubtargetInfo &STI);
248 const MCExpr *emitPAuthRelocationAsIRelative(
250 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
254 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
257 void emitAttributes(
unsigned Flags, uint64_t PAuthABIPlatform,
258 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
261 void emitCBPseudoExpansion(
const MachineInstr *
MI);
263 void EmitToStreamer(MCStreamer &S,
const MCInst &Inst);
264 void EmitToStreamer(
const MCInst &Inst) {
265 EmitToStreamer(*OutStreamer, Inst);
270 void emitFunctionHeaderComment()
override;
272 void getAnalysisUsage(AnalysisUsage &AU)
const override {
277 bool runOnMachineFunction(MachineFunction &MF)
override {
278 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
279 PSI = &PSIW->getPSI();
281 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
282 SDPI = &SDPIW->getStaticDataProfileInfo();
284 AArch64FI = MF.
getInfo<AArch64FunctionInfo>();
287 SetupMachineFunction(MF);
289 if (STI->isTargetCOFF()) {
296 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
297 OutStreamer->emitCOFFSymbolStorageClass(Scl);
298 OutStreamer->emitCOFFSymbolType(
Type);
299 OutStreamer->endCOFFSymbolDef();
313 const Constant *BaseCV =
nullptr,
314 uint64_t
Offset = 0)
override;
317 void printOperand(
const MachineInstr *
MI,
unsigned OpNum, raw_ostream &O);
319 bool printAsmRegInClass(
const MachineOperand &MO,
320 const TargetRegisterClass *RC,
unsigned AltName,
323 bool PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
324 const char *ExtraCode, raw_ostream &O)
override;
325 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
326 const char *ExtraCode, raw_ostream &O)
override;
328 void PrintDebugValueComment(
const MachineInstr *
MI, raw_ostream &OS);
330 void emitFunctionBodyEnd()
override;
331 void emitGlobalAlias(
const Module &M,
const GlobalAlias &GA)
override;
333 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
334 void emitEndOfAsmFile(
Module &M)
override;
336 AArch64FunctionInfo *AArch64FI =
nullptr;
342 void emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift);
343 void emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift);
351 void emitFMov0(
const MachineInstr &
MI);
352 void emitFMov0AsFMov(
const MachineInstr &
MI,
Register DestReg);
354 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
356 MInstToMCSymbol LOHInstToLabel;
358 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
359 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
362 const MCSubtargetInfo *getIFuncMCSubtargetInfo()
const override {
366 void emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
367 MCSymbol *LazyPointer)
override;
368 void emitMachOIFuncStubHelperBody(
Module &M,
const GlobalIFunc &GI,
369 MCSymbol *LazyPointer)
override;
374 void recordIfImportCall(
const MachineInstr *BranchInst);
379void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
380 const Triple &
TT = TM.getTargetTriple();
382 if (
TT.isOSBinFormatCOFF()) {
383 emitCOFFFeatureSymbol(M);
384 emitCOFFReplaceableFunctionData(M);
386 if (
M.getModuleFlag(
"import-call-optimization"))
387 EnableImportCallOptimization =
true;
390 if (!
TT.isOSBinFormatELF())
395 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
398 unsigned BAFlags = 0;
399 unsigned GNUFlags = 0;
401 M.getModuleFlag(
"branch-target-enforcement"))) {
402 if (!BTE->isZero()) {
403 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
409 M.getModuleFlag(
"guarded-control-stack"))) {
410 if (!GCS->isZero()) {
411 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
417 M.getModuleFlag(
"sign-return-address"))) {
418 if (!Sign->isZero()) {
419 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
424 uint64_t PAuthABIPlatform = -1;
426 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
427 PAuthABIPlatform = PAP->getZExtValue();
430 uint64_t PAuthABIVersion = -1;
432 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
433 PAuthABIVersion = PAV->getZExtValue();
437 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
439 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
442void AArch64AsmPrinter::emitFunctionHeaderComment() {
443 const AArch64FunctionInfo *FI = MF->
getInfo<AArch64FunctionInfo>();
445 if (OutlinerString != std::nullopt)
446 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
449void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
452 if (
F.hasFnAttribute(
"patchable-function-entry")) {
454 if (
F.getFnAttribute(
"patchable-function-entry")
456 .getAsInteger(10, Num))
462 emitSled(
MI, SledKind::FUNCTION_ENTER);
465void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
466 emitSled(
MI, SledKind::FUNCTION_EXIT);
469void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
470 emitSled(
MI, SledKind::TAIL_CALL);
473void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
474 static const int8_t NoopsInSledCount = 7;
495 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
496 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
497 OutStreamer->emitLabel(CurSled);
498 auto Target = OutContext.createTempSymbol();
503 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
505 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
506 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
508 OutStreamer->emitLabel(Target);
509 recordSled(CurSled,
MI, Kind, 2);
512void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
513 uint64_t PAuthABIPlatform,
514 uint64_t PAuthABIVersion,
515 AArch64TargetStreamer *TS) {
517 PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
518 PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
520 if (PAuthABIPlatform || PAuthABIVersion) {
524 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
525 AArch64BuildAttributes::SubsectionType::ULEB128);
529 PAuthABIPlatform,
"");
543 if (BTIValue || PACValue || GCSValue) {
547 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
548 AArch64BuildAttributes::SubsectionType::ULEB128);
576void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
578 auto &
O = *OutStreamer;
579 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
580 O.emitLabel(CurSled);
581 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
583 OutContext.getOrCreateSymbol(
584 Twine(MachO ?
"_" :
"") +
585 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
588 O.AddComment(
"Begin XRay typed event");
589 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
590 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
596 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
600 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
601 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
602 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
603 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
604 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
608 O.AddComment(
"End XRay typed event");
609 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
616 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
618 O.AddComment(
"Begin XRay custom event");
619 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
620 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
626 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
627 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
628 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
629 O.AddComment(
"End XRay custom event");
630 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
637 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
641void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
643 assert(std::next(
MI.getIterator())->isCall() &&
644 "KCFI_CHECK not followed by a call instruction");
645 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
646 "KCFI_CHECK call target doesn't match call operand");
650 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
651 if (AddrReg == AArch64::XZR) {
655 emitMovXReg(AddrReg, AArch64::XZR);
661 for (
auto &
Reg : ScratchRegs) {
667 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
668 "Invalid scratch registers for KCFI_CHECK");
672 int64_t PrefixNops = 0;
675 .getFnAttribute(
"patchable-function-prefix")
677 .getAsInteger(10, PrefixNops);
680 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
681 .addReg(ScratchRegs[0])
683 .addImm(-(PrefixNops * 4 + 4)));
687 const int64_t
Type =
MI.getOperand(1).getImm();
688 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
689 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
692 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
693 .addReg(AArch64::WZR)
694 .addReg(ScratchRegs[0])
695 .addReg(ScratchRegs[1])
699 EmitToStreamer(*OutStreamer,
700 MCInstBuilder(AArch64::Bcc)
709 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
713 AddrIndex = AddrReg - AArch64::X0;
723 assert(AddrIndex < 31 && TypeIndex < 31);
725 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
726 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
727 OutStreamer->emitLabel(
Pass);
730void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
738 if (
Reg == AArch64::XZR)
742 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
744 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
745 uint32_t AccessInfo =
MI.getOperand(1).getImm();
747 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
749 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
750 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
752 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
753 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
756 if (!TM.getTargetTriple().isOSBinFormatELF())
759 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
762 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
764 SymName +=
"_short_v2";
765 Sym = OutContext.getOrCreateSymbol(SymName);
768 EmitToStreamer(*OutStreamer,
769 MCInstBuilder(AArch64::BL)
773void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
774 if (HwasanMemaccessSymbols.empty())
777 const Triple &
TT = TM.getTargetTriple();
781 auto STI = std::make_unique<AArch64Subtarget>(
782 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
784 this->STI = STI.get();
787 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
789 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
791 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
793 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
796 for (
auto &
P : HwasanMemaccessSymbols) {
797 unsigned Reg = std::get<0>(
P.first);
798 bool IsShort = std::get<1>(
P.first);
799 uint32_t AccessInfo = std::get<2>(
P.first);
800 bool IsFixedShadow = std::get<3>(
P.first);
801 uint64_t FixedShadowOffset = std::get<4>(
P.first);
802 const MCSymbolRefExpr *HwasanTagMismatchRef =
803 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
806 bool HasMatchAllTag =
808 uint8_t MatchAllTag =
815 OutStreamer->switchSection(OutContext.getELFSection(
821 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
822 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
823 OutStreamer->emitLabel(Sym);
825 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
826 .addReg(AArch64::X16)
836 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
837 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
838 .addReg(AArch64::W16)
839 .addReg(AArch64::X17)
840 .addReg(AArch64::X16)
844 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
845 .addReg(AArch64::W16)
846 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
847 .addReg(AArch64::X16)
852 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
853 .addReg(AArch64::XZR)
854 .addReg(AArch64::X16)
857 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
858 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
861 HandleMismatchOrPartialSym, OutContext)));
862 MCSymbol *ReturnSym = OutContext.createTempSymbol();
863 OutStreamer->emitLabel(ReturnSym);
864 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
865 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
867 if (HasMatchAllTag) {
868 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
869 .addReg(AArch64::X17)
873 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
874 .addReg(AArch64::XZR)
875 .addReg(AArch64::X17)
879 MCInstBuilder(AArch64::Bcc)
885 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
886 .addReg(AArch64::WZR)
887 .addReg(AArch64::W16)
890 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
892 MCInstBuilder(AArch64::Bcc)
896 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
897 .addReg(AArch64::X17)
901 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
902 .addReg(AArch64::X17)
903 .addReg(AArch64::X17)
906 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
907 .addReg(AArch64::WZR)
908 .addReg(AArch64::W16)
909 .addReg(AArch64::W17)
912 MCInstBuilder(AArch64::Bcc)
916 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
917 .addReg(AArch64::X16)
920 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
921 .addReg(AArch64::W16)
922 .addReg(AArch64::X16)
925 MCInstBuilder(AArch64::SUBSXrs)
926 .addReg(AArch64::XZR)
927 .addReg(AArch64::X16)
931 MCInstBuilder(AArch64::Bcc)
935 OutStreamer->emitLabel(HandleMismatchSym);
938 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
944 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
950 if (
Reg != AArch64::X0)
951 emitMovXReg(AArch64::X0,
Reg);
958 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
963 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
964 .addReg(AArch64::X16)
968 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
969 .addReg(AArch64::X16)
970 .addReg(AArch64::X16)
974 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
982 const MCExpr *StubAuthPtrRef) {
985 OutStreamer.
emitValue(StubAuthPtrRef, 8);
988void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
989 emitHwasanMemaccessSymbols(M);
991 const Triple &
TT = TM.getTargetTriple();
992 if (
TT.isOSBinFormatMachO()) {
994 MachineModuleInfoMachO &MMIMacho =
995 MMI->getObjFileInfo<MachineModuleInfoMachO>();
999 if (!Stubs.empty()) {
1001 OutStreamer->switchSection(
1004 emitAlignment(
Align(8));
1006 for (
const auto &Stub : Stubs)
1009 OutStreamer->addBlankLine();
1017 OutStreamer->emitSubsectionsViaSymbols();
1020 if (
TT.isOSBinFormatELF()) {
1022 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1026 if (!Stubs.empty()) {
1027 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1029 emitAlignment(
Align(8));
1031 for (
const auto &Stub : Stubs)
1034 OutStreamer->addBlankLine();
1045 M.getModuleFlag(
"ptrauth-elf-got"));
1046 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1047 for (
const GlobalValue &GV :
M.global_values())
1049 !GV.getName().starts_with(
"llvm."))
1050 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1059 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1060 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1063 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1064 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1075 for (
auto &[Section, CallsToImportedFuncs] :
1076 SectionToImportedFunctionCalls) {
1078 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1079 OutStreamer->emitInt32(SectionSize);
1080 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1081 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1083 OutStreamer->emitInt32(0x13);
1084 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1085 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1091void AArch64AsmPrinter::emitLOHs() {
1095 for (
const MachineInstr *
MI :
D.getArgs()) {
1096 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1097 assert(LabelIt != LOHInstToLabel.end() &&
1098 "Label hasn't been inserted for LOH related instruction");
1101 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1106void AArch64AsmPrinter::emitFunctionBodyEnd() {
1112MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1116 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1117 return OutContext.getOrCreateSymbol(
1118 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1119 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1124void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1126 const MachineOperand &MO =
MI->getOperand(OpNum);
1142 PrintSymbolOperand(MO, O);
1153bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1177bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1178 const TargetRegisterClass *RC,
1179 unsigned AltName, raw_ostream &O) {
1180 assert(MO.
isReg() &&
"Should only get here with a register!");
1181 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1190bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1191 const char *ExtraCode, raw_ostream &O) {
1192 const MachineOperand &MO =
MI->getOperand(OpNum);
1199 if (ExtraCode && ExtraCode[0]) {
1200 if (ExtraCode[1] != 0)
1203 switch (ExtraCode[0]) {
1211 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1224 const TargetRegisterClass *RC;
1225 switch (ExtraCode[0]) {
1227 RC = &AArch64::FPR8RegClass;
1230 RC = &AArch64::FPR16RegClass;
1233 RC = &AArch64::FPR32RegClass;
1236 RC = &AArch64::FPR64RegClass;
1239 RC = &AArch64::FPR128RegClass;
1242 RC = &AArch64::ZPRRegClass;
1247 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1268 unsigned AltName = AArch64::NoRegAltName;
1269 const TargetRegisterClass *RegClass;
1271 RegClass = &AArch64::ZPRRegClass;
1273 RegClass = &AArch64::PPRRegClass;
1275 RegClass = &AArch64::PNRRegClass;
1277 RegClass = &AArch64::FPR128RegClass;
1278 AltName = AArch64::vreg;
1282 return printAsmRegInClass(MO, RegClass, AltName, O);
1289bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1291 const char *ExtraCode,
1293 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1296 const MachineOperand &MO =
MI->getOperand(OpNum);
1297 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1302void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1304 unsigned NOps =
MI->getNumOperands();
1306 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1308 OS <<
MI->getDebugVariable()->getName();
1311 assert(
MI->isIndirectDebugValue());
1323void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1324 ArrayRef<unsigned> JumpTableIndices) {
1326 if (JumpTableIndices.
empty())
1328 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1332 MCSection *ReadOnlySec =
nullptr;
1333 if (TM.Options.EnableStaticDataPartitioning) {
1339 OutStreamer->switchSection(ReadOnlySec);
1341 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1342 for (
unsigned JTI : JumpTableIndices) {
1343 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1346 if (JTBBs.empty())
continue;
1348 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1350 OutStreamer->emitLabel(GetJTISymbol(JTI));
1355 for (
auto *JTBB : JTBBs) {
1356 const MCExpr *
Value =
1375AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1376 const MachineInstr *BranchInstr,
1377 const MCSymbol *BranchLabel)
const {
1378 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1381 switch (AFI->getJumpTableEntrySize(JTI)) {
1383 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1386 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1389 EntrySize = codeview::JumpTableEntrySize::Int32;
1394 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1397void AArch64AsmPrinter::emitFunctionEntryLabel() {
1398 const Triple &
TT = TM.getTargetTriple();
1399 if (
TT.isOSBinFormatELF() &&
1402 CallingConv::AArch64_SVE_VectorCall ||
1403 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1405 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1416 OutStreamer->emitAssignment(
1420 auto getSymbolFromMetadata = [&](StringRef
Name) {
1424 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1431 for (MDNode *Node : UnmangledNames) {
1433 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1434 if (std::optional<std::string> MangledName =
1437 MMI->getContext().getOrCreateSymbol(*MangledName);
1438 emitFunctionAlias(UnmangledSym, ECMangledSym);
1441 if (MCSymbol *ECMangledSym =
1442 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1443 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1447void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1448 const Constant *CV) {
1450 if (CPA->hasAddressDiscriminator() &&
1451 !CPA->hasSpecialAddressDiscriminator(
1454 "unexpected address discrimination value for ctors/dtors entry, only "
1455 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1464void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1465 const GlobalAlias &GA) {
1471 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1473 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1476 OutStreamer->beginCOFFSymbolDef(ExpSym);
1480 OutStreamer->endCOFFSymbolDef();
1482 OutStreamer->beginCOFFSymbolDef(Sym);
1486 OutStreamer->endCOFFSymbolDef();
1487 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1488 OutStreamer->emitAssignment(
1505void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1506 const llvm::MachineInstr &
MI) {
1507 Register DestReg =
MI.getOperand(0).getReg();
1508 Register ScratchReg =
MI.getOperand(1).getReg();
1510 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1511 Register TableReg =
MI.getOperand(2).getReg();
1512 Register EntryReg =
MI.getOperand(3).getReg();
1513 int JTIdx =
MI.getOperand(4).getIndex();
1519 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1530 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1532 .addExpr(LabelExpr));
1537 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1538 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1539 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1544 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1545 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1549 .addImm(
Size == 1 ? 0 : 1));
1553 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1557 .addImm(
Size == 4 ? 0 : 2));
1560void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1562 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1564 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1565 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1581 MachineOperand JTOp =
MI.getOperand(0);
1585 "unsupported compressed jump table");
1587 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1591 uint64_t MaxTableEntry = NumTableEntries - 1;
1593 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1594 .addReg(AArch64::XZR)
1595 .addReg(AArch64::X16)
1596 .addImm(MaxTableEntry)
1599 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1604 if ((MaxTableEntry >>
Offset) == 0)
1606 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1609 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1610 .addReg(AArch64::XZR)
1611 .addReg(AArch64::X16)
1612 .addReg(AArch64::X17)
1618 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1619 .addReg(AArch64::X16)
1620 .addReg(AArch64::X16)
1621 .addReg(AArch64::XZR)
1625 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1626 MCOperand JTMCHi, JTMCLo;
1636 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1638 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1639 .addReg(AArch64::X17)
1640 .addReg(AArch64::X17)
1644 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1645 .addReg(AArch64::X16)
1646 .addReg(AArch64::X17)
1647 .addReg(AArch64::X16)
1658 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1660 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1661 .addReg(AArch64::X16)
1662 .addReg(AArch64::X17)
1663 .addReg(AArch64::X16)
1666 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1669void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1670 const llvm::MachineInstr &
MI) {
1671 unsigned Opcode =
MI.getOpcode();
1673 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1675 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1676 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1677 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1678 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1679 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1680 if (Opcode == AArch64::MOPSMemorySetPseudo)
1681 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1682 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1683 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1686 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1687 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1689 for (
auto Op :
Ops) {
1691 auto MCIB = MCInstBuilder(
Op);
1693 MCIB.addReg(
MI.getOperand(i++).getReg());
1694 MCIB.addReg(
MI.getOperand(i++).getReg());
1696 MCIB.addReg(
MI.getOperand(i++).getReg());
1698 MCIB.addReg(
MI.getOperand(i++).getReg());
1699 MCIB.addReg(
MI.getOperand(i++).getReg());
1700 MCIB.addReg(
MI.getOperand(i++).getReg());
1702 EmitToStreamer(OutStreamer, MCIB);
1706void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1707 const MachineInstr &
MI) {
1708 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1711 MCSymbol *MILabel = Ctx.createTempSymbol();
1715 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1718 const MachineBasicBlock &
MBB = *
MI.getParent();
1721 while (NumNOPBytes > 0) {
1722 if (MII ==
MBB.
end() || MII->isCall() ||
1723 MII->getOpcode() == AArch64::DBG_VALUE ||
1724 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1725 MII->getOpcode() == TargetOpcode::STACKMAP)
1732 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1733 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1738void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1739 const MachineInstr &
MI) {
1741 MCSymbol *MILabel = Ctx.createTempSymbol();
1745 PatchPointOpers Opers(&
MI);
1747 int64_t CallTarget = Opers.getCallTarget().getImm();
1748 unsigned EncodedBytes = 0;
1750 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1751 "High 16 bits of call target should be zero.");
1752 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1755 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1756 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1757 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1758 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1761 unsigned NumBytes = Opers.getNumPatchBytes();
1762 assert(NumBytes >= EncodedBytes &&
1763 "Patchpoint can't request size less than the length of a call.");
1764 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1765 "Invalid number of NOP bytes requested!");
1766 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1767 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1770void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1771 const MachineInstr &
MI) {
1772 StatepointOpers SOpers(&
MI);
1773 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1774 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1775 for (
unsigned i = 0; i < PatchBytes; i += 4)
1776 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1779 const MachineOperand &CallTarget = SOpers.getCallTarget();
1780 MCOperand CallTargetMCOp;
1781 unsigned CallOpcode;
1782 switch (CallTarget.
getType()) {
1785 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1786 CallOpcode = AArch64::BL;
1790 CallOpcode = AArch64::BL;
1794 CallOpcode = AArch64::BLR;
1801 EmitToStreamer(OutStreamer,
1802 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1806 MCSymbol *MILabel = Ctx.createTempSymbol();
1811void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1820 unsigned OperandsBeginIdx = 4;
1823 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1830 MI.setOpcode(Opcode);
1835 for (
const MachineOperand &MO :
1838 lowerOperand(MO, Dest);
1839 MI.addOperand(Dest);
1847 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1849 .addReg(AArch64::XZR)
1854void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1855 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1856 EmitToStreamer(*OutStreamer,
1857 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1863void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1864 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1865 EmitToStreamer(*OutStreamer,
1866 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1875 bool IsZeroDisc = Disc == AArch64::XZR;
1887 EmitToStreamer(AUTInst);
1892 bool IsZeroDisc = Disc == AArch64::XZR;
1904 EmitToStreamer(PACInst);
1909 bool IsZeroDisc = Disc == AArch64::XZR;
1919 EmitToStreamer(Inst);
1922void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1923 Register DestReg =
MI.getOperand(0).getReg();
1924 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1925 if (STI->hasZeroCycleZeroingFPR64()) {
1927 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1928 if (AArch64::FPR16RegClass.
contains(DestReg))
1929 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1930 &AArch64::FPR64RegClass);
1931 else if (AArch64::FPR32RegClass.
contains(DestReg))
1932 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1933 &AArch64::FPR64RegClass);
1941 EmitToStreamer(*OutStreamer, MOVI);
1942 ++NumZCZeroingInstrsFPR;
1943 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1945 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1946 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1947 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1948 &AArch64::FPR128RegClass);
1949 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1950 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1951 &AArch64::FPR128RegClass);
1954 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1955 &AArch64::FPR128RegClass);
1962 EmitToStreamer(*OutStreamer, MOVI);
1963 ++NumZCZeroingInstrsFPR;
1965 emitFMov0AsFMov(
MI, DestReg);
1968 emitFMov0AsFMov(
MI, DestReg);
1972void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1975 switch (
MI.getOpcode()) {
1978 case AArch64::FMOVH0:
1979 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1980 if (!STI->hasFullFP16())
1981 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1985 case AArch64::FMOVS0:
1990 case AArch64::FMOVD0:
1996 EmitToStreamer(*OutStreamer, FMov);
1999Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint64_t Disc,
2002 bool MayClobberAddrDisc) {
2003 assert(isPtrauthRegSafe(ScratchReg) &&
2004 "Safe scratch register must be provided by the caller");
2008 if (AddrDisc == AArch64::NoRegister)
2009 AddrDisc = AArch64::XZR;
2017 if (AddrDisc == AArch64::XZR) {
2018 emitMOVZ(ScratchReg, Disc, 0);
2025 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2026 ScratchReg = AddrDisc;
2028 emitMovXReg(ScratchReg, AddrDisc);
2029 assert(ScratchReg != AddrDisc &&
2030 "Forbidden to clobber AddrDisc, but have to");
2033 emitMOVK(ScratchReg, Disc, 48);
2047void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2079 if (Method == AuthCheckMethod::None)
2081 if (Method == AuthCheckMethod::DummyLoad) {
2082 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2086 assert(!OnFailure &&
"DummyLoad always traps on error");
2090 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2091 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2093 emitMovXReg(ScratchReg, TestedReg);
2095 if (Method == AuthCheckMethod::XPAC) {
2099 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2104 assert(TestedReg == AArch64::LR &&
2105 "XPACHint mode is only compatible with checking the LR register");
2107 "XPACHint mode is only compatible with I-keys");
2108 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2112 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2113 .addReg(AArch64::XZR)
2120 MCInstBuilder(AArch64::Bcc)
2123 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2125 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2132 MCInstBuilder(AArch64::TBZX)
2143 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2157 case AuthCheckMethod::XPACHint:
2160 case AuthCheckMethod::XPAC:
2162 emitMovXReg(TestedReg, ScratchReg);
2169 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2174 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2186void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2190 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2191 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2194 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2198 "Neither x16 nor x17 is available as a scratch register");
2201 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2205bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2211 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2214 MCSymbol *Dot = OutContext.createTempSymbol();
2219 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2225void AArch64AsmPrinter::emitPtrauthAuthResign(
2227 const MachineOperand *AUTAddrDisc,
Register Scratch,
2228 std::optional<AArch64PACKey::ID> PACKey, uint64_t PACDisc,
2230 const bool IsAUTPAC = PACKey.has_value();
2244 bool ShouldCheck =
true;
2251 ShouldCheck = ShouldTrap =
false;
2258 ShouldCheck = ShouldTrap =
false;
2265 ShouldCheck = ShouldTrap =
true;
2270 Register AUTDiscReg = emitPtrauthDiscriminator(
2271 AUTDisc, AUTAddrDisc->
getReg(), Scratch, AUTAddrDisc->
isKill());
2273 if (!emitDeactivationSymbolRelocation(DS))
2274 emitAUT(AUTKey, AUTVal, AUTDiscReg);
2277 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2283 if (IsAUTPAC && !ShouldTrap)
2284 EndSym = createTempSymbol(
"resign_end_");
2286 emitPtrauthCheckAuthenticatedValue(
2287 AUTVal, Scratch, AUTKey, AArch64PAuth::AuthCheckMethod::XPAC, EndSym);
2297 Register PACDiscReg = emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
2298 emitPAC(*PACKey, AUTVal, PACDiscReg);
2305void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2308 uint64_t Disc =
MI->getOperand(3).getImm();
2309 Register AddrDisc =
MI->getOperand(4).getReg();
2310 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2314 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2315 assert(ScratchReg != AddrDisc &&
2316 "Neither X16 nor X17 is available as a scratch register");
2319 Register DiscReg = emitPtrauthDiscriminator(
2320 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2322 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2325 emitPAC(
Key, Val, DiscReg);
2328void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2329 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2330 unsigned BrTarget =
MI->getOperand(0).getReg();
2333 uint64_t Disc =
MI->getOperand(2).getImm();
2335 unsigned AddrDisc =
MI->getOperand(3).getReg();
2341 if (BrTarget == AddrDisc)
2358 bool AddrDiscIsImplicitDef =
2359 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2360 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2361 AddrDiscIsImplicitDef);
2362 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2365void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2368 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2369 const bool IsNeg = Addend < 0;
2371 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2374 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2377 .addImm((AbsOffset >> BitPos) & 0xfff)
2381 const uint64_t UAddend = Addend;
2382 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2384 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2386 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2387 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2388 uint64_t Shifted = UAddend >> BitPos;
2390 return Shifted != 0;
2391 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2392 if (((Shifted >>
I) & 0xffff) != 0xffff)
2396 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2397 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2399 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2408void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2409 MCRegister Tmp,
bool DSOLocal,
2410 const MCSubtargetInfo &STI) {
2416 MCInstBuilder(AArch64::ADRP)
2420 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2430 MCInstBuilder(AArch64::ADRP)
2435 MCInstBuilder(AArch64::LDRXui)
2446 if (!TT.isOSBinFormatELF())
2450 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2451 TT.isOSDragonFly() || TT.isOSNetBSD();
2505const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2507 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2508 const Triple &
TT = TM.getTargetTriple();
2520 auto STI = std::make_unique<AArch64Subtarget>(
2521 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2523 this->STI = STI.get();
2529 const MCSymbolELF *Group =
2544 .addReg(AArch64::X0)
2549 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2551 if (HasAddressDiversity) {
2556 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2560 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2562 "' out of range [0, 0xFFFF]");
2564 emitMOVZ(AArch64::X1, Disc, 0);
2571 auto *PrePACInstExpr =
2583 const MCSymbolRefExpr *EmuPACRef =
2585 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2592 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2600AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2601 MCContext &Ctx = OutContext;
2606 getDataLayout(),
Offset,
true);
2624 const MCExpr *DSExpr =
nullptr;
2636 "' out of range [0, " +
2644 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2646 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2651 "' out of range [0, 0xFFFF]");
2657 "expressions on this target");
2664void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2665 unsigned DstReg =
MI.getOperand(0).getReg();
2666 const MachineOperand &GAOp =
MI.getOperand(1);
2667 const uint64_t KeyC =
MI.getOperand(2).getImm();
2669 "key is out of range [0, AArch64PACKey::LAST]");
2671 const uint64_t Disc =
MI.getOperand(3).getImm();
2673 "constant discriminator is out of range [0, 0xffff]");
2682 if (TM.getTargetTriple().isOSBinFormatELF()) {
2684 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2687 "non-zero offset for $auth_ptr$ stub slots is not supported");
2689 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2691 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2692 "LOADauthptrstatic is implemented only for MachO/ELF");
2694 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2695 getObjFileLowering());
2698 "non-zero offset for $auth_ptr$ stub slots is not supported");
2700 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2703 MachineOperand StubMOHi =
2707 MCOperand StubMCHi, StubMCLo;
2714 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2716 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2722void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2723 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2724 const bool IsELFSignedGOT =
MI.getParent()
2726 ->getInfo<AArch64FunctionInfo>()
2727 ->hasELFSignedGOT();
2728 MachineOperand GAOp =
MI.getOperand(0);
2729 const uint64_t KeyC =
MI.getOperand(1).getImm();
2731 "key is out of range [0, AArch64PACKey::LAST]");
2733 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2734 const uint64_t Disc =
MI.getOperand(3).getImm();
2781 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2782 MCOperand GAMCHi, GAMCLo;
2795 MCInstBuilder(AArch64::ADRP)
2796 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2800 if (IsELFSignedGOT) {
2801 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2802 .addReg(AArch64::X17)
2803 .addReg(AArch64::X17)
2807 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2808 .addReg(AArch64::X16)
2809 .addReg(AArch64::X17)
2817 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2819 if (!STI->hasFPAC())
2820 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2821 AArch64PAuth::AuthCheckMethod::XPAC);
2823 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2824 .addReg(AArch64::X16)
2825 .addReg(AArch64::X16)
2829 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2830 .addReg(AArch64::X16)
2831 .addReg(AArch64::X16)
2836 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2837 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2839 emitPAC(
Key, AArch64::X16, DiscReg);
2842void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2844 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2845 const MachineOperand &GAMO =
MI.getOperand(1);
2852 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2853 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2854 .addReg(AuthResultReg)
2855 .addReg(AArch64::X17)
2858 MachineOperand GAHiOp(GAMO);
2859 MachineOperand GALoOp(GAMO);
2863 MCOperand GAMCHi, GAMCLo;
2868 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2870 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2871 .addReg(AArch64::X17)
2872 .addReg(AArch64::X17)
2876 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2877 .addReg(AuthResultReg)
2878 .addReg(AArch64::X17)
2885 UndefWeakSym = createTempSymbol(
"undef_weak");
2887 MCInstBuilder(AArch64::CBZX)
2888 .addReg(AuthResultReg)
2896 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2901 if (!STI->hasFPAC()) {
2902 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2903 AArch64PAuth::AuthCheckMethod::XPAC);
2905 emitMovXReg(DstReg, AuthResultReg);
2910AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2914 if (std::optional<uint16_t> BADisc =
2915 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2922void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
2926 switch (
MI->getOpcode()) {
2929 case AArch64::CBBAssertExt:
2933 case AArch64::CBHAssertExt:
2937 case AArch64::CBWPrr:
2940 case AArch64::CBXPrr:
2943 case AArch64::CBWPri:
2947 case AArch64::CBXPri:
2955 bool NeedsRegSwap =
false;
2956 bool NeedsImmDec =
false;
2957 bool NeedsImmInc =
false;
2959#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
2961 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
2963 ? AArch64::CBB##RegCond##Wrr \
2964 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
2965 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
2966 : AArch64::CB##RegCond##Xrr))))
2982 NeedsImmDec = IsImm;
2986 NeedsRegSwap = !IsImm;
2993 NeedsRegSwap = !IsImm;
2994 NeedsImmInc = IsImm;
2998 NeedsImmDec = IsImm;
3002 NeedsRegSwap = !IsImm;
3009 NeedsRegSwap = !IsImm;
3010 NeedsImmInc = IsImm;
3018 MCOperand Lhs, Rhs, Trgt;
3019 lowerOperand(
MI->getOperand(1), Lhs);
3020 lowerOperand(
MI->getOperand(2), Rhs);
3021 lowerOperand(
MI->getOperand(3), Trgt);
3025 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3026 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3029 }
else if (NeedsImmDec) {
3033 }
else if (NeedsImmInc) {
3043 "CB immediate operand out-of-bounds");
3046 EmitToStreamer(*OutStreamer, Inst);
3051#include "AArch64GenMCPseudoLowering.inc"
3053void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3060void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3061 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3066 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3071 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3072 EmitToStreamer(*OutStreamer, OutInst);
3076 if (
MI->getOpcode() == AArch64::ADRP) {
3077 for (
auto &Opd :
MI->operands()) {
3078 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3079 "swift_async_extendedFramePointerFlags") {
3080 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3087 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3089 LOHInstToLabel[
MI] = LOHLabel;
3093 AArch64TargetStreamer *TS =
3096 switch (
MI->getOpcode()) {
3099 "Unhandled tail call instruction");
3101 case AArch64::HINT: {
3106 if (CurrentPatchableFunctionEntrySym &&
3107 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3109 int64_t
Imm =
MI->getOperand(0).getImm();
3110 if ((Imm & 32) && (Imm & 6)) {
3112 MCInstLowering.
Lower(
MI, Inst);
3113 EmitToStreamer(*OutStreamer, Inst);
3114 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3115 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3121 case AArch64::MOVMCSym: {
3122 Register DestReg =
MI->getOperand(0).getReg();
3123 const MachineOperand &MO_Sym =
MI->getOperand(1);
3124 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3125 MCOperand Hi_MCSym, Lo_MCSym;
3138 EmitToStreamer(*OutStreamer, MovZ);
3146 EmitToStreamer(*OutStreamer, MovK);
3149 case AArch64::MOVIv2d_ns:
3157 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3158 MI->getOperand(1).getImm() == 0) {
3160 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3163 EmitToStreamer(*OutStreamer, TmpInst);
3168 case AArch64::DBG_VALUE:
3169 case AArch64::DBG_VALUE_LIST:
3171 SmallString<128> TmpStr;
3172 raw_svector_ostream OS(TmpStr);
3173 PrintDebugValueComment(
MI, OS);
3178 case AArch64::EMITBKEY: {
3180 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3181 ExceptionHandlingType != ExceptionHandling::ARM)
3184 if (getFunctionCFISectionType(*MF) == CFISection::None)
3191 case AArch64::EMITMTETAGGED: {
3193 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3194 ExceptionHandlingType != ExceptionHandling::ARM)
3197 if (getFunctionCFISectionType(*MF) != CFISection::None)
3202 case AArch64::AUTx16x17:
3203 emitPtrauthAuthResign(
3205 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3206 std::nullopt, 0, 0,
MI->getDeactivationSymbol());
3209 case AArch64::AUTxMxN:
3210 emitPtrauthAuthResign(
MI->getOperand(0).getReg(),
3212 MI->getOperand(4).getImm(), &
MI->getOperand(5),
3213 MI->getOperand(1).getReg(), std::nullopt, 0, 0,
3214 MI->getDeactivationSymbol());
3217 case AArch64::AUTPAC:
3218 emitPtrauthAuthResign(
3220 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3222 MI->getOperand(4).getImm(),
MI->getOperand(5).getReg(),
3223 MI->getDeactivationSymbol());
3227 emitPtrauthSign(
MI);
3230 case AArch64::LOADauthptrstatic:
3231 LowerLOADauthptrstatic(*
MI);
3234 case AArch64::LOADgotPAC:
3235 case AArch64::MOVaddrPAC:
3236 LowerMOVaddrPAC(*
MI);
3239 case AArch64::LOADgotAUTH:
3240 LowerLOADgotAUTH(*
MI);
3245 emitPtrauthBranch(
MI);
3251 case AArch64::AUTH_TCRETURN:
3252 case AArch64::AUTH_TCRETURN_BTI: {
3255 const uint64_t Disc =
MI->getOperand(3).getImm();
3257 Register AddrDisc =
MI->getOperand(4).getReg();
3259 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3261 emitPtrauthTailCallHardening(
MI);
3264 if (Callee == AddrDisc)
3271 bool AddrDiscIsImplicitDef =
3272 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3273 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3274 AddrDiscIsImplicitDef);
3275 emitBLRA(
false,
Key, Callee, DiscReg);
3279 case AArch64::TCRETURNri:
3280 case AArch64::TCRETURNrix16x17:
3281 case AArch64::TCRETURNrix17:
3282 case AArch64::TCRETURNrinotx16:
3283 case AArch64::TCRETURNriALL: {
3284 emitPtrauthTailCallHardening(
MI);
3286 recordIfImportCall(
MI);
3290 EmitToStreamer(*OutStreamer, TmpInst);
3293 case AArch64::TCRETURNdi: {
3294 emitPtrauthTailCallHardening(
MI);
3298 recordIfImportCall(
MI);
3302 EmitToStreamer(*OutStreamer, TmpInst);
3305 case AArch64::SpeculationBarrierISBDSBEndBB: {
3310 EmitToStreamer(*OutStreamer, TmpInstDSB);
3314 EmitToStreamer(*OutStreamer, TmpInstISB);
3317 case AArch64::SpeculationBarrierSBEndBB: {
3321 EmitToStreamer(*OutStreamer, TmpInstSB);
3324 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3331 const MachineOperand &MO_Sym =
MI->getOperand(0);
3332 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3333 MCOperand SymTLSDescLo12, SymTLSDesc;
3336 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3343 EmitToStreamer(*OutStreamer, Adrp);
3351 EmitToStreamer(*OutStreamer, Ldr);
3354 Add.setOpcode(AArch64::ADDXri);
3357 Add.addOperand(SymTLSDescLo12);
3359 EmitToStreamer(*OutStreamer,
Add);
3368 EmitToStreamer(*OutStreamer, Blraa);
3372 case AArch64::TLSDESC_CALLSEQ: {
3380 const MachineOperand &MO_Sym =
MI->getOperand(0);
3381 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3382 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3386 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3393 EmitToStreamer(*OutStreamer, Adrp);
3396 if (STI->isTargetILP32()) {
3406 EmitToStreamer(*OutStreamer, Ldr);
3409 if (STI->isTargetILP32()) {
3410 Add.setOpcode(AArch64::ADDWri);
3414 Add.setOpcode(AArch64::ADDXri);
3418 Add.addOperand(SymTLSDescLo12);
3420 EmitToStreamer(*OutStreamer,
Add);
3425 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3427 EmitToStreamer(*OutStreamer, TLSDescCall);
3435 EmitToStreamer(*OutStreamer, Blr);
3440 case AArch64::JumpTableDest32:
3441 case AArch64::JumpTableDest16:
3442 case AArch64::JumpTableDest8:
3443 LowerJumpTableDest(*OutStreamer, *
MI);
3446 case AArch64::BR_JumpTable:
3447 LowerHardenedBRJumpTable(*
MI);
3450 case AArch64::FMOVH0:
3451 case AArch64::FMOVS0:
3452 case AArch64::FMOVD0:
3456 case AArch64::MOPSMemoryCopyPseudo:
3457 case AArch64::MOPSMemoryMovePseudo:
3458 case AArch64::MOPSMemorySetPseudo:
3459 case AArch64::MOPSMemorySetTaggingPseudo:
3460 LowerMOPS(*OutStreamer, *
MI);
3463 case TargetOpcode::STACKMAP:
3464 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3466 case TargetOpcode::PATCHPOINT:
3467 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3469 case TargetOpcode::STATEPOINT:
3470 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3472 case TargetOpcode::FAULTING_OP:
3473 return LowerFAULTING_OP(*
MI);
3475 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3476 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3479 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3480 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3483 case TargetOpcode::PATCHABLE_TAIL_CALL:
3484 LowerPATCHABLE_TAIL_CALL(*
MI);
3486 case TargetOpcode::PATCHABLE_EVENT_CALL:
3487 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3488 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3489 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3491 case AArch64::KCFI_CHECK:
3492 LowerKCFI_CHECK(*
MI);
3495 case AArch64::HWASAN_CHECK_MEMACCESS:
3496 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3497 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3498 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3499 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3502 case AArch64::SEH_StackAlloc:
3506 case AArch64::SEH_SaveFPLR:
3510 case AArch64::SEH_SaveFPLR_X:
3511 assert(
MI->getOperand(0).getImm() < 0 &&
3512 "Pre increment SEH opcode must have a negative offset");
3516 case AArch64::SEH_SaveReg:
3518 MI->getOperand(1).getImm());
3521 case AArch64::SEH_SaveReg_X:
3522 assert(
MI->getOperand(1).getImm() < 0 &&
3523 "Pre increment SEH opcode must have a negative offset");
3525 -
MI->getOperand(1).getImm());
3528 case AArch64::SEH_SaveRegP:
3529 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3530 MI->getOperand(0).getImm() <= 28) {
3531 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3532 "Register paired with LR must be odd");
3534 MI->getOperand(2).getImm());
3537 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3538 "Non-consecutive registers not allowed for save_regp");
3540 MI->getOperand(2).getImm());
3543 case AArch64::SEH_SaveRegP_X:
3544 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3545 "Non-consecutive registers not allowed for save_regp_x");
3546 assert(
MI->getOperand(2).getImm() < 0 &&
3547 "Pre increment SEH opcode must have a negative offset");
3549 -
MI->getOperand(2).getImm());
3552 case AArch64::SEH_SaveFReg:
3554 MI->getOperand(1).getImm());
3557 case AArch64::SEH_SaveFReg_X:
3558 assert(
MI->getOperand(1).getImm() < 0 &&
3559 "Pre increment SEH opcode must have a negative offset");
3561 -
MI->getOperand(1).getImm());
3564 case AArch64::SEH_SaveFRegP:
3565 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3566 "Non-consecutive registers not allowed for save_regp");
3568 MI->getOperand(2).getImm());
3571 case AArch64::SEH_SaveFRegP_X:
3572 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3573 "Non-consecutive registers not allowed for save_regp_x");
3574 assert(
MI->getOperand(2).getImm() < 0 &&
3575 "Pre increment SEH opcode must have a negative offset");
3577 -
MI->getOperand(2).getImm());
3580 case AArch64::SEH_SetFP:
3584 case AArch64::SEH_AddFP:
3588 case AArch64::SEH_Nop:
3592 case AArch64::SEH_PrologEnd:
3596 case AArch64::SEH_EpilogStart:
3600 case AArch64::SEH_EpilogEnd:
3604 case AArch64::SEH_PACSignLR:
3608 case AArch64::SEH_SaveAnyRegI:
3609 assert(
MI->getOperand(1).getImm() <= 1008 &&
3610 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3612 MI->getOperand(1).getImm());
3615 case AArch64::SEH_SaveAnyRegIP:
3616 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3617 "Non-consecutive registers not allowed for save_any_reg");
3618 assert(
MI->getOperand(2).getImm() <= 1008 &&
3619 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3621 MI->getOperand(2).getImm());
3624 case AArch64::SEH_SaveAnyRegQP:
3625 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3626 "Non-consecutive registers not allowed for save_any_reg");
3627 assert(
MI->getOperand(2).getImm() >= 0 &&
3628 "SaveAnyRegQP SEH opcode offset must be non-negative");
3629 assert(
MI->getOperand(2).getImm() <= 1008 &&
3630 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3632 MI->getOperand(2).getImm());
3635 case AArch64::SEH_SaveAnyRegQPX:
3636 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3637 "Non-consecutive registers not allowed for save_any_reg");
3638 assert(
MI->getOperand(2).getImm() < 0 &&
3639 "SaveAnyRegQPX SEH opcode offset must be negative");
3640 assert(
MI->getOperand(2).getImm() >= -1008 &&
3641 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3643 -
MI->getOperand(2).getImm());
3646 case AArch64::SEH_AllocZ:
3647 assert(
MI->getOperand(0).getImm() >= 0 &&
3648 "AllocZ SEH opcode offset must be non-negative");
3649 assert(
MI->getOperand(0).getImm() <= 255 &&
3650 "AllocZ SEH opcode offset must fit into 8 bits");
3654 case AArch64::SEH_SaveZReg:
3655 assert(
MI->getOperand(1).getImm() >= 0 &&
3656 "SaveZReg SEH opcode offset must be non-negative");
3657 assert(
MI->getOperand(1).getImm() <= 255 &&
3658 "SaveZReg SEH opcode offset must fit into 8 bits");
3660 MI->getOperand(1).getImm());
3663 case AArch64::SEH_SavePReg:
3664 assert(
MI->getOperand(1).getImm() >= 0 &&
3665 "SavePReg SEH opcode offset must be non-negative");
3666 assert(
MI->getOperand(1).getImm() <= 255 &&
3667 "SavePReg SEH opcode offset must fit into 8 bits");
3669 MI->getOperand(1).getImm());
3674 recordIfImportCall(
MI);
3676 MCInstLowering.
Lower(
MI, TmpInst);
3677 EmitToStreamer(*OutStreamer, TmpInst);
3680 case AArch64::CBWPri:
3681 case AArch64::CBXPri:
3682 case AArch64::CBBAssertExt:
3683 case AArch64::CBHAssertExt:
3684 case AArch64::CBWPrr:
3685 case AArch64::CBXPrr:
3686 emitCBPseudoExpansion(
MI);
3690 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3695 MCInstLowering.
Lower(
MI, TmpInst);
3696 EmitToStreamer(*OutStreamer, TmpInst);
3699void AArch64AsmPrinter::recordIfImportCall(
3700 const llvm::MachineInstr *BranchInst) {
3701 if (!EnableImportCallOptimization)
3705 if (GV && GV->hasDLLImportStorageClass()) {
3706 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3711 .push_back({CallSiteSymbol, CalledSymbol});
3715void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3716 MCSymbol *LazyPointer) {
3733 EmitToStreamer(Adrp);
3741 MCOperand SymPageOff;
3748 EmitToStreamer(Ldr);
3751 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3752 .addReg(AArch64::X16)
3753 .addReg(AArch64::X16)
3756 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3758 .addReg(AArch64::X16));
3761void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3762 const GlobalIFunc &GI,
3763 MCSymbol *LazyPointer) {
3795 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3796 .addReg(AArch64::SP)
3797 .addReg(AArch64::FP)
3798 .addReg(AArch64::LR)
3799 .addReg(AArch64::SP)
3802 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3803 .addReg(AArch64::FP)
3804 .addReg(AArch64::SP)
3808 for (
int I = 0;
I != 4; ++
I)
3809 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3810 .addReg(AArch64::SP)
3811 .addReg(AArch64::X1 + 2 *
I)
3812 .addReg(AArch64::X0 + 2 *
I)
3813 .addReg(AArch64::SP)
3816 for (
int I = 0;
I != 4; ++
I)
3817 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3818 .addReg(AArch64::SP)
3819 .addReg(AArch64::D1 + 2 *
I)
3820 .addReg(AArch64::D0 + 2 *
I)
3821 .addReg(AArch64::SP)
3825 MCInstBuilder(AArch64::BL)
3838 EmitToStreamer(Adrp);
3846 MCOperand SymPageOff;
3853 EmitToStreamer(Ldr);
3856 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3857 .addReg(AArch64::X0)
3858 .addReg(AArch64::X16)
3861 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3862 .addReg(AArch64::X16)
3863 .addReg(AArch64::X0)
3867 for (
int I = 3;
I != -1; --
I)
3868 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3869 .addReg(AArch64::SP)
3870 .addReg(AArch64::D1 + 2 *
I)
3871 .addReg(AArch64::D0 + 2 *
I)
3872 .addReg(AArch64::SP)
3875 for (
int I = 3;
I != -1; --
I)
3876 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3877 .addReg(AArch64::SP)
3878 .addReg(AArch64::X1 + 2 *
I)
3879 .addReg(AArch64::X0 + 2 *
I)
3880 .addReg(AArch64::SP)
3883 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3884 .addReg(AArch64::SP)
3885 .addReg(AArch64::FP)
3886 .addReg(AArch64::LR)
3887 .addReg(AArch64::SP)
3890 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3892 .addReg(AArch64::X16));
3895const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
3896 const Constant *BaseCV,
3906char AArch64AsmPrinter::ID = 0;
3909 "AArch64 Assembly Printer",
false,
false)
3913LLVMInitializeAArch64AsmPrinter() {
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
#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 TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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 current metadata attachments for the given kind, if any.
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.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static SectionKind getMetadata()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void push_back(const T &Elt)
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
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.
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 LLVMContext & getContext() const
All values hold a context through their type.
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.
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)
Implement std::hash so that hash_code can be used in STL containers.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...