77#define DEBUG_TYPE "AArch64AsmPrinter"
82 "Number of zero-cycle FPR zeroing instructions expanded from "
83 "canonical pseudo instructions");
91 cl::desc(
"Check pointer authentication auth/resign failures"),
100 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
102 unsigned InstsEmitted;
104 bool EnableImportCallOptimization =
false;
106 SectionToImportedFunctionCalls;
107 unsigned PAuthIFuncNextUniqueID = 1;
112 AArch64AsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
114 MCInstLowering(OutContext, *this), FM(*this) {}
116 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
120 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const {
121 return MCInstLowering.lowerOperand(MO, MCOp);
124 const MCExpr *lowerConstantPtrAuth(
const ConstantPtrAuth &CPA)
override;
126 const MCExpr *lowerBlockAddressConstant(
const BlockAddress &BA)
override;
128 void emitStartOfAsmFile(
Module &M)
override;
129 void emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
130 ArrayRef<unsigned> JumpTableIndices)
override;
133 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
134 const MCSymbol *BranchLabel)
const override;
136 void emitFunctionEntryLabel()
override;
138 void emitXXStructor(
const DataLayout &
DL,
const Constant *CV)
override;
140 void LowerJumpTableDest(MCStreamer &OutStreamer,
const MachineInstr &
MI);
142 void LowerHardenedBRJumpTable(
const MachineInstr &
MI);
144 void LowerMOPS(MCStreamer &OutStreamer,
const MachineInstr &
MI);
146 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &
SM,
147 const MachineInstr &
MI);
148 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
149 const MachineInstr &
MI);
150 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
151 const MachineInstr &
MI);
152 void LowerFAULTING_OP(
const MachineInstr &
MI);
154 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI);
155 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI);
156 void LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI);
157 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
159 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
160 HwasanMemaccessTuple;
161 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
162 void LowerKCFI_CHECK(
const MachineInstr &
MI);
163 void LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI);
164 void emitHwasanMemaccessSymbols(
Module &M);
166 void emitSled(
const MachineInstr &
MI, SledKind Kind);
174 if (STI->isX16X17Safer())
175 return Reg == AArch64::X16 ||
Reg == AArch64::X17;
181 void emitPtrauthBranch(
const MachineInstr *
MI);
183 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
187 const MCSymbol *OnFailure =
nullptr);
190 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
192 struct PtrAuthSchema {
194 const MachineOperand &AddrDiscOp);
199 bool AddrDiscIsKilled;
204 PtrAuthSchema AuthSchema,
205 std::optional<PtrAuthSchema> SignSchema,
206 std::optional<uint64_t> Addend,
Value *DS);
211 bool emitDeactivationSymbolRelocation(
Value *DS);
214 void emitPtrauthSign(
const MachineInstr *
MI);
238 bool MayClobberAddrDisc =
false);
241 void LowerLOADauthptrstatic(
const MachineInstr &
MI);
245 void LowerMOVaddrPAC(
const MachineInstr &
MI);
250 void LowerLOADgotAUTH(
const MachineInstr &
MI);
252 void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
253 void emitAddress(MCRegister
Reg,
const MCExpr *Expr, MCRegister Tmp,
254 bool DSOLocal,
const MCSubtargetInfo &STI);
256 const MCExpr *emitPAuthRelocationAsIRelative(
258 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
262 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
265 void emitAttributes(
unsigned Flags, uint64_t PAuthABIPlatform,
266 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
269 void emitCBPseudoExpansion(
const MachineInstr *
MI);
271 void EmitToStreamer(MCStreamer &S,
const MCInst &Inst);
272 void EmitToStreamer(
const MCInst &Inst) {
273 EmitToStreamer(*OutStreamer, Inst);
278 void emitFunctionHeaderComment()
override;
280 void getAnalysisUsage(AnalysisUsage &AU)
const override {
285 bool runOnMachineFunction(MachineFunction &MF)
override {
286 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
287 PSI = &PSIW->getPSI();
289 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
290 SDPI = &SDPIW->getStaticDataProfileInfo();
292 AArch64FI = MF.
getInfo<AArch64FunctionInfo>();
295 SetupMachineFunction(MF);
297 if (STI->isTargetCOFF()) {
304 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
305 OutStreamer->emitCOFFSymbolStorageClass(Scl);
306 OutStreamer->emitCOFFSymbolType(
Type);
307 OutStreamer->endCOFFSymbolDef();
321 const Constant *BaseCV =
nullptr,
322 uint64_t
Offset = 0)
override;
325 void printOperand(
const MachineInstr *
MI,
unsigned OpNum, raw_ostream &O);
327 bool printAsmRegInClass(
const MachineOperand &MO,
328 const TargetRegisterClass *RC,
unsigned AltName,
331 bool PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
332 const char *ExtraCode, raw_ostream &O)
override;
333 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
334 const char *ExtraCode, raw_ostream &O)
override;
336 void PrintDebugValueComment(
const MachineInstr *
MI, raw_ostream &OS);
338 void emitFunctionBodyEnd()
override;
339 void emitGlobalAlias(
const Module &M,
const GlobalAlias &GA)
override;
341 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
342 void emitEndOfAsmFile(
Module &M)
override;
344 AArch64FunctionInfo *AArch64FI =
nullptr;
350 void emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift);
351 void emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift);
359 void emitFMov0(
const MachineInstr &
MI);
360 void emitFMov0AsFMov(
const MachineInstr &
MI,
Register DestReg);
362 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
364 MInstToMCSymbol LOHInstToLabel;
366 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
367 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
370 const MCSubtargetInfo *getIFuncMCSubtargetInfo()
const override {
374 void emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
375 MCSymbol *LazyPointer)
override;
376 void emitMachOIFuncStubHelperBody(
Module &M,
const GlobalIFunc &GI,
377 MCSymbol *LazyPointer)
override;
382 void recordIfImportCall(
const MachineInstr *BranchInst);
387void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
388 const Triple &
TT = TM.getTargetTriple();
390 if (
TT.isOSBinFormatCOFF()) {
391 emitCOFFFeatureSymbol(M);
392 emitCOFFReplaceableFunctionData(M);
394 if (
M.getModuleFlag(
"import-call-optimization"))
395 EnableImportCallOptimization =
true;
398 if (!
TT.isOSBinFormatELF())
403 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
406 unsigned BAFlags = 0;
407 unsigned GNUFlags = 0;
409 M.getModuleFlag(
"branch-target-enforcement"))) {
410 if (!BTE->isZero()) {
411 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
417 M.getModuleFlag(
"guarded-control-stack"))) {
418 if (!GCS->isZero()) {
419 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
425 M.getModuleFlag(
"sign-return-address"))) {
426 if (!Sign->isZero()) {
427 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
432 uint64_t PAuthABIPlatform = -1;
434 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
435 PAuthABIPlatform = PAP->getZExtValue();
438 uint64_t PAuthABIVersion = -1;
440 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
441 PAuthABIVersion = PAV->getZExtValue();
445 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
447 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
450void AArch64AsmPrinter::emitFunctionHeaderComment() {
451 const AArch64FunctionInfo *FI = MF->
getInfo<AArch64FunctionInfo>();
453 if (OutlinerString != std::nullopt)
454 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
457void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
460 if (
F.hasFnAttribute(
"patchable-function-entry")) {
462 if (
F.getFnAttribute(
"patchable-function-entry")
464 .getAsInteger(10, Num))
470 emitSled(
MI, SledKind::FUNCTION_ENTER);
473void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
474 emitSled(
MI, SledKind::FUNCTION_EXIT);
477void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
478 emitSled(
MI, SledKind::TAIL_CALL);
481void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
482 static const int8_t NoopsInSledCount = 7;
503 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
504 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
505 OutStreamer->emitLabel(CurSled);
506 auto Target = OutContext.createTempSymbol();
511 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
513 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
514 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
516 OutStreamer->emitLabel(Target);
517 recordSled(CurSled,
MI, Kind, 2);
520void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
521 uint64_t PAuthABIPlatform,
522 uint64_t PAuthABIVersion,
523 AArch64TargetStreamer *TS) {
525 PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
526 PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
528 if (PAuthABIPlatform || PAuthABIVersion) {
532 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
533 AArch64BuildAttributes::SubsectionType::ULEB128);
537 PAuthABIPlatform,
"");
551 if (BTIValue || PACValue || GCSValue) {
555 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
556 AArch64BuildAttributes::SubsectionType::ULEB128);
584void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
586 auto &
O = *OutStreamer;
587 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
588 O.emitLabel(CurSled);
589 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
591 OutContext.getOrCreateSymbol(
592 Twine(MachO ?
"_" :
"") +
593 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
596 O.AddComment(
"Begin XRay typed event");
597 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
598 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
604 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
608 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
609 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
610 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
611 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
612 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
616 O.AddComment(
"End XRay typed event");
617 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
624 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
626 O.AddComment(
"Begin XRay custom event");
627 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
628 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
634 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
635 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
636 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
637 O.AddComment(
"End XRay custom event");
638 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
645 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
649void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
651 assert(std::next(
MI.getIterator())->isCall() &&
652 "KCFI_CHECK not followed by a call instruction");
653 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
654 "KCFI_CHECK call target doesn't match call operand");
658 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
659 if (AddrReg == AArch64::XZR) {
663 emitMovXReg(AddrReg, AArch64::XZR);
669 for (
auto &
Reg : ScratchRegs) {
675 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
676 "Invalid scratch registers for KCFI_CHECK");
680 int64_t PrefixNops = 0;
683 .getFnAttribute(
"patchable-function-prefix")
685 .getAsInteger(10, PrefixNops);
688 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
689 .addReg(ScratchRegs[0])
691 .addImm(-(PrefixNops * 4 + 4)));
695 const int64_t
Type =
MI.getOperand(1).getImm();
696 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
697 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
700 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
701 .addReg(AArch64::WZR)
702 .addReg(ScratchRegs[0])
703 .addReg(ScratchRegs[1])
707 EmitToStreamer(*OutStreamer,
708 MCInstBuilder(AArch64::Bcc)
717 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
721 AddrIndex = AddrReg - AArch64::X0;
731 assert(AddrIndex < 31 && TypeIndex < 31);
733 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
734 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
735 OutStreamer->emitLabel(
Pass);
738void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
746 if (
Reg == AArch64::XZR)
750 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
752 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
753 uint32_t AccessInfo =
MI.getOperand(1).getImm();
755 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
757 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
758 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
760 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
761 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
764 if (!TM.getTargetTriple().isOSBinFormatELF())
767 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
770 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
772 SymName +=
"_short_v2";
773 Sym = OutContext.getOrCreateSymbol(SymName);
776 EmitToStreamer(*OutStreamer,
777 MCInstBuilder(AArch64::BL)
781void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
782 if (HwasanMemaccessSymbols.empty())
785 const Triple &
TT = TM.getTargetTriple();
789 auto STI = std::make_unique<AArch64Subtarget>(
790 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
792 this->STI = STI.get();
795 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
797 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
799 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
801 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
804 for (
auto &
P : HwasanMemaccessSymbols) {
805 unsigned Reg = std::get<0>(
P.first);
806 bool IsShort = std::get<1>(
P.first);
807 uint32_t AccessInfo = std::get<2>(
P.first);
808 bool IsFixedShadow = std::get<3>(
P.first);
809 uint64_t FixedShadowOffset = std::get<4>(
P.first);
810 const MCSymbolRefExpr *HwasanTagMismatchRef =
811 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
814 bool HasMatchAllTag =
816 uint8_t MatchAllTag =
823 OutStreamer->switchSection(OutContext.getELFSection(
829 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
830 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
831 OutStreamer->emitLabel(Sym);
833 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
834 .addReg(AArch64::X16)
844 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
845 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
846 .addReg(AArch64::W16)
847 .addReg(AArch64::X17)
848 .addReg(AArch64::X16)
852 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
853 .addReg(AArch64::W16)
854 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
855 .addReg(AArch64::X16)
860 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
861 .addReg(AArch64::XZR)
862 .addReg(AArch64::X16)
865 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
866 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
869 HandleMismatchOrPartialSym, OutContext)));
870 MCSymbol *ReturnSym = OutContext.createTempSymbol();
871 OutStreamer->emitLabel(ReturnSym);
872 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
873 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
875 if (HasMatchAllTag) {
876 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
877 .addReg(AArch64::X17)
881 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
882 .addReg(AArch64::XZR)
883 .addReg(AArch64::X17)
887 MCInstBuilder(AArch64::Bcc)
893 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
894 .addReg(AArch64::WZR)
895 .addReg(AArch64::W16)
898 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
900 MCInstBuilder(AArch64::Bcc)
904 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
905 .addReg(AArch64::X17)
909 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
910 .addReg(AArch64::X17)
911 .addReg(AArch64::X17)
914 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
915 .addReg(AArch64::WZR)
916 .addReg(AArch64::W16)
917 .addReg(AArch64::W17)
920 MCInstBuilder(AArch64::Bcc)
924 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
925 .addReg(AArch64::X16)
928 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
929 .addReg(AArch64::W16)
930 .addReg(AArch64::X16)
933 MCInstBuilder(AArch64::SUBSXrs)
934 .addReg(AArch64::XZR)
935 .addReg(AArch64::X16)
939 MCInstBuilder(AArch64::Bcc)
943 OutStreamer->emitLabel(HandleMismatchSym);
946 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
952 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
958 if (
Reg != AArch64::X0)
959 emitMovXReg(AArch64::X0,
Reg);
966 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
971 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
972 .addReg(AArch64::X16)
976 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
977 .addReg(AArch64::X16)
978 .addReg(AArch64::X16)
982 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
990 const MCExpr *StubAuthPtrRef) {
993 OutStreamer.
emitValue(StubAuthPtrRef, 8);
996void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
997 emitHwasanMemaccessSymbols(M);
999 const Triple &
TT = TM.getTargetTriple();
1000 if (
TT.isOSBinFormatMachO()) {
1002 MachineModuleInfoMachO &MMIMacho =
1003 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1007 if (!Stubs.empty()) {
1009 OutStreamer->switchSection(
1012 emitAlignment(
Align(8));
1014 for (
const auto &Stub : Stubs)
1017 OutStreamer->addBlankLine();
1025 OutStreamer->emitSubsectionsViaSymbols();
1028 if (
TT.isOSBinFormatELF()) {
1030 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1034 if (!Stubs.empty()) {
1035 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1037 emitAlignment(
Align(8));
1039 for (
const auto &Stub : Stubs)
1042 OutStreamer->addBlankLine();
1053 M.getModuleFlag(
"ptrauth-elf-got"));
1054 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1055 for (
const GlobalValue &GV :
M.global_values())
1057 !GV.getName().starts_with(
"llvm."))
1058 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1067 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1068 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1071 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1072 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1083 for (
auto &[Section, CallsToImportedFuncs] :
1084 SectionToImportedFunctionCalls) {
1086 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1087 OutStreamer->emitInt32(SectionSize);
1088 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1089 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1091 OutStreamer->emitInt32(0x13);
1092 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1093 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1099void AArch64AsmPrinter::emitLOHs() {
1103 for (
const MachineInstr *
MI :
D.getArgs()) {
1104 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1105 assert(LabelIt != LOHInstToLabel.end() &&
1106 "Label hasn't been inserted for LOH related instruction");
1109 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1114void AArch64AsmPrinter::emitFunctionBodyEnd() {
1120MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1124 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1125 return OutContext.getOrCreateSymbol(
1126 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1127 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1132void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1134 const MachineOperand &MO =
MI->getOperand(OpNum);
1150 PrintSymbolOperand(MO, O);
1161bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1185bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1186 const TargetRegisterClass *RC,
1187 unsigned AltName, raw_ostream &O) {
1188 assert(MO.
isReg() &&
"Should only get here with a register!");
1189 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1198bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1199 const char *ExtraCode, raw_ostream &O) {
1200 const MachineOperand &MO =
MI->getOperand(OpNum);
1207 if (ExtraCode && ExtraCode[0]) {
1208 if (ExtraCode[1] != 0)
1211 switch (ExtraCode[0]) {
1219 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1232 const TargetRegisterClass *RC;
1233 switch (ExtraCode[0]) {
1235 RC = &AArch64::FPR8RegClass;
1238 RC = &AArch64::FPR16RegClass;
1241 RC = &AArch64::FPR32RegClass;
1244 RC = &AArch64::FPR64RegClass;
1247 RC = &AArch64::FPR128RegClass;
1250 RC = &AArch64::ZPRRegClass;
1255 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1276 unsigned AltName = AArch64::NoRegAltName;
1277 const TargetRegisterClass *RegClass;
1279 RegClass = &AArch64::ZPRRegClass;
1281 RegClass = &AArch64::PPRRegClass;
1283 RegClass = &AArch64::PNRRegClass;
1285 RegClass = &AArch64::FPR128RegClass;
1286 AltName = AArch64::vreg;
1290 return printAsmRegInClass(MO, RegClass, AltName, O);
1297bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1299 const char *ExtraCode,
1301 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1304 const MachineOperand &MO =
MI->getOperand(OpNum);
1305 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1310void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1312 unsigned NOps =
MI->getNumOperands();
1314 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1316 OS <<
MI->getDebugVariable()->getName();
1319 assert(
MI->isIndirectDebugValue());
1331void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1332 ArrayRef<unsigned> JumpTableIndices) {
1334 if (JumpTableIndices.
empty())
1336 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1340 MCSection *ReadOnlySec =
nullptr;
1341 if (TM.Options.EnableStaticDataPartitioning) {
1347 OutStreamer->switchSection(ReadOnlySec);
1349 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1350 for (
unsigned JTI : JumpTableIndices) {
1351 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1354 if (JTBBs.empty())
continue;
1356 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1358 OutStreamer->emitLabel(GetJTISymbol(JTI));
1363 for (
auto *JTBB : JTBBs) {
1364 const MCExpr *
Value =
1383AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1384 const MachineInstr *BranchInstr,
1385 const MCSymbol *BranchLabel)
const {
1386 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1389 switch (AFI->getJumpTableEntrySize(JTI)) {
1391 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1394 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1397 EntrySize = codeview::JumpTableEntrySize::Int32;
1402 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1405void AArch64AsmPrinter::emitFunctionEntryLabel() {
1406 const Triple &
TT = TM.getTargetTriple();
1407 if (
TT.isOSBinFormatELF() &&
1410 CallingConv::AArch64_SVE_VectorCall ||
1411 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1413 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1424 OutStreamer->emitAssignment(
1428 auto getSymbolFromMetadata = [&](StringRef
Name) {
1432 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1439 for (MDNode *Node : UnmangledNames) {
1441 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1442 if (std::optional<std::string> MangledName =
1445 MMI->getContext().getOrCreateSymbol(*MangledName);
1446 emitFunctionAlias(UnmangledSym, ECMangledSym);
1449 if (MCSymbol *ECMangledSym =
1450 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1451 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1455void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1456 const Constant *CV) {
1458 if (CPA->hasAddressDiscriminator() &&
1459 !CPA->hasSpecialAddressDiscriminator(
1462 "unexpected address discrimination value for ctors/dtors entry, only "
1463 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1472void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1473 const GlobalAlias &GA) {
1479 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1481 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1484 OutStreamer->beginCOFFSymbolDef(ExpSym);
1488 OutStreamer->endCOFFSymbolDef();
1490 OutStreamer->beginCOFFSymbolDef(Sym);
1494 OutStreamer->endCOFFSymbolDef();
1495 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1496 OutStreamer->emitAssignment(
1513void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1514 const llvm::MachineInstr &
MI) {
1515 Register DestReg =
MI.getOperand(0).getReg();
1516 Register ScratchReg =
MI.getOperand(1).getReg();
1518 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1519 Register TableReg =
MI.getOperand(2).getReg();
1520 Register EntryReg =
MI.getOperand(3).getReg();
1521 int JTIdx =
MI.getOperand(4).getIndex();
1527 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1538 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1540 .addExpr(LabelExpr));
1545 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1546 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1547 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1552 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1553 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1557 .addImm(
Size == 1 ? 0 : 1));
1561 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1565 .addImm(
Size == 4 ? 0 : 2));
1568void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1570 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1572 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1573 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1589 MachineOperand JTOp =
MI.getOperand(0);
1593 "unsupported compressed jump table");
1595 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1599 uint64_t MaxTableEntry = NumTableEntries - 1;
1601 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1602 .addReg(AArch64::XZR)
1603 .addReg(AArch64::X16)
1604 .addImm(MaxTableEntry)
1607 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1612 if ((MaxTableEntry >>
Offset) == 0)
1614 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1617 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1618 .addReg(AArch64::XZR)
1619 .addReg(AArch64::X16)
1620 .addReg(AArch64::X17)
1626 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1627 .addReg(AArch64::X16)
1628 .addReg(AArch64::X16)
1629 .addReg(AArch64::XZR)
1633 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1634 MCOperand JTMCHi, JTMCLo;
1644 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1646 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1647 .addReg(AArch64::X17)
1648 .addReg(AArch64::X17)
1652 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1653 .addReg(AArch64::X16)
1654 .addReg(AArch64::X17)
1655 .addReg(AArch64::X16)
1666 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1668 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1669 .addReg(AArch64::X16)
1670 .addReg(AArch64::X17)
1671 .addReg(AArch64::X16)
1674 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1677void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1678 const llvm::MachineInstr &
MI) {
1679 unsigned Opcode =
MI.getOpcode();
1681 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1683 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1684 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1685 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1686 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1687 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1688 if (Opcode == AArch64::MOPSMemorySetPseudo)
1689 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1690 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1691 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1694 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1695 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1697 for (
auto Op :
Ops) {
1699 auto MCIB = MCInstBuilder(
Op);
1701 MCIB.addReg(
MI.getOperand(i++).getReg());
1702 MCIB.addReg(
MI.getOperand(i++).getReg());
1704 MCIB.addReg(
MI.getOperand(i++).getReg());
1706 MCIB.addReg(
MI.getOperand(i++).getReg());
1707 MCIB.addReg(
MI.getOperand(i++).getReg());
1708 MCIB.addReg(
MI.getOperand(i++).getReg());
1710 EmitToStreamer(OutStreamer, MCIB);
1714void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &
SM,
1715 const MachineInstr &
MI) {
1716 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1719 MCSymbol *MILabel = Ctx.createTempSymbol();
1722 SM.recordStackMap(*MILabel,
MI);
1723 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1726 const MachineBasicBlock &
MBB = *
MI.getParent();
1729 while (NumNOPBytes > 0) {
1730 if (MII ==
MBB.
end() || MII->isCall() ||
1731 MII->getOpcode() == AArch64::DBG_VALUE ||
1732 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1733 MII->getOpcode() == TargetOpcode::STACKMAP)
1740 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1741 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1746void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
1747 const MachineInstr &
MI) {
1749 MCSymbol *MILabel = Ctx.createTempSymbol();
1751 SM.recordPatchPoint(*MILabel,
MI);
1753 PatchPointOpers Opers(&
MI);
1755 int64_t CallTarget = Opers.getCallTarget().getImm();
1756 unsigned EncodedBytes = 0;
1758 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1759 "High 16 bits of call target should be zero.");
1760 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1763 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1764 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1765 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1766 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1769 unsigned NumBytes = Opers.getNumPatchBytes();
1770 assert(NumBytes >= EncodedBytes &&
1771 "Patchpoint can't request size less than the length of a call.");
1772 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1773 "Invalid number of NOP bytes requested!");
1774 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1775 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1778void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
1779 const MachineInstr &
MI) {
1780 StatepointOpers SOpers(&
MI);
1781 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1782 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1783 for (
unsigned i = 0; i < PatchBytes; i += 4)
1784 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1787 const MachineOperand &CallTarget = SOpers.getCallTarget();
1788 MCOperand CallTargetMCOp;
1789 unsigned CallOpcode;
1790 switch (CallTarget.
getType()) {
1793 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1794 CallOpcode = AArch64::BL;
1798 CallOpcode = AArch64::BL;
1802 CallOpcode = AArch64::BLR;
1809 EmitToStreamer(OutStreamer,
1810 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1814 MCSymbol *MILabel = Ctx.createTempSymbol();
1816 SM.recordStatepoint(*MILabel,
MI);
1819void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1828 unsigned OperandsBeginIdx = 4;
1831 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1838 MI.setOpcode(Opcode);
1843 for (
const MachineOperand &MO :
1846 lowerOperand(MO, Dest);
1847 MI.addOperand(Dest);
1855 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1857 .addReg(AArch64::XZR)
1862void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1863 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1864 EmitToStreamer(*OutStreamer,
1865 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1871void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1872 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1873 EmitToStreamer(*OutStreamer,
1874 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1883 bool IsZeroDisc = Disc == AArch64::XZR;
1895 EmitToStreamer(AUTInst);
1900 bool IsZeroDisc = Disc == AArch64::XZR;
1912 EmitToStreamer(PACInst);
1917 bool IsZeroDisc = Disc == AArch64::XZR;
1927 EmitToStreamer(Inst);
1930void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1931 Register DestReg =
MI.getOperand(0).getReg();
1932 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1933 if (STI->hasZeroCycleZeroingFPR64()) {
1935 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1936 if (AArch64::FPR16RegClass.
contains(DestReg))
1937 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1938 &AArch64::FPR64RegClass);
1939 else if (AArch64::FPR32RegClass.
contains(DestReg))
1940 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1941 &AArch64::FPR64RegClass);
1949 EmitToStreamer(*OutStreamer, MOVI);
1950 ++NumZCZeroingInstrsFPR;
1951 }
else if (STI->hasZeroCycleZeroingFPR128()) {
1953 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1954 if (AArch64::FPR16RegClass.
contains(DestReg)) {
1955 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1956 &AArch64::FPR128RegClass);
1957 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
1958 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1959 &AArch64::FPR128RegClass);
1962 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
1963 &AArch64::FPR128RegClass);
1970 EmitToStreamer(*OutStreamer, MOVI);
1971 ++NumZCZeroingInstrsFPR;
1973 emitFMov0AsFMov(
MI, DestReg);
1976 emitFMov0AsFMov(
MI, DestReg);
1980void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
1983 switch (
MI.getOpcode()) {
1986 case AArch64::FMOVH0:
1987 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1988 if (!STI->hasFullFP16())
1989 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1993 case AArch64::FMOVS0:
1998 case AArch64::FMOVD0:
2004 EmitToStreamer(*OutStreamer, FMov);
2007Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint64_t Disc,
2010 bool MayClobberAddrDisc) {
2011 assert(isPtrauthRegSafe(ScratchReg) &&
2012 "Safe scratch register must be provided by the caller");
2016 if (AddrDisc == AArch64::NoRegister)
2017 AddrDisc = AArch64::XZR;
2025 if (AddrDisc == AArch64::XZR) {
2026 emitMOVZ(ScratchReg, Disc, 0);
2033 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2034 ScratchReg = AddrDisc;
2036 emitMovXReg(ScratchReg, AddrDisc);
2037 assert(ScratchReg != AddrDisc &&
2038 "Forbidden to clobber AddrDisc, but have to");
2041 emitMOVK(ScratchReg, Disc, 48);
2055void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2087 if (Method == AuthCheckMethod::None)
2089 if (Method == AuthCheckMethod::DummyLoad) {
2090 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2094 assert(!OnFailure &&
"DummyLoad always traps on error");
2098 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2099 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2101 emitMovXReg(ScratchReg, TestedReg);
2103 if (Method == AuthCheckMethod::XPAC) {
2107 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2112 assert(TestedReg == AArch64::LR &&
2113 "XPACHint mode is only compatible with checking the LR register");
2115 "XPACHint mode is only compatible with I-keys");
2116 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2120 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2121 .addReg(AArch64::XZR)
2128 MCInstBuilder(AArch64::Bcc)
2131 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2133 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2140 MCInstBuilder(AArch64::TBZX)
2151 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2165 case AuthCheckMethod::XPACHint:
2168 case AuthCheckMethod::XPAC:
2170 emitMovXReg(TestedReg, ScratchReg);
2177 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2182 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2194void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2198 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2199 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2202 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2206 "Neither x16 nor x17 is available as a scratch register");
2209 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2213bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2219 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2222 MCSymbol *Dot = OutContext.createTempSymbol();
2227 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2233AArch64AsmPrinter::PtrAuthSchema::PtrAuthSchema(
2235 :
Key(
Key), IntDisc(IntDisc), AddrDisc(AddrDiscOp.
getReg()),
2236 AddrDiscIsKilled(AddrDiscOp.isKill()) {}
2238void AArch64AsmPrinter::emitPtrauthAuthResign(
2240 std::optional<PtrAuthSchema> SignSchema, std::optional<uint64_t> OptAddend,
2242 const bool IsResign = SignSchema.has_value();
2243 const bool HasLoad = OptAddend.has_value();
2256 bool ShouldCheck =
true;
2263 ShouldCheck = ShouldTrap =
false;
2270 ShouldCheck = ShouldTrap =
false;
2277 ShouldCheck = ShouldTrap =
true;
2283 emitPtrauthDiscriminator(AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2284 AuthSchema.AddrDiscIsKilled);
2286 if (!emitDeactivationSymbolRelocation(DS))
2287 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2290 if (!IsResign && (!ShouldCheck || !ShouldTrap))
2296 if (IsResign && !ShouldTrap)
2297 EndSym = createTempSymbol(
"resign_end_");
2299 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2300 AArch64PAuth::AuthCheckMethod::XPAC,
2311 int64_t Addend = *OptAddend;
2315 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWpre)
2316 .addReg(AArch64::X16)
2317 .addReg(AArch64::X17)
2318 .addReg(AArch64::X16)
2325 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2326 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
2327 .addReg(AArch64::X16)
2328 .addReg(AArch64::X16)
2329 .addImm((Addend >> BitPos) & 0xfff)
2336 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi)
2337 .addReg(AArch64::X17)
2338 .addImm(Addend & 0xffff)
2343 uint16_t Fragment =
static_cast<uint16_t
>(Addend >>
Offset);
2346 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKXi)
2347 .addReg(AArch64::X17)
2348 .addReg(AArch64::X17)
2353 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
2354 .addReg(AArch64::X16)
2355 .addReg(AArch64::X16)
2356 .addReg(AArch64::X17)
2360 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWui)
2361 .addReg(AArch64::X17)
2362 .addReg(AArch64::X16)
2366 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
2367 .addReg(AArch64::X16)
2368 .addReg(AArch64::X16)
2369 .addReg(AArch64::X17)
2375 Register PACDiscReg = emitPtrauthDiscriminator(SignSchema->IntDisc,
2376 SignSchema->AddrDisc, Scratch);
2377 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2384void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2387 uint64_t Disc =
MI->getOperand(3).getImm();
2388 Register AddrDisc =
MI->getOperand(4).getReg();
2389 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2393 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2394 assert(ScratchReg != AddrDisc &&
2395 "Neither X16 nor X17 is available as a scratch register");
2398 Register DiscReg = emitPtrauthDiscriminator(
2399 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2401 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2404 emitPAC(
Key, Val, DiscReg);
2407void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2408 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2409 unsigned BrTarget =
MI->getOperand(0).getReg();
2412 uint64_t Disc =
MI->getOperand(2).getImm();
2414 unsigned AddrDisc =
MI->getOperand(3).getReg();
2420 if (BrTarget == AddrDisc)
2437 bool AddrDiscIsImplicitDef =
2438 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2439 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2440 AddrDiscIsImplicitDef);
2441 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2444void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2447 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2448 const bool IsNeg = Addend < 0;
2450 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2453 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2456 .addImm((AbsOffset >> BitPos) & 0xfff)
2460 const uint64_t UAddend = Addend;
2461 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2463 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2465 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2466 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2467 uint64_t Shifted = UAddend >> BitPos;
2469 return Shifted != 0;
2470 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2471 if (((Shifted >>
I) & 0xffff) != 0xffff)
2475 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2476 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2478 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2487void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2488 MCRegister Tmp,
bool DSOLocal,
2489 const MCSubtargetInfo &STI) {
2495 MCInstBuilder(AArch64::ADRP)
2499 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2509 MCInstBuilder(AArch64::ADRP)
2514 MCInstBuilder(AArch64::LDRXui)
2525 if (!TT.isOSBinFormatELF())
2529 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2530 TT.isOSDragonFly() || TT.isOSNetBSD();
2584const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2586 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2587 const Triple &
TT = TM.getTargetTriple();
2599 auto STI = std::make_unique<AArch64Subtarget>(
2600 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2602 this->STI = STI.get();
2608 const MCSymbolELF *Group =
2623 .addReg(AArch64::X0)
2628 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2630 if (HasAddressDiversity) {
2635 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2639 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2641 "' out of range [0, 0xFFFF]");
2643 emitMOVZ(AArch64::X1, Disc, 0);
2650 auto *PrePACInstExpr =
2662 const MCSymbolRefExpr *EmuPACRef =
2664 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2671 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2679AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2680 MCContext &Ctx = OutContext;
2685 getDataLayout(),
Offset,
true);
2703 const MCExpr *DSExpr =
nullptr;
2715 "' out of range [0, " +
2723 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2725 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2730 "' out of range [0, 0xFFFF]");
2736 "expressions on this target");
2743void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2744 unsigned DstReg =
MI.getOperand(0).getReg();
2745 const MachineOperand &GAOp =
MI.getOperand(1);
2746 const uint64_t KeyC =
MI.getOperand(2).getImm();
2748 "key is out of range [0, AArch64PACKey::LAST]");
2750 const uint64_t Disc =
MI.getOperand(3).getImm();
2752 "constant discriminator is out of range [0, 0xffff]");
2761 if (TM.getTargetTriple().isOSBinFormatELF()) {
2763 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2766 "non-zero offset for $auth_ptr$ stub slots is not supported");
2768 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2770 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2771 "LOADauthptrstatic is implemented only for MachO/ELF");
2773 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2774 getObjFileLowering());
2777 "non-zero offset for $auth_ptr$ stub slots is not supported");
2779 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2782 MachineOperand StubMOHi =
2786 MCOperand StubMCHi, StubMCLo;
2793 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2795 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2801void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2802 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2803 const bool IsELFSignedGOT =
MI.getParent()
2805 ->getInfo<AArch64FunctionInfo>()
2806 ->hasELFSignedGOT();
2807 MachineOperand GAOp =
MI.getOperand(0);
2808 const uint64_t KeyC =
MI.getOperand(1).getImm();
2810 "key is out of range [0, AArch64PACKey::LAST]");
2812 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2813 const uint64_t Disc =
MI.getOperand(3).getImm();
2860 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2861 MCOperand GAMCHi, GAMCLo;
2874 MCInstBuilder(AArch64::ADRP)
2875 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2879 if (IsELFSignedGOT) {
2880 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2881 .addReg(AArch64::X17)
2882 .addReg(AArch64::X17)
2886 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2887 .addReg(AArch64::X16)
2888 .addReg(AArch64::X17)
2896 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2898 if (!STI->hasFPAC())
2899 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2900 AArch64PAuth::AuthCheckMethod::XPAC);
2902 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2903 .addReg(AArch64::X16)
2904 .addReg(AArch64::X16)
2908 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2909 .addReg(AArch64::X16)
2910 .addReg(AArch64::X16)
2915 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2916 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2918 emitPAC(
Key, AArch64::X16, DiscReg);
2921void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2923 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2924 const MachineOperand &GAMO =
MI.getOperand(1);
2931 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2932 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2933 .addReg(AuthResultReg)
2934 .addReg(AArch64::X17)
2937 MachineOperand GAHiOp(GAMO);
2938 MachineOperand GALoOp(GAMO);
2942 MCOperand GAMCHi, GAMCLo;
2947 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2949 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2950 .addReg(AArch64::X17)
2951 .addReg(AArch64::X17)
2955 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2956 .addReg(AuthResultReg)
2957 .addReg(AArch64::X17)
2964 UndefWeakSym = createTempSymbol(
"undef_weak");
2966 MCInstBuilder(AArch64::CBZX)
2967 .addReg(AuthResultReg)
2975 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2980 if (!STI->hasFPAC()) {
2981 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2982 AArch64PAuth::AuthCheckMethod::XPAC);
2984 emitMovXReg(DstReg, AuthResultReg);
2989AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2993 if (std::optional<uint16_t> BADisc =
2994 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3001void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3005 switch (
MI->getOpcode()) {
3008 case AArch64::CBBAssertExt:
3012 case AArch64::CBHAssertExt:
3016 case AArch64::CBWPrr:
3019 case AArch64::CBXPrr:
3022 case AArch64::CBWPri:
3026 case AArch64::CBXPri:
3034 bool NeedsRegSwap =
false;
3035 bool NeedsImmDec =
false;
3036 bool NeedsImmInc =
false;
3038#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3040 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3042 ? AArch64::CBB##RegCond##Wrr \
3043 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3044 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3045 : AArch64::CB##RegCond##Xrr))))
3061 NeedsImmDec = IsImm;
3065 NeedsRegSwap = !IsImm;
3072 NeedsRegSwap = !IsImm;
3073 NeedsImmInc = IsImm;
3077 NeedsImmDec = IsImm;
3081 NeedsRegSwap = !IsImm;
3088 NeedsRegSwap = !IsImm;
3089 NeedsImmInc = IsImm;
3097 MCOperand Lhs, Rhs, Trgt;
3098 lowerOperand(
MI->getOperand(1), Lhs);
3099 lowerOperand(
MI->getOperand(2), Rhs);
3100 lowerOperand(
MI->getOperand(3), Trgt);
3104 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3105 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3108 }
else if (NeedsImmDec) {
3112 }
else if (NeedsImmInc) {
3122 "CB immediate operand out-of-bounds");
3125 EmitToStreamer(*OutStreamer, Inst);
3130#include "AArch64GenMCPseudoLowering.inc"
3132void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3139void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3140 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3145 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3150 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3151 EmitToStreamer(*OutStreamer, OutInst);
3155 if (
MI->getOpcode() == AArch64::ADRP) {
3156 for (
auto &Opd :
MI->operands()) {
3157 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3158 "swift_async_extendedFramePointerFlags") {
3159 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3166 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3168 LOHInstToLabel[
MI] = LOHLabel;
3172 AArch64TargetStreamer *TS =
3175 switch (
MI->getOpcode()) {
3178 "Unhandled tail call instruction");
3180 case AArch64::HINT: {
3185 if (CurrentPatchableFunctionEntrySym &&
3186 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3188 int64_t
Imm =
MI->getOperand(0).getImm();
3189 if ((Imm & 32) && (Imm & 6)) {
3191 MCInstLowering.
Lower(
MI, Inst);
3192 EmitToStreamer(*OutStreamer, Inst);
3193 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3194 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3200 case AArch64::MOVMCSym: {
3201 Register DestReg =
MI->getOperand(0).getReg();
3202 const MachineOperand &MO_Sym =
MI->getOperand(1);
3203 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3204 MCOperand Hi_MCSym, Lo_MCSym;
3217 EmitToStreamer(*OutStreamer, MovZ);
3225 EmitToStreamer(*OutStreamer, MovK);
3228 case AArch64::MOVIv2d_ns:
3236 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3237 MI->getOperand(1).getImm() == 0) {
3239 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3242 EmitToStreamer(*OutStreamer, TmpInst);
3247 case AArch64::DBG_VALUE:
3248 case AArch64::DBG_VALUE_LIST:
3250 SmallString<128> TmpStr;
3251 raw_svector_ostream OS(TmpStr);
3252 PrintDebugValueComment(
MI, OS);
3257 case AArch64::EMITBKEY: {
3259 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3260 ExceptionHandlingType != ExceptionHandling::ARM)
3263 if (getFunctionCFISectionType(*MF) == CFISection::None)
3270 case AArch64::EMITMTETAGGED: {
3272 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3273 ExceptionHandlingType != ExceptionHandling::ARM)
3276 if (getFunctionCFISectionType(*MF) != CFISection::None)
3281 case AArch64::AUTx16x17: {
3283 const Register Scratch = AArch64::X17;
3286 MI->getOperand(1).getImm(),
MI->getOperand(2));
3288 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3289 std::nullopt,
MI->getDeactivationSymbol());
3293 case AArch64::AUTxMxN: {
3295 const Register Scratch =
MI->getOperand(1).getReg();
3298 MI->getOperand(4).getImm(),
MI->getOperand(5));
3300 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3301 std::nullopt,
MI->getDeactivationSymbol());
3305 case AArch64::AUTPAC: {
3307 const Register Scratch = AArch64::X17;
3310 MI->getOperand(1).getImm(),
MI->getOperand(2));
3313 MI->getOperand(4).getImm(),
MI->getOperand(5));
3315 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3316 std::nullopt,
MI->getDeactivationSymbol());
3320 case AArch64::AUTRELLOADPAC: {
3322 const Register Scratch = AArch64::X17;
3325 MI->getOperand(1).getImm(),
MI->getOperand(2));
3328 MI->getOperand(4).getImm(),
MI->getOperand(5));
3330 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3331 MI->getOperand(6).getImm(),
3332 MI->getDeactivationSymbol());
3338 emitPtrauthSign(
MI);
3341 case AArch64::LOADauthptrstatic:
3342 LowerLOADauthptrstatic(*
MI);
3345 case AArch64::LOADgotPAC:
3346 case AArch64::MOVaddrPAC:
3347 LowerMOVaddrPAC(*
MI);
3350 case AArch64::LOADgotAUTH:
3351 LowerLOADgotAUTH(*
MI);
3356 emitPtrauthBranch(
MI);
3362 case AArch64::AUTH_TCRETURN:
3363 case AArch64::AUTH_TCRETURN_BTI: {
3366 const uint64_t Disc =
MI->getOperand(3).getImm();
3368 Register AddrDisc =
MI->getOperand(4).getReg();
3370 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3372 emitPtrauthTailCallHardening(
MI);
3375 if (Callee == AddrDisc)
3382 bool AddrDiscIsImplicitDef =
3383 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3384 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3385 AddrDiscIsImplicitDef);
3386 emitBLRA(
false,
Key, Callee, DiscReg);
3390 case AArch64::TCRETURNri:
3391 case AArch64::TCRETURNrix16x17:
3392 case AArch64::TCRETURNrix17:
3393 case AArch64::TCRETURNrinotx16:
3394 case AArch64::TCRETURNriALL: {
3395 emitPtrauthTailCallHardening(
MI);
3397 recordIfImportCall(
MI);
3401 EmitToStreamer(*OutStreamer, TmpInst);
3404 case AArch64::TCRETURNdi: {
3405 emitPtrauthTailCallHardening(
MI);
3409 recordIfImportCall(
MI);
3413 EmitToStreamer(*OutStreamer, TmpInst);
3416 case AArch64::SpeculationBarrierISBDSBEndBB: {
3421 EmitToStreamer(*OutStreamer, TmpInstDSB);
3425 EmitToStreamer(*OutStreamer, TmpInstISB);
3428 case AArch64::SpeculationBarrierSBEndBB: {
3432 EmitToStreamer(*OutStreamer, TmpInstSB);
3435 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3442 const MachineOperand &MO_Sym =
MI->getOperand(0);
3443 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3444 MCOperand SymTLSDescLo12, SymTLSDesc;
3447 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3454 EmitToStreamer(*OutStreamer, Adrp);
3462 EmitToStreamer(*OutStreamer, Ldr);
3465 Add.setOpcode(AArch64::ADDXri);
3468 Add.addOperand(SymTLSDescLo12);
3470 EmitToStreamer(*OutStreamer,
Add);
3479 EmitToStreamer(*OutStreamer, Blraa);
3483 case AArch64::TLSDESC_CALLSEQ: {
3491 const MachineOperand &MO_Sym =
MI->getOperand(0);
3492 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3493 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3497 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3504 EmitToStreamer(*OutStreamer, Adrp);
3507 if (STI->isTargetILP32()) {
3517 EmitToStreamer(*OutStreamer, Ldr);
3520 if (STI->isTargetILP32()) {
3521 Add.setOpcode(AArch64::ADDWri);
3525 Add.setOpcode(AArch64::ADDXri);
3529 Add.addOperand(SymTLSDescLo12);
3531 EmitToStreamer(*OutStreamer,
Add);
3536 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3538 EmitToStreamer(*OutStreamer, TLSDescCall);
3546 EmitToStreamer(*OutStreamer, Blr);
3551 case AArch64::JumpTableDest32:
3552 case AArch64::JumpTableDest16:
3553 case AArch64::JumpTableDest8:
3554 LowerJumpTableDest(*OutStreamer, *
MI);
3557 case AArch64::BR_JumpTable:
3558 LowerHardenedBRJumpTable(*
MI);
3561 case AArch64::FMOVH0:
3562 case AArch64::FMOVS0:
3563 case AArch64::FMOVD0:
3567 case AArch64::MOPSMemoryCopyPseudo:
3568 case AArch64::MOPSMemoryMovePseudo:
3569 case AArch64::MOPSMemorySetPseudo:
3570 case AArch64::MOPSMemorySetTaggingPseudo:
3571 LowerMOPS(*OutStreamer, *
MI);
3574 case TargetOpcode::STACKMAP:
3575 return LowerSTACKMAP(*OutStreamer,
SM, *
MI);
3577 case TargetOpcode::PATCHPOINT:
3578 return LowerPATCHPOINT(*OutStreamer,
SM, *
MI);
3580 case TargetOpcode::STATEPOINT:
3581 return LowerSTATEPOINT(*OutStreamer,
SM, *
MI);
3583 case TargetOpcode::FAULTING_OP:
3584 return LowerFAULTING_OP(*
MI);
3586 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3587 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3590 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3591 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3594 case TargetOpcode::PATCHABLE_TAIL_CALL:
3595 LowerPATCHABLE_TAIL_CALL(*
MI);
3597 case TargetOpcode::PATCHABLE_EVENT_CALL:
3598 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3599 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3600 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3602 case AArch64::KCFI_CHECK:
3603 LowerKCFI_CHECK(*
MI);
3606 case AArch64::HWASAN_CHECK_MEMACCESS:
3607 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3608 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3609 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3610 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3613 case AArch64::SEH_StackAlloc:
3617 case AArch64::SEH_SaveFPLR:
3621 case AArch64::SEH_SaveFPLR_X:
3622 assert(
MI->getOperand(0).getImm() < 0 &&
3623 "Pre increment SEH opcode must have a negative offset");
3627 case AArch64::SEH_SaveReg:
3629 MI->getOperand(1).getImm());
3632 case AArch64::SEH_SaveReg_X:
3633 assert(
MI->getOperand(1).getImm() < 0 &&
3634 "Pre increment SEH opcode must have a negative offset");
3636 -
MI->getOperand(1).getImm());
3639 case AArch64::SEH_SaveRegP:
3640 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3641 MI->getOperand(0).getImm() <= 28) {
3642 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3643 "Register paired with LR must be odd");
3645 MI->getOperand(2).getImm());
3648 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3649 "Non-consecutive registers not allowed for save_regp");
3651 MI->getOperand(2).getImm());
3654 case AArch64::SEH_SaveRegP_X:
3655 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3656 "Non-consecutive registers not allowed for save_regp_x");
3657 assert(
MI->getOperand(2).getImm() < 0 &&
3658 "Pre increment SEH opcode must have a negative offset");
3660 -
MI->getOperand(2).getImm());
3663 case AArch64::SEH_SaveFReg:
3665 MI->getOperand(1).getImm());
3668 case AArch64::SEH_SaveFReg_X:
3669 assert(
MI->getOperand(1).getImm() < 0 &&
3670 "Pre increment SEH opcode must have a negative offset");
3672 -
MI->getOperand(1).getImm());
3675 case AArch64::SEH_SaveFRegP:
3676 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3677 "Non-consecutive registers not allowed for save_regp");
3679 MI->getOperand(2).getImm());
3682 case AArch64::SEH_SaveFRegP_X:
3683 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3684 "Non-consecutive registers not allowed for save_regp_x");
3685 assert(
MI->getOperand(2).getImm() < 0 &&
3686 "Pre increment SEH opcode must have a negative offset");
3688 -
MI->getOperand(2).getImm());
3691 case AArch64::SEH_SetFP:
3695 case AArch64::SEH_AddFP:
3699 case AArch64::SEH_Nop:
3703 case AArch64::SEH_PrologEnd:
3707 case AArch64::SEH_EpilogStart:
3711 case AArch64::SEH_EpilogEnd:
3715 case AArch64::SEH_PACSignLR:
3719 case AArch64::SEH_SaveAnyRegI:
3720 assert(
MI->getOperand(1).getImm() <= 1008 &&
3721 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3723 MI->getOperand(1).getImm());
3726 case AArch64::SEH_SaveAnyRegIP:
3727 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3728 "Non-consecutive registers not allowed for save_any_reg");
3729 assert(
MI->getOperand(2).getImm() <= 1008 &&
3730 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3732 MI->getOperand(2).getImm());
3735 case AArch64::SEH_SaveAnyRegQP:
3736 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3737 "Non-consecutive registers not allowed for save_any_reg");
3738 assert(
MI->getOperand(2).getImm() >= 0 &&
3739 "SaveAnyRegQP SEH opcode offset must be non-negative");
3740 assert(
MI->getOperand(2).getImm() <= 1008 &&
3741 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3743 MI->getOperand(2).getImm());
3746 case AArch64::SEH_SaveAnyRegQPX:
3747 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3748 "Non-consecutive registers not allowed for save_any_reg");
3749 assert(
MI->getOperand(2).getImm() < 0 &&
3750 "SaveAnyRegQPX SEH opcode offset must be negative");
3751 assert(
MI->getOperand(2).getImm() >= -1008 &&
3752 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3754 -
MI->getOperand(2).getImm());
3757 case AArch64::SEH_AllocZ:
3758 assert(
MI->getOperand(0).getImm() >= 0 &&
3759 "AllocZ SEH opcode offset must be non-negative");
3760 assert(
MI->getOperand(0).getImm() <= 255 &&
3761 "AllocZ SEH opcode offset must fit into 8 bits");
3765 case AArch64::SEH_SaveZReg:
3766 assert(
MI->getOperand(1).getImm() >= 0 &&
3767 "SaveZReg SEH opcode offset must be non-negative");
3768 assert(
MI->getOperand(1).getImm() <= 255 &&
3769 "SaveZReg SEH opcode offset must fit into 8 bits");
3771 MI->getOperand(1).getImm());
3774 case AArch64::SEH_SavePReg:
3775 assert(
MI->getOperand(1).getImm() >= 0 &&
3776 "SavePReg SEH opcode offset must be non-negative");
3777 assert(
MI->getOperand(1).getImm() <= 255 &&
3778 "SavePReg SEH opcode offset must fit into 8 bits");
3780 MI->getOperand(1).getImm());
3785 recordIfImportCall(
MI);
3787 MCInstLowering.
Lower(
MI, TmpInst);
3788 EmitToStreamer(*OutStreamer, TmpInst);
3791 case AArch64::CBWPri:
3792 case AArch64::CBXPri:
3793 case AArch64::CBBAssertExt:
3794 case AArch64::CBHAssertExt:
3795 case AArch64::CBWPrr:
3796 case AArch64::CBXPrr:
3797 emitCBPseudoExpansion(
MI);
3801 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3806 MCInstLowering.
Lower(
MI, TmpInst);
3807 EmitToStreamer(*OutStreamer, TmpInst);
3810void AArch64AsmPrinter::recordIfImportCall(
3811 const llvm::MachineInstr *BranchInst) {
3812 if (!EnableImportCallOptimization)
3816 if (GV && GV->hasDLLImportStorageClass()) {
3817 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3822 .push_back({CallSiteSymbol, CalledSymbol});
3826void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3827 MCSymbol *LazyPointer) {
3844 EmitToStreamer(Adrp);
3852 MCOperand SymPageOff;
3859 EmitToStreamer(Ldr);
3862 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3863 .addReg(AArch64::X16)
3864 .addReg(AArch64::X16)
3867 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3869 .addReg(AArch64::X16));
3872void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3873 const GlobalIFunc &GI,
3874 MCSymbol *LazyPointer) {
3906 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3907 .addReg(AArch64::SP)
3908 .addReg(AArch64::FP)
3909 .addReg(AArch64::LR)
3910 .addReg(AArch64::SP)
3913 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3914 .addReg(AArch64::FP)
3915 .addReg(AArch64::SP)
3919 for (
int I = 0;
I != 4; ++
I)
3920 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3921 .addReg(AArch64::SP)
3922 .addReg(AArch64::X1 + 2 *
I)
3923 .addReg(AArch64::X0 + 2 *
I)
3924 .addReg(AArch64::SP)
3927 for (
int I = 0;
I != 4; ++
I)
3928 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3929 .addReg(AArch64::SP)
3930 .addReg(AArch64::D1 + 2 *
I)
3931 .addReg(AArch64::D0 + 2 *
I)
3932 .addReg(AArch64::SP)
3936 MCInstBuilder(AArch64::BL)
3949 EmitToStreamer(Adrp);
3957 MCOperand SymPageOff;
3964 EmitToStreamer(Ldr);
3967 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3968 .addReg(AArch64::X0)
3969 .addReg(AArch64::X16)
3972 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3973 .addReg(AArch64::X16)
3974 .addReg(AArch64::X0)
3978 for (
int I = 3;
I != -1; --
I)
3979 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3980 .addReg(AArch64::SP)
3981 .addReg(AArch64::D1 + 2 *
I)
3982 .addReg(AArch64::D0 + 2 *
I)
3983 .addReg(AArch64::SP)
3986 for (
int I = 3;
I != -1; --
I)
3987 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3988 .addReg(AArch64::SP)
3989 .addReg(AArch64::X1 + 2 *
I)
3990 .addReg(AArch64::X0 + 2 *
I)
3991 .addReg(AArch64::SP)
3994 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3995 .addReg(AArch64::SP)
3996 .addReg(AArch64::FP)
3997 .addReg(AArch64::LR)
3998 .addReg(AArch64::SP)
4001 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4003 .addReg(AArch64::X16));
4006const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4007 const Constant *BaseCV,
4017char AArch64AsmPrinter::ID = 0;
4020 "AArch64 Assembly Printer",
false,
false)
4024LLVMInitializeAArch64AsmPrinter() {
static cl::opt< PtrauthCheckMode > PtrauthAuthChecks("aarch64-ptrauth-auth-checks", cl::Hidden, cl::values(clEnumValN(Unchecked, "none", "don't test for failure"), clEnumValN(Poison, "poison", "poison on failure"), clEnumValN(Trap, "trap", "trap on failure")), cl::desc("Check pointer authentication auth/resign failures"), cl::init(Default))
#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond)
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
static bool targetSupportsIRelativeRelocation(const Triple &TT)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_EXTERNAL_VISIBILITY
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr unsigned SM(unsigned Version)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static 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.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static SectionKind getMetadata()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void push_back(const T &Elt)
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
virtual MCSection * getSectionForJumpTable(const Function &F, const TargetMachine &TM) const
Primary interface to the complete machine description for the target machine.
MCRegister getRegister(unsigned i) const
Return the specified register in the class.
bool regsOverlap(Register RegA, Register RegB) const
Returns true if the two registers are equal or alias each other.
Triple - Helper class for working with autoconf configuration names.
bool isFunctionTy() const
True if this is an instance of FunctionType.
LLVM Value Representation.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
StringRef getVendorName(unsigned const Vendor)
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
AuthCheckMethod
Variants of check performed on an authenticated pointer.
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
SymbolStorageClass
Storage class tells where and what the symbol represents.
@ IMAGE_SYM_CLASS_EXTERNAL
External symbol.
@ IMAGE_SYM_CLASS_STATIC
Static.
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
@ SCT_COMPLEX_TYPE_SHIFT
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ GNU_PROPERTY_AARCH64_FEATURE_1_BTI
@ GNU_PROPERTY_AARCH64_FEATURE_1_PAC
@ GNU_PROPERTY_AARCH64_FEATURE_1_GCS
@ S_REGULAR
S_REGULAR - Regular section.
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
FunctionAddr VTableAddr Value
LLVM_ABI std::optional< std::string > getArm64ECMangledFunctionName(StringRef Name)
Returns the ARM64EC mangled function name unless the input is already mangled.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
scope_exit(Callable) -> scope_exit< Callable >
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
std::string utostr(uint64_t X, bool isNeg=false)
static unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K, bool Zero)
Return B(L)RA opcode to be used for an authenticated branch or call using the given key,...
Target & getTheAArch64leTarget()
auto dyn_cast_or_null(const Y &Val)
Target & getTheAArch64_32Target()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Target & getTheARM64_32Target()
static MCRegister getXRegFromWReg(MCRegister Reg)
Target & getTheARM64Target()
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static MCRegister getXRegFromXRegTuple(MCRegister RegTuple)
static unsigned getPACOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return PAC opcode to be used for a ptrauth sign using the given key, or its PAC*Z variant that doesn'...
static MCRegister getWRegFromXReg(MCRegister Reg)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static unsigned getAUTOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return AUT opcode to be used for a ptrauth auth using the given key, or its AUT*Z variant that doesn'...
@ MCSA_WeakAntiDep
.weak_anti_dep (COFF)
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
Implement std::hash so that hash_code can be used in STL containers.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...