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);
2680AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2681 MCContext &Ctx = OutContext;
2686 getDataLayout(),
Offset,
true);
2704 const MCExpr *DSExpr =
nullptr;
2716 "' out of range [0, " +
2724 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2726 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2731 "' out of range [0, 0xFFFF]");
2737 "expressions on this target");
2744void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2745 unsigned DstReg =
MI.getOperand(0).getReg();
2746 const MachineOperand &GAOp =
MI.getOperand(1);
2747 const uint64_t KeyC =
MI.getOperand(2).getImm();
2749 "key is out of range [0, AArch64PACKey::LAST]");
2751 const uint64_t Disc =
MI.getOperand(3).getImm();
2753 "constant discriminator is out of range [0, 0xffff]");
2762 if (TM.getTargetTriple().isOSBinFormatELF()) {
2764 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2767 "non-zero offset for $auth_ptr$ stub slots is not supported");
2769 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2771 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2772 "LOADauthptrstatic is implemented only for MachO/ELF");
2774 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2775 getObjFileLowering());
2778 "non-zero offset for $auth_ptr$ stub slots is not supported");
2780 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2783 MachineOperand StubMOHi =
2787 MCOperand StubMCHi, StubMCLo;
2794 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2796 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2802void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2803 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2804 const bool IsELFSignedGOT =
MI.getParent()
2806 ->getInfo<AArch64FunctionInfo>()
2807 ->hasELFSignedGOT();
2808 MachineOperand GAOp =
MI.getOperand(0);
2809 const uint64_t KeyC =
MI.getOperand(1).getImm();
2811 "key is out of range [0, AArch64PACKey::LAST]");
2813 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2814 const uint64_t Disc =
MI.getOperand(3).getImm();
2861 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2862 MCOperand GAMCHi, GAMCLo;
2875 MCInstBuilder(AArch64::ADRP)
2876 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2880 if (IsELFSignedGOT) {
2881 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2882 .addReg(AArch64::X17)
2883 .addReg(AArch64::X17)
2887 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2888 .addReg(AArch64::X16)
2889 .addReg(AArch64::X17)
2897 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2899 if (!STI->hasFPAC())
2900 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2901 AArch64PAuth::AuthCheckMethod::XPAC);
2903 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2904 .addReg(AArch64::X16)
2905 .addReg(AArch64::X16)
2909 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2910 .addReg(AArch64::X16)
2911 .addReg(AArch64::X16)
2916 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2917 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2919 emitPAC(
Key, AArch64::X16, DiscReg);
2922void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2924 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2925 const MachineOperand &GAMO =
MI.getOperand(1);
2932 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2933 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2934 .addReg(AuthResultReg)
2935 .addReg(AArch64::X17)
2938 MachineOperand GAHiOp(GAMO);
2939 MachineOperand GALoOp(GAMO);
2943 MCOperand GAMCHi, GAMCLo;
2948 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2950 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2951 .addReg(AArch64::X17)
2952 .addReg(AArch64::X17)
2956 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2957 .addReg(AuthResultReg)
2958 .addReg(AArch64::X17)
2965 UndefWeakSym = createTempSymbol(
"undef_weak");
2967 MCInstBuilder(AArch64::CBZX)
2968 .addReg(AuthResultReg)
2976 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2981 if (!STI->hasFPAC()) {
2982 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2983 AArch64PAuth::AuthCheckMethod::XPAC);
2985 emitMovXReg(DstReg, AuthResultReg);
2990AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2994 if (std::optional<uint16_t> BADisc =
2995 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3002void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3006 switch (
MI->getOpcode()) {
3009 case AArch64::CBBAssertExt:
3013 case AArch64::CBHAssertExt:
3017 case AArch64::CBWPrr:
3020 case AArch64::CBXPrr:
3023 case AArch64::CBWPri:
3027 case AArch64::CBXPri:
3035 bool NeedsRegSwap =
false;
3036 bool NeedsImmDec =
false;
3037 bool NeedsImmInc =
false;
3039#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3041 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3043 ? AArch64::CBB##RegCond##Wrr \
3044 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3045 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3046 : AArch64::CB##RegCond##Xrr))))
3062 NeedsImmDec = IsImm;
3066 NeedsRegSwap = !IsImm;
3073 NeedsRegSwap = !IsImm;
3074 NeedsImmInc = IsImm;
3078 NeedsImmDec = IsImm;
3082 NeedsRegSwap = !IsImm;
3089 NeedsRegSwap = !IsImm;
3090 NeedsImmInc = IsImm;
3098 MCOperand Lhs, Rhs, Trgt;
3099 lowerOperand(
MI->getOperand(1), Lhs);
3100 lowerOperand(
MI->getOperand(2), Rhs);
3101 lowerOperand(
MI->getOperand(3), Trgt);
3105 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3106 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3109 }
else if (NeedsImmDec) {
3113 }
else if (NeedsImmInc) {
3123 "CB immediate operand out-of-bounds");
3126 EmitToStreamer(*OutStreamer, Inst);
3131#include "AArch64GenMCPseudoLowering.inc"
3133void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3140void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3141 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3146 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3151 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3152 EmitToStreamer(*OutStreamer, OutInst);
3156 if (
MI->getOpcode() == AArch64::ADRP) {
3157 for (
auto &Opd :
MI->operands()) {
3158 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3159 "swift_async_extendedFramePointerFlags") {
3160 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3167 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3169 LOHInstToLabel[
MI] = LOHLabel;
3173 AArch64TargetStreamer *TS =
3176 switch (
MI->getOpcode()) {
3179 "Unhandled tail call instruction");
3181 case AArch64::HINT: {
3186 if (CurrentPatchableFunctionEntrySym &&
3187 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3189 int64_t
Imm =
MI->getOperand(0).getImm();
3190 if ((Imm & 32) && (Imm & 6)) {
3192 MCInstLowering.
Lower(
MI, Inst);
3193 EmitToStreamer(*OutStreamer, Inst);
3194 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3195 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3201 case AArch64::MOVMCSym: {
3202 Register DestReg =
MI->getOperand(0).getReg();
3203 const MachineOperand &MO_Sym =
MI->getOperand(1);
3204 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3205 MCOperand Hi_MCSym, Lo_MCSym;
3218 EmitToStreamer(*OutStreamer, MovZ);
3226 EmitToStreamer(*OutStreamer, MovK);
3229 case AArch64::MOVIv2d_ns:
3237 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3238 MI->getOperand(1).getImm() == 0) {
3240 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3243 EmitToStreamer(*OutStreamer, TmpInst);
3248 case AArch64::DBG_VALUE:
3249 case AArch64::DBG_VALUE_LIST:
3251 SmallString<128> TmpStr;
3252 raw_svector_ostream OS(TmpStr);
3253 PrintDebugValueComment(
MI, OS);
3258 case AArch64::EMITBKEY: {
3260 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3261 ExceptionHandlingType != ExceptionHandling::ARM)
3264 if (getFunctionCFISectionType(*MF) == CFISection::None)
3271 case AArch64::EMITMTETAGGED: {
3273 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3274 ExceptionHandlingType != ExceptionHandling::ARM)
3277 if (getFunctionCFISectionType(*MF) != CFISection::None)
3282 case AArch64::AUTx16x17: {
3284 const Register Scratch = AArch64::X17;
3287 MI->getOperand(1).getImm(),
MI->getOperand(2));
3289 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3290 std::nullopt,
MI->getDeactivationSymbol());
3294 case AArch64::AUTxMxN: {
3296 const Register Scratch =
MI->getOperand(1).getReg();
3299 MI->getOperand(4).getImm(),
MI->getOperand(5));
3301 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3302 std::nullopt,
MI->getDeactivationSymbol());
3306 case AArch64::AUTPAC: {
3308 const Register Scratch = AArch64::X17;
3311 MI->getOperand(1).getImm(),
MI->getOperand(2));
3314 MI->getOperand(4).getImm(),
MI->getOperand(5));
3316 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3317 std::nullopt,
MI->getDeactivationSymbol());
3321 case AArch64::AUTRELLOADPAC: {
3323 const Register Scratch = AArch64::X17;
3326 MI->getOperand(1).getImm(),
MI->getOperand(2));
3329 MI->getOperand(4).getImm(),
MI->getOperand(5));
3331 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3332 MI->getOperand(6).getImm(),
3333 MI->getDeactivationSymbol());
3339 emitPtrauthSign(
MI);
3342 case AArch64::LOADauthptrstatic:
3343 LowerLOADauthptrstatic(*
MI);
3346 case AArch64::LOADgotPAC:
3347 case AArch64::MOVaddrPAC:
3348 LowerMOVaddrPAC(*
MI);
3351 case AArch64::LOADgotAUTH:
3352 LowerLOADgotAUTH(*
MI);
3357 emitPtrauthBranch(
MI);
3363 case AArch64::AUTH_TCRETURN:
3364 case AArch64::AUTH_TCRETURN_BTI: {
3367 const uint64_t Disc =
MI->getOperand(3).getImm();
3369 Register AddrDisc =
MI->getOperand(4).getReg();
3371 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3373 emitPtrauthTailCallHardening(
MI);
3376 if (Callee == AddrDisc)
3383 bool AddrDiscIsImplicitDef =
3384 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3385 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3386 AddrDiscIsImplicitDef);
3387 emitBLRA(
false,
Key, Callee, DiscReg);
3391 case AArch64::TCRETURNri:
3392 case AArch64::TCRETURNrix16x17:
3393 case AArch64::TCRETURNrix17:
3394 case AArch64::TCRETURNrinotx16:
3395 case AArch64::TCRETURNriALL: {
3396 emitPtrauthTailCallHardening(
MI);
3398 recordIfImportCall(
MI);
3402 EmitToStreamer(*OutStreamer, TmpInst);
3405 case AArch64::TCRETURNdi: {
3406 emitPtrauthTailCallHardening(
MI);
3410 recordIfImportCall(
MI);
3414 EmitToStreamer(*OutStreamer, TmpInst);
3417 case AArch64::SpeculationBarrierISBDSBEndBB: {
3422 EmitToStreamer(*OutStreamer, TmpInstDSB);
3426 EmitToStreamer(*OutStreamer, TmpInstISB);
3429 case AArch64::SpeculationBarrierSBEndBB: {
3433 EmitToStreamer(*OutStreamer, TmpInstSB);
3436 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3443 const MachineOperand &MO_Sym =
MI->getOperand(0);
3444 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3445 MCOperand SymTLSDescLo12, SymTLSDesc;
3448 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3455 EmitToStreamer(*OutStreamer, Adrp);
3463 EmitToStreamer(*OutStreamer, Ldr);
3466 Add.setOpcode(AArch64::ADDXri);
3469 Add.addOperand(SymTLSDescLo12);
3471 EmitToStreamer(*OutStreamer,
Add);
3480 EmitToStreamer(*OutStreamer, Blraa);
3484 case AArch64::TLSDESC_CALLSEQ: {
3492 const MachineOperand &MO_Sym =
MI->getOperand(0);
3493 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3494 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3498 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3505 EmitToStreamer(*OutStreamer, Adrp);
3508 if (STI->isTargetILP32()) {
3518 EmitToStreamer(*OutStreamer, Ldr);
3521 if (STI->isTargetILP32()) {
3522 Add.setOpcode(AArch64::ADDWri);
3526 Add.setOpcode(AArch64::ADDXri);
3530 Add.addOperand(SymTLSDescLo12);
3532 EmitToStreamer(*OutStreamer,
Add);
3537 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3539 EmitToStreamer(*OutStreamer, TLSDescCall);
3547 EmitToStreamer(*OutStreamer, Blr);
3552 case AArch64::JumpTableDest32:
3553 case AArch64::JumpTableDest16:
3554 case AArch64::JumpTableDest8:
3555 LowerJumpTableDest(*OutStreamer, *
MI);
3558 case AArch64::BR_JumpTable:
3559 LowerHardenedBRJumpTable(*
MI);
3562 case AArch64::FMOVH0:
3563 case AArch64::FMOVS0:
3564 case AArch64::FMOVD0:
3568 case AArch64::MOPSMemoryCopyPseudo:
3569 case AArch64::MOPSMemoryMovePseudo:
3570 case AArch64::MOPSMemorySetPseudo:
3571 case AArch64::MOPSMemorySetTaggingPseudo:
3572 LowerMOPS(*OutStreamer, *
MI);
3575 case TargetOpcode::STACKMAP:
3576 return LowerSTACKMAP(*OutStreamer,
SM, *
MI);
3578 case TargetOpcode::PATCHPOINT:
3579 return LowerPATCHPOINT(*OutStreamer,
SM, *
MI);
3581 case TargetOpcode::STATEPOINT:
3582 return LowerSTATEPOINT(*OutStreamer,
SM, *
MI);
3584 case TargetOpcode::FAULTING_OP:
3585 return LowerFAULTING_OP(*
MI);
3587 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3588 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3591 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3592 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3595 case TargetOpcode::PATCHABLE_TAIL_CALL:
3596 LowerPATCHABLE_TAIL_CALL(*
MI);
3598 case TargetOpcode::PATCHABLE_EVENT_CALL:
3599 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3600 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3601 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3603 case AArch64::KCFI_CHECK:
3604 LowerKCFI_CHECK(*
MI);
3607 case AArch64::HWASAN_CHECK_MEMACCESS:
3608 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3609 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3610 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3611 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3614 case AArch64::SEH_StackAlloc:
3618 case AArch64::SEH_SaveFPLR:
3622 case AArch64::SEH_SaveFPLR_X:
3623 assert(
MI->getOperand(0).getImm() < 0 &&
3624 "Pre increment SEH opcode must have a negative offset");
3628 case AArch64::SEH_SaveReg:
3630 MI->getOperand(1).getImm());
3633 case AArch64::SEH_SaveReg_X:
3634 assert(
MI->getOperand(1).getImm() < 0 &&
3635 "Pre increment SEH opcode must have a negative offset");
3637 -
MI->getOperand(1).getImm());
3640 case AArch64::SEH_SaveRegP:
3641 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3642 MI->getOperand(0).getImm() <= 28) {
3643 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3644 "Register paired with LR must be odd");
3646 MI->getOperand(2).getImm());
3649 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3650 "Non-consecutive registers not allowed for save_regp");
3652 MI->getOperand(2).getImm());
3655 case AArch64::SEH_SaveRegP_X:
3656 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3657 "Non-consecutive registers not allowed for save_regp_x");
3658 assert(
MI->getOperand(2).getImm() < 0 &&
3659 "Pre increment SEH opcode must have a negative offset");
3661 -
MI->getOperand(2).getImm());
3664 case AArch64::SEH_SaveFReg:
3666 MI->getOperand(1).getImm());
3669 case AArch64::SEH_SaveFReg_X:
3670 assert(
MI->getOperand(1).getImm() < 0 &&
3671 "Pre increment SEH opcode must have a negative offset");
3673 -
MI->getOperand(1).getImm());
3676 case AArch64::SEH_SaveFRegP:
3677 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3678 "Non-consecutive registers not allowed for save_regp");
3680 MI->getOperand(2).getImm());
3683 case AArch64::SEH_SaveFRegP_X:
3684 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3685 "Non-consecutive registers not allowed for save_regp_x");
3686 assert(
MI->getOperand(2).getImm() < 0 &&
3687 "Pre increment SEH opcode must have a negative offset");
3689 -
MI->getOperand(2).getImm());
3692 case AArch64::SEH_SetFP:
3696 case AArch64::SEH_AddFP:
3700 case AArch64::SEH_Nop:
3704 case AArch64::SEH_PrologEnd:
3708 case AArch64::SEH_EpilogStart:
3712 case AArch64::SEH_EpilogEnd:
3716 case AArch64::SEH_PACSignLR:
3720 case AArch64::SEH_SaveAnyRegI:
3721 assert(
MI->getOperand(1).getImm() <= 1008 &&
3722 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3724 MI->getOperand(1).getImm());
3727 case AArch64::SEH_SaveAnyRegIP:
3728 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3729 "Non-consecutive registers not allowed for save_any_reg");
3730 assert(
MI->getOperand(2).getImm() <= 1008 &&
3731 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3733 MI->getOperand(2).getImm());
3736 case AArch64::SEH_SaveAnyRegQP:
3737 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3738 "Non-consecutive registers not allowed for save_any_reg");
3739 assert(
MI->getOperand(2).getImm() >= 0 &&
3740 "SaveAnyRegQP SEH opcode offset must be non-negative");
3741 assert(
MI->getOperand(2).getImm() <= 1008 &&
3742 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3744 MI->getOperand(2).getImm());
3747 case AArch64::SEH_SaveAnyRegQPX:
3748 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3749 "Non-consecutive registers not allowed for save_any_reg");
3750 assert(
MI->getOperand(2).getImm() < 0 &&
3751 "SaveAnyRegQPX SEH opcode offset must be negative");
3752 assert(
MI->getOperand(2).getImm() >= -1008 &&
3753 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3755 -
MI->getOperand(2).getImm());
3758 case AArch64::SEH_AllocZ:
3759 assert(
MI->getOperand(0).getImm() >= 0 &&
3760 "AllocZ SEH opcode offset must be non-negative");
3761 assert(
MI->getOperand(0).getImm() <= 255 &&
3762 "AllocZ SEH opcode offset must fit into 8 bits");
3766 case AArch64::SEH_SaveZReg:
3767 assert(
MI->getOperand(1).getImm() >= 0 &&
3768 "SaveZReg SEH opcode offset must be non-negative");
3769 assert(
MI->getOperand(1).getImm() <= 255 &&
3770 "SaveZReg SEH opcode offset must fit into 8 bits");
3772 MI->getOperand(1).getImm());
3775 case AArch64::SEH_SavePReg:
3776 assert(
MI->getOperand(1).getImm() >= 0 &&
3777 "SavePReg SEH opcode offset must be non-negative");
3778 assert(
MI->getOperand(1).getImm() <= 255 &&
3779 "SavePReg SEH opcode offset must fit into 8 bits");
3781 MI->getOperand(1).getImm());
3786 recordIfImportCall(
MI);
3788 MCInstLowering.
Lower(
MI, TmpInst);
3789 EmitToStreamer(*OutStreamer, TmpInst);
3792 case AArch64::CBWPri:
3793 case AArch64::CBXPri:
3794 case AArch64::CBBAssertExt:
3795 case AArch64::CBHAssertExt:
3796 case AArch64::CBWPrr:
3797 case AArch64::CBXPrr:
3798 emitCBPseudoExpansion(
MI);
3802 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3807 MCInstLowering.
Lower(
MI, TmpInst);
3808 EmitToStreamer(*OutStreamer, TmpInst);
3811void AArch64AsmPrinter::recordIfImportCall(
3812 const llvm::MachineInstr *BranchInst) {
3813 if (!EnableImportCallOptimization)
3817 if (GV && GV->hasDLLImportStorageClass()) {
3818 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3823 .push_back({CallSiteSymbol, CalledSymbol});
3827void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3828 MCSymbol *LazyPointer) {
3845 EmitToStreamer(Adrp);
3853 MCOperand SymPageOff;
3860 EmitToStreamer(Ldr);
3863 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3864 .addReg(AArch64::X16)
3865 .addReg(AArch64::X16)
3868 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3870 .addReg(AArch64::X16));
3873void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3874 const GlobalIFunc &GI,
3875 MCSymbol *LazyPointer) {
3907 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3908 .addReg(AArch64::SP)
3909 .addReg(AArch64::FP)
3910 .addReg(AArch64::LR)
3911 .addReg(AArch64::SP)
3914 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3915 .addReg(AArch64::FP)
3916 .addReg(AArch64::SP)
3920 for (
int I = 0;
I != 4; ++
I)
3921 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3922 .addReg(AArch64::SP)
3923 .addReg(AArch64::X1 + 2 *
I)
3924 .addReg(AArch64::X0 + 2 *
I)
3925 .addReg(AArch64::SP)
3928 for (
int I = 0;
I != 4; ++
I)
3929 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3930 .addReg(AArch64::SP)
3931 .addReg(AArch64::D1 + 2 *
I)
3932 .addReg(AArch64::D0 + 2 *
I)
3933 .addReg(AArch64::SP)
3937 MCInstBuilder(AArch64::BL)
3950 EmitToStreamer(Adrp);
3958 MCOperand SymPageOff;
3965 EmitToStreamer(Ldr);
3968 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3969 .addReg(AArch64::X0)
3970 .addReg(AArch64::X16)
3973 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3974 .addReg(AArch64::X16)
3975 .addReg(AArch64::X0)
3979 for (
int I = 3;
I != -1; --
I)
3980 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3981 .addReg(AArch64::SP)
3982 .addReg(AArch64::D1 + 2 *
I)
3983 .addReg(AArch64::D0 + 2 *
I)
3984 .addReg(AArch64::SP)
3987 for (
int I = 3;
I != -1; --
I)
3988 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3989 .addReg(AArch64::SP)
3990 .addReg(AArch64::X1 + 2 *
I)
3991 .addReg(AArch64::X0 + 2 *
I)
3992 .addReg(AArch64::SP)
3995 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3996 .addReg(AArch64::SP)
3997 .addReg(AArch64::FP)
3998 .addReg(AArch64::LR)
3999 .addReg(AArch64::SP)
4002 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4004 .addReg(AArch64::X16));
4007const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4008 const Constant *BaseCV,
4018char AArch64AsmPrinter::ID = 0;
4021 "AArch64 Assembly Printer",
false,
false)
4025LLVMInitializeAArch64AsmPrinter() {
static cl::opt< PtrauthCheckMode > PtrauthAuthChecks("aarch64-ptrauth-auth-checks", cl::Hidden, cl::values(clEnumValN(Unchecked, "none", "don't test for failure"), clEnumValN(Poison, "poison", "poison on failure"), clEnumValN(Trap, "trap", "trap on failure")), cl::desc("Check pointer authentication auth/resign failures"), cl::init(Default))
#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond)
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
static bool targetSupportsIRelativeRelocation(const Triple &TT)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_EXTERNAL_VISIBILITY
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr unsigned SM(unsigned Version)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static 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,...