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();
779 AArch64Subtarget STI(TT, TM.getTargetCPU(), TM.getTargetCPU(),
780 TM.getTargetFeatureString(), TM,
true);
784 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
786 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
788 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
790 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
793 for (
auto &
P : HwasanMemaccessSymbols) {
794 unsigned Reg = std::get<0>(
P.first);
795 bool IsShort = std::get<1>(
P.first);
796 uint32_t AccessInfo = std::get<2>(
P.first);
797 bool IsFixedShadow = std::get<3>(
P.first);
798 uint64_t FixedShadowOffset = std::get<4>(
P.first);
799 const MCSymbolRefExpr *HwasanTagMismatchRef =
800 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
803 bool HasMatchAllTag =
805 uint8_t MatchAllTag =
812 OutStreamer->switchSection(OutContext.getELFSection(
818 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
819 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
820 OutStreamer->emitLabel(Sym);
822 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
823 .addReg(AArch64::X16)
833 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
834 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
835 .addReg(AArch64::W16)
836 .addReg(AArch64::X17)
837 .addReg(AArch64::X16)
841 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
842 .addReg(AArch64::W16)
843 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
844 .addReg(AArch64::X16)
849 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
850 .addReg(AArch64::XZR)
851 .addReg(AArch64::X16)
854 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
855 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
858 HandleMismatchOrPartialSym, OutContext)));
859 MCSymbol *ReturnSym = OutContext.createTempSymbol();
860 OutStreamer->emitLabel(ReturnSym);
861 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
862 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
864 if (HasMatchAllTag) {
865 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
866 .addReg(AArch64::X17)
870 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
871 .addReg(AArch64::XZR)
872 .addReg(AArch64::X17)
876 MCInstBuilder(AArch64::Bcc)
882 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
883 .addReg(AArch64::WZR)
884 .addReg(AArch64::W16)
887 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
889 MCInstBuilder(AArch64::Bcc)
893 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
894 .addReg(AArch64::X17)
898 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
899 .addReg(AArch64::X17)
900 .addReg(AArch64::X17)
903 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
904 .addReg(AArch64::WZR)
905 .addReg(AArch64::W16)
906 .addReg(AArch64::W17)
909 MCInstBuilder(AArch64::Bcc)
913 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
914 .addReg(AArch64::X16)
917 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
918 .addReg(AArch64::W16)
919 .addReg(AArch64::X16)
922 MCInstBuilder(AArch64::SUBSXrs)
923 .addReg(AArch64::XZR)
924 .addReg(AArch64::X16)
928 MCInstBuilder(AArch64::Bcc)
932 OutStreamer->emitLabel(HandleMismatchSym);
935 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
941 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
947 if (
Reg != AArch64::X0)
948 emitMovXReg(AArch64::X0,
Reg);
955 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
960 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
961 .addReg(AArch64::X16)
965 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
966 .addReg(AArch64::X16)
967 .addReg(AArch64::X16)
971 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
979 const MCExpr *StubAuthPtrRef) {
982 OutStreamer.
emitValue(StubAuthPtrRef, 8);
985void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
986 emitHwasanMemaccessSymbols(M);
988 const Triple &
TT = TM.getTargetTriple();
989 if (
TT.isOSBinFormatMachO()) {
991 MachineModuleInfoMachO &MMIMacho =
992 MMI->getObjFileInfo<MachineModuleInfoMachO>();
996 if (!Stubs.empty()) {
998 OutStreamer->switchSection(
1001 emitAlignment(
Align(8));
1003 for (
const auto &Stub : Stubs)
1006 OutStreamer->addBlankLine();
1014 OutStreamer->emitSubsectionsViaSymbols();
1017 if (
TT.isOSBinFormatELF()) {
1019 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1023 if (!Stubs.empty()) {
1024 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1026 emitAlignment(
Align(8));
1028 for (
const auto &Stub : Stubs)
1031 OutStreamer->addBlankLine();
1042 M.getModuleFlag(
"ptrauth-elf-got"));
1043 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1044 for (
const GlobalValue &GV :
M.global_values())
1046 !GV.getName().starts_with(
"llvm."))
1047 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1056 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1057 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1060 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1061 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1072 for (
auto &[Section, CallsToImportedFuncs] :
1073 SectionToImportedFunctionCalls) {
1075 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1076 OutStreamer->emitInt32(SectionSize);
1077 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1078 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1080 OutStreamer->emitInt32(0x13);
1081 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1082 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1088void AArch64AsmPrinter::emitLOHs() {
1092 for (
const MachineInstr *
MI :
D.getArgs()) {
1093 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1094 assert(LabelIt != LOHInstToLabel.end() &&
1095 "Label hasn't been inserted for LOH related instruction");
1098 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1103void AArch64AsmPrinter::emitFunctionBodyEnd() {
1109MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1113 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1114 return OutContext.getOrCreateSymbol(
1115 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1116 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1121void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1123 const MachineOperand &MO =
MI->getOperand(OpNum);
1139 PrintSymbolOperand(MO, O);
1150bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1174bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1175 const TargetRegisterClass *RC,
1176 unsigned AltName, raw_ostream &O) {
1177 assert(MO.
isReg() &&
"Should only get here with a register!");
1178 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1187bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1188 const char *ExtraCode, raw_ostream &O) {
1189 const MachineOperand &MO =
MI->getOperand(OpNum);
1196 if (ExtraCode && ExtraCode[0]) {
1197 if (ExtraCode[1] != 0)
1200 switch (ExtraCode[0]) {
1208 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1221 const TargetRegisterClass *RC;
1222 switch (ExtraCode[0]) {
1224 RC = &AArch64::FPR8RegClass;
1227 RC = &AArch64::FPR16RegClass;
1230 RC = &AArch64::FPR32RegClass;
1233 RC = &AArch64::FPR64RegClass;
1236 RC = &AArch64::FPR128RegClass;
1239 RC = &AArch64::ZPRRegClass;
1244 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1265 unsigned AltName = AArch64::NoRegAltName;
1266 const TargetRegisterClass *RegClass;
1268 RegClass = &AArch64::ZPRRegClass;
1270 RegClass = &AArch64::PPRRegClass;
1272 RegClass = &AArch64::PNRRegClass;
1274 RegClass = &AArch64::FPR128RegClass;
1275 AltName = AArch64::vreg;
1279 return printAsmRegInClass(MO, RegClass, AltName, O);
1286bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1288 const char *ExtraCode,
1290 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1293 const MachineOperand &MO =
MI->getOperand(OpNum);
1294 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1299void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1301 unsigned NOps =
MI->getNumOperands();
1303 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1305 OS <<
MI->getDebugVariable()->getName();
1308 assert(
MI->isIndirectDebugValue());
1320void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1321 ArrayRef<unsigned> JumpTableIndices) {
1323 if (JumpTableIndices.
empty())
1325 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1329 MCSection *ReadOnlySec =
nullptr;
1330 if (TM.Options.EnableStaticDataPartitioning) {
1336 OutStreamer->switchSection(ReadOnlySec);
1338 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1339 for (
unsigned JTI : JumpTableIndices) {
1340 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1343 if (JTBBs.empty())
continue;
1345 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1347 OutStreamer->emitLabel(GetJTISymbol(JTI));
1352 for (
auto *JTBB : JTBBs) {
1353 const MCExpr *
Value =
1372AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1373 const MachineInstr *BranchInstr,
1374 const MCSymbol *BranchLabel)
const {
1375 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1378 switch (AFI->getJumpTableEntrySize(JTI)) {
1380 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1383 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1386 EntrySize = codeview::JumpTableEntrySize::Int32;
1391 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1394void AArch64AsmPrinter::emitFunctionEntryLabel() {
1395 const Triple &
TT = TM.getTargetTriple();
1396 if (
TT.isOSBinFormatELF() &&
1399 CallingConv::AArch64_SVE_VectorCall ||
1400 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1402 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1413 OutStreamer->emitAssignment(
1417 auto getSymbolFromMetadata = [&](StringRef
Name) {
1421 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1428 for (MDNode *Node : UnmangledNames) {
1430 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1431 if (std::optional<std::string> MangledName =
1434 MMI->getContext().getOrCreateSymbol(*MangledName);
1435 emitFunctionAlias(UnmangledSym, ECMangledSym);
1438 if (MCSymbol *ECMangledSym =
1439 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1440 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1444void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1445 const Constant *CV) {
1447 if (CPA->hasAddressDiscriminator() &&
1448 !CPA->hasSpecialAddressDiscriminator(
1451 "unexpected address discrimination value for ctors/dtors entry, only "
1452 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1461void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1462 const GlobalAlias &GA) {
1468 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1470 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1473 OutStreamer->beginCOFFSymbolDef(ExpSym);
1477 OutStreamer->endCOFFSymbolDef();
1479 OutStreamer->beginCOFFSymbolDef(Sym);
1483 OutStreamer->endCOFFSymbolDef();
1484 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1485 OutStreamer->emitAssignment(
1502void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1503 const llvm::MachineInstr &
MI) {
1504 Register DestReg =
MI.getOperand(0).getReg();
1505 Register ScratchReg =
MI.getOperand(1).getReg();
1507 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1508 Register TableReg =
MI.getOperand(2).getReg();
1509 Register EntryReg =
MI.getOperand(3).getReg();
1510 int JTIdx =
MI.getOperand(4).getIndex();
1516 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1527 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1529 .addExpr(LabelExpr));
1534 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1535 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1536 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1541 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1542 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1546 .addImm(
Size == 1 ? 0 : 1));
1550 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1554 .addImm(
Size == 4 ? 0 : 2));
1557void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1559 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1561 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1562 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1578 MachineOperand JTOp =
MI.getOperand(0);
1582 "unsupported compressed jump table");
1584 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1588 uint64_t MaxTableEntry = NumTableEntries - 1;
1590 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1591 .addReg(AArch64::XZR)
1592 .addReg(AArch64::X16)
1593 .addImm(MaxTableEntry)
1596 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1601 if ((MaxTableEntry >>
Offset) == 0)
1603 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1606 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1607 .addReg(AArch64::XZR)
1608 .addReg(AArch64::X16)
1609 .addReg(AArch64::X17)
1615 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1616 .addReg(AArch64::X16)
1617 .addReg(AArch64::X16)
1618 .addReg(AArch64::XZR)
1622 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1623 MCOperand JTMCHi, JTMCLo;
1633 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1635 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1636 .addReg(AArch64::X17)
1637 .addReg(AArch64::X17)
1641 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1642 .addReg(AArch64::X16)
1643 .addReg(AArch64::X17)
1644 .addReg(AArch64::X16)
1655 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1657 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1658 .addReg(AArch64::X16)
1659 .addReg(AArch64::X17)
1660 .addReg(AArch64::X16)
1663 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1666void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1667 const llvm::MachineInstr &
MI) {
1668 unsigned Opcode =
MI.getOpcode();
1670 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1672 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1673 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1674 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1675 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1676 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1677 if (Opcode == AArch64::MOPSMemorySetPseudo)
1678 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1679 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1680 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1683 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1684 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1686 for (
auto Op :
Ops) {
1688 auto MCIB = MCInstBuilder(
Op);
1690 MCIB.addReg(
MI.getOperand(i++).getReg());
1691 MCIB.addReg(
MI.getOperand(i++).getReg());
1693 MCIB.addReg(
MI.getOperand(i++).getReg());
1695 MCIB.addReg(
MI.getOperand(i++).getReg());
1696 MCIB.addReg(
MI.getOperand(i++).getReg());
1697 MCIB.addReg(
MI.getOperand(i++).getReg());
1699 EmitToStreamer(OutStreamer, MCIB);
1703void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
1704 const MachineInstr &
MI) {
1705 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1708 MCSymbol *MILabel = Ctx.createTempSymbol();
1712 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1715 const MachineBasicBlock &
MBB = *
MI.getParent();
1718 while (NumNOPBytes > 0) {
1719 if (MII ==
MBB.
end() || MII->isCall() ||
1720 MII->getOpcode() == AArch64::DBG_VALUE ||
1721 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1722 MII->getOpcode() == TargetOpcode::STACKMAP)
1729 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1730 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1735void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1736 const MachineInstr &
MI) {
1738 MCSymbol *MILabel = Ctx.createTempSymbol();
1742 PatchPointOpers Opers(&
MI);
1744 int64_t CallTarget = Opers.getCallTarget().getImm();
1745 unsigned EncodedBytes = 0;
1747 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1748 "High 16 bits of call target should be zero.");
1749 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1752 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1753 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1754 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1755 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1758 unsigned NumBytes = Opers.getNumPatchBytes();
1759 assert(NumBytes >= EncodedBytes &&
1760 "Patchpoint can't request size less than the length of a call.");
1761 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1762 "Invalid number of NOP bytes requested!");
1763 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1764 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1767void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
1768 const MachineInstr &
MI) {
1769 StatepointOpers SOpers(&
MI);
1770 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1771 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1772 for (
unsigned i = 0; i < PatchBytes; i += 4)
1773 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1776 const MachineOperand &CallTarget = SOpers.getCallTarget();
1777 MCOperand CallTargetMCOp;
1778 unsigned CallOpcode;
1779 switch (CallTarget.
getType()) {
1782 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1783 CallOpcode = AArch64::BL;
1787 CallOpcode = AArch64::BL;
1791 CallOpcode = AArch64::BLR;
1798 EmitToStreamer(OutStreamer,
1799 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1803 MCSymbol *MILabel = Ctx.createTempSymbol();
1808void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1817 unsigned OperandsBeginIdx = 4;
1820 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1827 MI.setOpcode(Opcode);
1832 for (
const MachineOperand &MO :
1835 lowerOperand(MO, Dest);
1836 MI.addOperand(Dest);
1844 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1846 .addReg(AArch64::XZR)
1851void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1852 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1853 EmitToStreamer(*OutStreamer,
1854 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1860void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1861 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1862 EmitToStreamer(*OutStreamer,
1863 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1872 bool IsZeroDisc = Disc == AArch64::XZR;
1884 EmitToStreamer(AUTInst);
1889 bool IsZeroDisc = Disc == AArch64::XZR;
1901 EmitToStreamer(PACInst);
1906 bool IsZeroDisc = Disc == AArch64::XZR;
1916 EmitToStreamer(Inst);
1919void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1920 Register DestReg =
MI.getOperand(0).getReg();
1921 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1922 if (STI->hasZeroCycleZeroingFPR64()) {
1924 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1925 if (AArch64::FPR16RegClass.
contains(DestReg))
1926 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1927 &AArch64::FPR64RegClass);
1928 else if (AArch64::FPR32RegClass.
contains(DestReg))
1929 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1930 &AArch64::FPR64RegClass);
1938 EmitToStreamer(*OutStreamer, MOVI);
1939 ++NumZCZeroingInstrsFPR;
1940 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1942 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1943 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1944 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1945 &AArch64::FPR128RegClass);
1946 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1947 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1948 &AArch64::FPR128RegClass);
1951 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1952 &AArch64::FPR128RegClass);
1959 EmitToStreamer(*OutStreamer, MOVI);
1960 ++NumZCZeroingInstrsFPR;
1962 emitFMov0AsFMov(
MI, DestReg);
1965 emitFMov0AsFMov(
MI, DestReg);
1969void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1972 switch (
MI.getOpcode()) {
1975 case AArch64::FMOVH0:
1976 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1977 if (!STI->hasFullFP16())
1978 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1982 case AArch64::FMOVS0:
1987 case AArch64::FMOVD0:
1993 EmitToStreamer(*OutStreamer, FMov);
1996Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint64_t Disc,
1999 bool MayClobberAddrDisc) {
2000 assert(isPtrauthRegSafe(ScratchReg) &&
2001 "Safe scratch register must be provided by the caller");
2005 if (AddrDisc == AArch64::NoRegister)
2006 AddrDisc = AArch64::XZR;
2014 if (AddrDisc == AArch64::XZR) {
2015 emitMOVZ(ScratchReg, Disc, 0);
2022 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2023 ScratchReg = AddrDisc;
2025 emitMovXReg(ScratchReg, AddrDisc);
2026 assert(ScratchReg != AddrDisc &&
2027 "Forbidden to clobber AddrDisc, but have to");
2030 emitMOVK(ScratchReg, Disc, 48);
2044void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2076 if (Method == AuthCheckMethod::None)
2078 if (Method == AuthCheckMethod::DummyLoad) {
2079 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2083 assert(!OnFailure &&
"DummyLoad always traps on error");
2087 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2088 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2090 emitMovXReg(ScratchReg, TestedReg);
2092 if (Method == AuthCheckMethod::XPAC) {
2096 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2101 assert(TestedReg == AArch64::LR &&
2102 "XPACHint mode is only compatible with checking the LR register");
2104 "XPACHint mode is only compatible with I-keys");
2105 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2109 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2110 .addReg(AArch64::XZR)
2117 MCInstBuilder(AArch64::Bcc)
2120 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2122 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2129 MCInstBuilder(AArch64::TBZX)
2140 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2154 case AuthCheckMethod::XPACHint:
2157 case AuthCheckMethod::XPAC:
2159 emitMovXReg(TestedReg, ScratchReg);
2166 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2171 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2183void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2187 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2188 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2191 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2195 "Neither x16 nor x17 is available as a scratch register");
2198 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2202bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2208 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2211 MCSymbol *Dot = OutContext.createTempSymbol();
2216 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2222void AArch64AsmPrinter::emitPtrauthAuthResign(
2224 const MachineOperand *AUTAddrDisc,
Register Scratch,
2225 std::optional<AArch64PACKey::ID> PACKey, uint64_t PACDisc,
2227 const bool IsAUTPAC = PACKey.has_value();
2241 bool ShouldCheck =
true;
2248 ShouldCheck = ShouldTrap =
false;
2255 ShouldCheck = ShouldTrap =
false;
2262 ShouldCheck = ShouldTrap =
true;
2267 Register AUTDiscReg = emitPtrauthDiscriminator(
2268 AUTDisc, AUTAddrDisc->
getReg(), Scratch, AUTAddrDisc->
isKill());
2270 if (!emitDeactivationSymbolRelocation(DS))
2271 emitAUT(AUTKey, AUTVal, AUTDiscReg);
2274 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2280 if (IsAUTPAC && !ShouldTrap)
2281 EndSym = createTempSymbol(
"resign_end_");
2283 emitPtrauthCheckAuthenticatedValue(
2284 AUTVal, Scratch, AUTKey, AArch64PAuth::AuthCheckMethod::XPAC, EndSym);
2294 Register PACDiscReg = emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
2295 emitPAC(*PACKey, AUTVal, PACDiscReg);
2302void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2305 uint64_t Disc =
MI->getOperand(3).getImm();
2306 Register AddrDisc =
MI->getOperand(4).getReg();
2307 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2311 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2312 assert(ScratchReg != AddrDisc &&
2313 "Neither X16 nor X17 is available as a scratch register");
2316 Register DiscReg = emitPtrauthDiscriminator(
2317 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2319 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2322 emitPAC(
Key, Val, DiscReg);
2325void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2326 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2327 unsigned BrTarget =
MI->getOperand(0).getReg();
2330 uint64_t Disc =
MI->getOperand(2).getImm();
2332 unsigned AddrDisc =
MI->getOperand(3).getReg();
2338 if (BrTarget == AddrDisc)
2355 bool AddrDiscIsImplicitDef =
2356 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2357 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2358 AddrDiscIsImplicitDef);
2359 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2362void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2365 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2366 const bool IsNeg = Addend < 0;
2368 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2371 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2374 .addImm((AbsOffset >> BitPos) & 0xfff)
2378 const uint64_t UAddend = Addend;
2379 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2381 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2383 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2384 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2385 uint64_t Shifted = UAddend >> BitPos;
2387 return Shifted != 0;
2388 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2389 if (((Shifted >>
I) & 0xffff) != 0xffff)
2393 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2394 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2396 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2405void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2406 MCRegister Tmp,
bool DSOLocal,
2407 const MCSubtargetInfo &STI) {
2413 MCInstBuilder(AArch64::ADRP)
2417 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2427 MCInstBuilder(AArch64::ADRP)
2432 MCInstBuilder(AArch64::LDRXui)
2443 if (!TT.isOSBinFormatELF())
2447 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2448 TT.isOSDragonFly() || TT.isOSNetBSD();
2502const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2504 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2505 const Triple &
TT = TM.getTargetTriple();
2515 AArch64Subtarget STI(TT, TM.getTargetCPU(), TM.getTargetCPU(),
2516 TM.getTargetFeatureString(), TM,
true);
2523 const MCSymbolELF *Group =
2538 .addReg(AArch64::X0)
2543 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, STI);
2545 if (HasAddressDiversity) {
2550 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2554 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2556 "' out of range [0, 0xFFFF]");
2558 emitMOVZ(AArch64::X1, Disc, 0);
2565 auto *PrePACInstExpr =
2577 const MCSymbolRefExpr *EmuPACRef =
2579 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2586 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), STI);
2594AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2595 MCContext &Ctx = OutContext;
2600 getDataLayout(),
Offset,
true);
2618 const MCExpr *DSExpr =
nullptr;
2630 "' out of range [0, " +
2638 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2640 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2645 "' out of range [0, 0xFFFF]");
2651 "expressions on this target");
2658void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2659 unsigned DstReg =
MI.getOperand(0).getReg();
2660 const MachineOperand &GAOp =
MI.getOperand(1);
2661 const uint64_t KeyC =
MI.getOperand(2).getImm();
2663 "key is out of range [0, AArch64PACKey::LAST]");
2665 const uint64_t Disc =
MI.getOperand(3).getImm();
2667 "constant discriminator is out of range [0, 0xffff]");
2676 if (TM.getTargetTriple().isOSBinFormatELF()) {
2678 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2681 "non-zero offset for $auth_ptr$ stub slots is not supported");
2683 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2685 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2686 "LOADauthptrstatic is implemented only for MachO/ELF");
2688 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2689 getObjFileLowering());
2692 "non-zero offset for $auth_ptr$ stub slots is not supported");
2694 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2697 MachineOperand StubMOHi =
2701 MCOperand StubMCHi, StubMCLo;
2708 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2710 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2716void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2717 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2718 const bool IsELFSignedGOT =
MI.getParent()
2720 ->getInfo<AArch64FunctionInfo>()
2721 ->hasELFSignedGOT();
2722 MachineOperand GAOp =
MI.getOperand(0);
2723 const uint64_t KeyC =
MI.getOperand(1).getImm();
2725 "key is out of range [0, AArch64PACKey::LAST]");
2727 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2728 const uint64_t Disc =
MI.getOperand(3).getImm();
2775 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2776 MCOperand GAMCHi, GAMCLo;
2789 MCInstBuilder(AArch64::ADRP)
2790 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2794 if (IsELFSignedGOT) {
2795 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2796 .addReg(AArch64::X17)
2797 .addReg(AArch64::X17)
2801 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2802 .addReg(AArch64::X16)
2803 .addReg(AArch64::X17)
2811 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2813 if (!STI->hasFPAC())
2814 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2815 AArch64PAuth::AuthCheckMethod::XPAC);
2817 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2818 .addReg(AArch64::X16)
2819 .addReg(AArch64::X16)
2823 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2824 .addReg(AArch64::X16)
2825 .addReg(AArch64::X16)
2830 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2831 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2833 emitPAC(
Key, AArch64::X16, DiscReg);
2836void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2838 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2839 const MachineOperand &GAMO =
MI.getOperand(1);
2846 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2847 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2848 .addReg(AuthResultReg)
2849 .addReg(AArch64::X17)
2852 MachineOperand GAHiOp(GAMO);
2853 MachineOperand GALoOp(GAMO);
2857 MCOperand GAMCHi, GAMCLo;
2862 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2864 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2865 .addReg(AArch64::X17)
2866 .addReg(AArch64::X17)
2870 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2871 .addReg(AuthResultReg)
2872 .addReg(AArch64::X17)
2879 UndefWeakSym = createTempSymbol(
"undef_weak");
2881 MCInstBuilder(AArch64::CBZX)
2882 .addReg(AuthResultReg)
2890 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2895 if (!STI->hasFPAC()) {
2896 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2897 AArch64PAuth::AuthCheckMethod::XPAC);
2899 emitMovXReg(DstReg, AuthResultReg);
2904AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2908 if (std::optional<uint16_t> BADisc =
2909 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2916void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
2920 switch (
MI->getOpcode()) {
2923 case AArch64::CBBAssertExt:
2927 case AArch64::CBHAssertExt:
2931 case AArch64::CBWPrr:
2934 case AArch64::CBXPrr:
2937 case AArch64::CBWPri:
2941 case AArch64::CBXPri:
2949 bool NeedsRegSwap =
false;
2950 bool NeedsImmDec =
false;
2951 bool NeedsImmInc =
false;
2953#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
2955 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
2957 ? AArch64::CBB##RegCond##Wrr \
2958 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
2959 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
2960 : AArch64::CB##RegCond##Xrr))))
2976 NeedsImmDec = IsImm;
2980 NeedsRegSwap = !IsImm;
2987 NeedsRegSwap = !IsImm;
2988 NeedsImmInc = IsImm;
2992 NeedsImmDec = IsImm;
2996 NeedsRegSwap = !IsImm;
3003 NeedsRegSwap = !IsImm;
3004 NeedsImmInc = IsImm;
3012 MCOperand Lhs, Rhs, Trgt;
3013 lowerOperand(
MI->getOperand(1), Lhs);
3014 lowerOperand(
MI->getOperand(2), Rhs);
3015 lowerOperand(
MI->getOperand(3), Trgt);
3019 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3020 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3023 }
else if (NeedsImmDec) {
3027 }
else if (NeedsImmInc) {
3037 "CB immediate operand out-of-bounds");
3040 EmitToStreamer(*OutStreamer, Inst);
3045#include "AArch64GenMCPseudoLowering.inc"
3047void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3054void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3055 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3060 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3065 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3066 EmitToStreamer(*OutStreamer, OutInst);
3070 if (
MI->getOpcode() == AArch64::ADRP) {
3071 for (
auto &Opd :
MI->operands()) {
3072 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3073 "swift_async_extendedFramePointerFlags") {
3074 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3081 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3083 LOHInstToLabel[
MI] = LOHLabel;
3087 AArch64TargetStreamer *TS =
3090 switch (
MI->getOpcode()) {
3093 "Unhandled tail call instruction");
3095 case AArch64::HINT: {
3100 if (CurrentPatchableFunctionEntrySym &&
3101 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3103 int64_t
Imm =
MI->getOperand(0).getImm();
3104 if ((Imm & 32) && (Imm & 6)) {
3106 MCInstLowering.
Lower(
MI, Inst);
3107 EmitToStreamer(*OutStreamer, Inst);
3108 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3109 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3115 case AArch64::MOVMCSym: {
3116 Register DestReg =
MI->getOperand(0).getReg();
3117 const MachineOperand &MO_Sym =
MI->getOperand(1);
3118 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3119 MCOperand Hi_MCSym, Lo_MCSym;
3132 EmitToStreamer(*OutStreamer, MovZ);
3140 EmitToStreamer(*OutStreamer, MovK);
3143 case AArch64::MOVIv2d_ns:
3151 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3152 MI->getOperand(1).getImm() == 0) {
3154 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3157 EmitToStreamer(*OutStreamer, TmpInst);
3162 case AArch64::DBG_VALUE:
3163 case AArch64::DBG_VALUE_LIST:
3165 SmallString<128> TmpStr;
3166 raw_svector_ostream OS(TmpStr);
3167 PrintDebugValueComment(
MI, OS);
3172 case AArch64::EMITBKEY: {
3174 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3175 ExceptionHandlingType != ExceptionHandling::ARM)
3178 if (getFunctionCFISectionType(*MF) == CFISection::None)
3185 case AArch64::EMITMTETAGGED: {
3187 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3188 ExceptionHandlingType != ExceptionHandling::ARM)
3191 if (getFunctionCFISectionType(*MF) != CFISection::None)
3196 case AArch64::AUTx16x17:
3197 emitPtrauthAuthResign(
3199 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3200 std::nullopt, 0, 0,
MI->getDeactivationSymbol());
3203 case AArch64::AUTxMxN:
3204 emitPtrauthAuthResign(
MI->getOperand(0).getReg(),
3206 MI->getOperand(4).getImm(), &
MI->getOperand(5),
3207 MI->getOperand(1).getReg(), std::nullopt, 0, 0,
3208 MI->getDeactivationSymbol());
3211 case AArch64::AUTPAC:
3212 emitPtrauthAuthResign(
3214 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
3216 MI->getOperand(4).getImm(),
MI->getOperand(5).getReg(),
3217 MI->getDeactivationSymbol());
3221 emitPtrauthSign(
MI);
3224 case AArch64::LOADauthptrstatic:
3225 LowerLOADauthptrstatic(*
MI);
3228 case AArch64::LOADgotPAC:
3229 case AArch64::MOVaddrPAC:
3230 LowerMOVaddrPAC(*
MI);
3233 case AArch64::LOADgotAUTH:
3234 LowerLOADgotAUTH(*
MI);
3239 emitPtrauthBranch(
MI);
3245 case AArch64::AUTH_TCRETURN:
3246 case AArch64::AUTH_TCRETURN_BTI: {
3249 const uint64_t Disc =
MI->getOperand(3).getImm();
3251 Register AddrDisc =
MI->getOperand(4).getReg();
3253 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3255 emitPtrauthTailCallHardening(
MI);
3258 if (Callee == AddrDisc)
3265 bool AddrDiscIsImplicitDef =
3266 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3267 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3268 AddrDiscIsImplicitDef);
3269 emitBLRA(
false,
Key, Callee, DiscReg);
3273 case AArch64::TCRETURNri:
3274 case AArch64::TCRETURNrix16x17:
3275 case AArch64::TCRETURNrix17:
3276 case AArch64::TCRETURNrinotx16:
3277 case AArch64::TCRETURNriALL: {
3278 emitPtrauthTailCallHardening(
MI);
3280 recordIfImportCall(
MI);
3284 EmitToStreamer(*OutStreamer, TmpInst);
3287 case AArch64::TCRETURNdi: {
3288 emitPtrauthTailCallHardening(
MI);
3292 recordIfImportCall(
MI);
3296 EmitToStreamer(*OutStreamer, TmpInst);
3299 case AArch64::SpeculationBarrierISBDSBEndBB: {
3304 EmitToStreamer(*OutStreamer, TmpInstDSB);
3308 EmitToStreamer(*OutStreamer, TmpInstISB);
3311 case AArch64::SpeculationBarrierSBEndBB: {
3315 EmitToStreamer(*OutStreamer, TmpInstSB);
3318 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3325 const MachineOperand &MO_Sym =
MI->getOperand(0);
3326 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3327 MCOperand SymTLSDescLo12, SymTLSDesc;
3330 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3337 EmitToStreamer(*OutStreamer, Adrp);
3345 EmitToStreamer(*OutStreamer, Ldr);
3348 Add.setOpcode(AArch64::ADDXri);
3351 Add.addOperand(SymTLSDescLo12);
3353 EmitToStreamer(*OutStreamer,
Add);
3362 EmitToStreamer(*OutStreamer, Blraa);
3366 case AArch64::TLSDESC_CALLSEQ: {
3374 const MachineOperand &MO_Sym =
MI->getOperand(0);
3375 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3376 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3380 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3387 EmitToStreamer(*OutStreamer, Adrp);
3390 if (STI->isTargetILP32()) {
3400 EmitToStreamer(*OutStreamer, Ldr);
3403 if (STI->isTargetILP32()) {
3404 Add.setOpcode(AArch64::ADDWri);
3408 Add.setOpcode(AArch64::ADDXri);
3412 Add.addOperand(SymTLSDescLo12);
3414 EmitToStreamer(*OutStreamer,
Add);
3419 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3421 EmitToStreamer(*OutStreamer, TLSDescCall);
3429 EmitToStreamer(*OutStreamer, Blr);
3434 case AArch64::JumpTableDest32:
3435 case AArch64::JumpTableDest16:
3436 case AArch64::JumpTableDest8:
3437 LowerJumpTableDest(*OutStreamer, *
MI);
3440 case AArch64::BR_JumpTable:
3441 LowerHardenedBRJumpTable(*
MI);
3444 case AArch64::FMOVH0:
3445 case AArch64::FMOVS0:
3446 case AArch64::FMOVD0:
3450 case AArch64::MOPSMemoryCopyPseudo:
3451 case AArch64::MOPSMemoryMovePseudo:
3452 case AArch64::MOPSMemorySetPseudo:
3453 case AArch64::MOPSMemorySetTaggingPseudo:
3454 LowerMOPS(*OutStreamer, *
MI);
3457 case TargetOpcode::STACKMAP:
3458 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3460 case TargetOpcode::PATCHPOINT:
3461 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3463 case TargetOpcode::STATEPOINT:
3464 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3466 case TargetOpcode::FAULTING_OP:
3467 return LowerFAULTING_OP(*
MI);
3469 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3470 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3473 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3474 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3477 case TargetOpcode::PATCHABLE_TAIL_CALL:
3478 LowerPATCHABLE_TAIL_CALL(*
MI);
3480 case TargetOpcode::PATCHABLE_EVENT_CALL:
3481 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3482 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3483 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3485 case AArch64::KCFI_CHECK:
3486 LowerKCFI_CHECK(*
MI);
3489 case AArch64::HWASAN_CHECK_MEMACCESS:
3490 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3491 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3492 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3493 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3496 case AArch64::SEH_StackAlloc:
3500 case AArch64::SEH_SaveFPLR:
3504 case AArch64::SEH_SaveFPLR_X:
3505 assert(
MI->getOperand(0).getImm() < 0 &&
3506 "Pre increment SEH opcode must have a negative offset");
3510 case AArch64::SEH_SaveReg:
3512 MI->getOperand(1).getImm());
3515 case AArch64::SEH_SaveReg_X:
3516 assert(
MI->getOperand(1).getImm() < 0 &&
3517 "Pre increment SEH opcode must have a negative offset");
3519 -
MI->getOperand(1).getImm());
3522 case AArch64::SEH_SaveRegP:
3523 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3524 MI->getOperand(0).getImm() <= 28) {
3525 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3526 "Register paired with LR must be odd");
3528 MI->getOperand(2).getImm());
3531 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3532 "Non-consecutive registers not allowed for save_regp");
3534 MI->getOperand(2).getImm());
3537 case AArch64::SEH_SaveRegP_X:
3538 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3539 "Non-consecutive registers not allowed for save_regp_x");
3540 assert(
MI->getOperand(2).getImm() < 0 &&
3541 "Pre increment SEH opcode must have a negative offset");
3543 -
MI->getOperand(2).getImm());
3546 case AArch64::SEH_SaveFReg:
3548 MI->getOperand(1).getImm());
3551 case AArch64::SEH_SaveFReg_X:
3552 assert(
MI->getOperand(1).getImm() < 0 &&
3553 "Pre increment SEH opcode must have a negative offset");
3555 -
MI->getOperand(1).getImm());
3558 case AArch64::SEH_SaveFRegP:
3559 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3560 "Non-consecutive registers not allowed for save_regp");
3562 MI->getOperand(2).getImm());
3565 case AArch64::SEH_SaveFRegP_X:
3566 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3567 "Non-consecutive registers not allowed for save_regp_x");
3568 assert(
MI->getOperand(2).getImm() < 0 &&
3569 "Pre increment SEH opcode must have a negative offset");
3571 -
MI->getOperand(2).getImm());
3574 case AArch64::SEH_SetFP:
3578 case AArch64::SEH_AddFP:
3582 case AArch64::SEH_Nop:
3586 case AArch64::SEH_PrologEnd:
3590 case AArch64::SEH_EpilogStart:
3594 case AArch64::SEH_EpilogEnd:
3598 case AArch64::SEH_PACSignLR:
3602 case AArch64::SEH_SaveAnyRegI:
3603 assert(
MI->getOperand(1).getImm() <= 1008 &&
3604 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3606 MI->getOperand(1).getImm());
3609 case AArch64::SEH_SaveAnyRegIP:
3610 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3611 "Non-consecutive registers not allowed for save_any_reg");
3612 assert(
MI->getOperand(2).getImm() <= 1008 &&
3613 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3615 MI->getOperand(2).getImm());
3618 case AArch64::SEH_SaveAnyRegQP:
3619 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3620 "Non-consecutive registers not allowed for save_any_reg");
3621 assert(
MI->getOperand(2).getImm() >= 0 &&
3622 "SaveAnyRegQP SEH opcode offset must be non-negative");
3623 assert(
MI->getOperand(2).getImm() <= 1008 &&
3624 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3626 MI->getOperand(2).getImm());
3629 case AArch64::SEH_SaveAnyRegQPX:
3630 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3631 "Non-consecutive registers not allowed for save_any_reg");
3632 assert(
MI->getOperand(2).getImm() < 0 &&
3633 "SaveAnyRegQPX SEH opcode offset must be negative");
3634 assert(
MI->getOperand(2).getImm() >= -1008 &&
3635 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3637 -
MI->getOperand(2).getImm());
3640 case AArch64::SEH_AllocZ:
3641 assert(
MI->getOperand(0).getImm() >= 0 &&
3642 "AllocZ SEH opcode offset must be non-negative");
3643 assert(
MI->getOperand(0).getImm() <= 255 &&
3644 "AllocZ SEH opcode offset must fit into 8 bits");
3648 case AArch64::SEH_SaveZReg:
3649 assert(
MI->getOperand(1).getImm() >= 0 &&
3650 "SaveZReg SEH opcode offset must be non-negative");
3651 assert(
MI->getOperand(1).getImm() <= 255 &&
3652 "SaveZReg SEH opcode offset must fit into 8 bits");
3654 MI->getOperand(1).getImm());
3657 case AArch64::SEH_SavePReg:
3658 assert(
MI->getOperand(1).getImm() >= 0 &&
3659 "SavePReg SEH opcode offset must be non-negative");
3660 assert(
MI->getOperand(1).getImm() <= 255 &&
3661 "SavePReg SEH opcode offset must fit into 8 bits");
3663 MI->getOperand(1).getImm());
3668 recordIfImportCall(
MI);
3670 MCInstLowering.
Lower(
MI, TmpInst);
3671 EmitToStreamer(*OutStreamer, TmpInst);
3674 case AArch64::CBWPri:
3675 case AArch64::CBXPri:
3676 case AArch64::CBBAssertExt:
3677 case AArch64::CBHAssertExt:
3678 case AArch64::CBWPrr:
3679 case AArch64::CBXPrr:
3680 emitCBPseudoExpansion(
MI);
3684 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3689 MCInstLowering.
Lower(
MI, TmpInst);
3690 EmitToStreamer(*OutStreamer, TmpInst);
3693void AArch64AsmPrinter::recordIfImportCall(
3694 const llvm::MachineInstr *BranchInst) {
3695 if (!EnableImportCallOptimization)
3699 if (GV && GV->hasDLLImportStorageClass()) {
3700 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3705 .push_back({CallSiteSymbol, CalledSymbol});
3709void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3710 MCSymbol *LazyPointer) {
3727 EmitToStreamer(Adrp);
3735 MCOperand SymPageOff;
3742 EmitToStreamer(Ldr);
3745 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3746 .addReg(AArch64::X16)
3747 .addReg(AArch64::X16)
3750 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3752 .addReg(AArch64::X16));
3755void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3756 const GlobalIFunc &GI,
3757 MCSymbol *LazyPointer) {
3789 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3790 .addReg(AArch64::SP)
3791 .addReg(AArch64::FP)
3792 .addReg(AArch64::LR)
3793 .addReg(AArch64::SP)
3796 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3797 .addReg(AArch64::FP)
3798 .addReg(AArch64::SP)
3802 for (
int I = 0;
I != 4; ++
I)
3803 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3804 .addReg(AArch64::SP)
3805 .addReg(AArch64::X1 + 2 *
I)
3806 .addReg(AArch64::X0 + 2 *
I)
3807 .addReg(AArch64::SP)
3810 for (
int I = 0;
I != 4; ++
I)
3811 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3812 .addReg(AArch64::SP)
3813 .addReg(AArch64::D1 + 2 *
I)
3814 .addReg(AArch64::D0 + 2 *
I)
3815 .addReg(AArch64::SP)
3819 MCInstBuilder(AArch64::BL)
3832 EmitToStreamer(Adrp);
3840 MCOperand SymPageOff;
3847 EmitToStreamer(Ldr);
3850 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3851 .addReg(AArch64::X0)
3852 .addReg(AArch64::X16)
3855 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3856 .addReg(AArch64::X16)
3857 .addReg(AArch64::X0)
3861 for (
int I = 3;
I != -1; --
I)
3862 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3863 .addReg(AArch64::SP)
3864 .addReg(AArch64::D1 + 2 *
I)
3865 .addReg(AArch64::D0 + 2 *
I)
3866 .addReg(AArch64::SP)
3869 for (
int I = 3;
I != -1; --
I)
3870 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3871 .addReg(AArch64::SP)
3872 .addReg(AArch64::X1 + 2 *
I)
3873 .addReg(AArch64::X0 + 2 *
I)
3874 .addReg(AArch64::SP)
3877 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3878 .addReg(AArch64::SP)
3879 .addReg(AArch64::FP)
3880 .addReg(AArch64::LR)
3881 .addReg(AArch64::SP)
3884 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3886 .addReg(AArch64::X16));
3889const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
3890 const Constant *BaseCV,
3900char AArch64AsmPrinter::ID = 0;
3903 "AArch64 Assembly Printer",
false,
false)
3907LLVMInitializeAArch64AsmPrinter() {
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.
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,...