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);
2706 const MCExpr *DSExpr =
nullptr;
2718 "' out of range [0, " +
2726 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2728 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2733 "' out of range [0, 0xFFFF]");
2739 "expressions on this target");
2746void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2747 unsigned DstReg =
MI.getOperand(0).getReg();
2748 const MachineOperand &GAOp =
MI.getOperand(1);
2749 const uint64_t KeyC =
MI.getOperand(2).getImm();
2751 "key is out of range [0, AArch64PACKey::LAST]");
2753 const uint64_t Disc =
MI.getOperand(3).getImm();
2755 "constant discriminator is out of range [0, 0xffff]");
2764 if (TM.getTargetTriple().isOSBinFormatELF()) {
2766 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2769 "non-zero offset for $auth_ptr$ stub slots is not supported");
2771 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2773 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2774 "LOADauthptrstatic is implemented only for MachO/ELF");
2776 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2777 getObjFileLowering());
2780 "non-zero offset for $auth_ptr$ stub slots is not supported");
2782 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2785 MachineOperand StubMOHi =
2789 MCOperand StubMCHi, StubMCLo;
2796 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2798 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2804void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2805 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2806 const bool IsELFSignedGOT =
MI.getParent()
2808 ->getInfo<AArch64FunctionInfo>()
2809 ->hasELFSignedGOT();
2810 MachineOperand GAOp =
MI.getOperand(0);
2811 const uint64_t KeyC =
MI.getOperand(1).getImm();
2813 "key is out of range [0, AArch64PACKey::LAST]");
2815 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2816 const uint64_t Disc =
MI.getOperand(3).getImm();
2863 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2864 MCOperand GAMCHi, GAMCLo;
2877 MCInstBuilder(AArch64::ADRP)
2878 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2882 if (IsELFSignedGOT) {
2883 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2884 .addReg(AArch64::X17)
2885 .addReg(AArch64::X17)
2889 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2890 .addReg(AArch64::X16)
2891 .addReg(AArch64::X17)
2899 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2901 if (!STI->hasFPAC())
2902 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2903 AArch64PAuth::AuthCheckMethod::XPAC);
2905 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2906 .addReg(AArch64::X16)
2907 .addReg(AArch64::X16)
2911 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2912 .addReg(AArch64::X16)
2913 .addReg(AArch64::X16)
2918 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2919 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2921 emitPAC(
Key, AArch64::X16, DiscReg);
2924void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2926 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2927 const MachineOperand &GAMO =
MI.getOperand(1);
2934 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2935 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2936 .addReg(AuthResultReg)
2937 .addReg(AArch64::X17)
2940 MachineOperand GAHiOp(GAMO);
2941 MachineOperand GALoOp(GAMO);
2945 MCOperand GAMCHi, GAMCLo;
2950 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2952 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2953 .addReg(AArch64::X17)
2954 .addReg(AArch64::X17)
2958 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2959 .addReg(AuthResultReg)
2960 .addReg(AArch64::X17)
2967 UndefWeakSym = createTempSymbol(
"undef_weak");
2969 MCInstBuilder(AArch64::CBZX)
2970 .addReg(AuthResultReg)
2978 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2983 if (!STI->hasFPAC()) {
2984 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2985 AArch64PAuth::AuthCheckMethod::XPAC);
2987 emitMovXReg(DstReg, AuthResultReg);
2992AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2996 if (std::optional<uint16_t> BADisc =
2997 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3004void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3008 switch (
MI->getOpcode()) {
3011 case AArch64::CBBAssertExt:
3015 case AArch64::CBHAssertExt:
3019 case AArch64::CBWPrr:
3022 case AArch64::CBXPrr:
3025 case AArch64::CBWPri:
3029 case AArch64::CBXPri:
3037 bool NeedsRegSwap =
false;
3038 bool NeedsImmDec =
false;
3039 bool NeedsImmInc =
false;
3041#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3043 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3045 ? AArch64::CBB##RegCond##Wrr \
3046 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3047 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3048 : AArch64::CB##RegCond##Xrr))))
3064 NeedsImmDec = IsImm;
3068 NeedsRegSwap = !IsImm;
3075 NeedsRegSwap = !IsImm;
3076 NeedsImmInc = IsImm;
3080 NeedsImmDec = IsImm;
3084 NeedsRegSwap = !IsImm;
3091 NeedsRegSwap = !IsImm;
3092 NeedsImmInc = IsImm;
3100 MCOperand Lhs, Rhs, Trgt;
3101 lowerOperand(
MI->getOperand(1), Lhs);
3102 lowerOperand(
MI->getOperand(2), Rhs);
3103 lowerOperand(
MI->getOperand(3), Trgt);
3107 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3108 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3111 }
else if (NeedsImmDec) {
3115 }
else if (NeedsImmInc) {
3125 "CB immediate operand out-of-bounds");
3128 EmitToStreamer(*OutStreamer, Inst);
3133#include "AArch64GenMCPseudoLowering.inc"
3135void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3142void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3143 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3148 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3153 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3154 EmitToStreamer(*OutStreamer, OutInst);
3158 if (
MI->getOpcode() == AArch64::ADRP) {
3159 for (
auto &Opd :
MI->operands()) {
3160 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3161 "swift_async_extendedFramePointerFlags") {
3162 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3169 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3171 LOHInstToLabel[
MI] = LOHLabel;
3175 AArch64TargetStreamer *TS =
3178 switch (
MI->getOpcode()) {
3181 "Unhandled tail call instruction");
3183 case AArch64::HINT: {
3188 if (CurrentPatchableFunctionEntrySym &&
3189 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3191 int64_t
Imm =
MI->getOperand(0).getImm();
3192 if ((Imm & 32) && (Imm & 6)) {
3194 MCInstLowering.
Lower(
MI, Inst);
3195 EmitToStreamer(*OutStreamer, Inst);
3196 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3197 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3203 case AArch64::MOVMCSym: {
3204 Register DestReg =
MI->getOperand(0).getReg();
3205 const MachineOperand &MO_Sym =
MI->getOperand(1);
3206 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3207 MCOperand Hi_MCSym, Lo_MCSym;
3220 EmitToStreamer(*OutStreamer, MovZ);
3228 EmitToStreamer(*OutStreamer, MovK);
3231 case AArch64::MOVIv2d_ns:
3239 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3240 MI->getOperand(1).getImm() == 0) {
3242 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3245 EmitToStreamer(*OutStreamer, TmpInst);
3250 case AArch64::DBG_VALUE:
3251 case AArch64::DBG_VALUE_LIST:
3253 SmallString<128> TmpStr;
3254 raw_svector_ostream OS(TmpStr);
3255 PrintDebugValueComment(
MI, OS);
3260 case AArch64::EMITBKEY: {
3262 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3263 ExceptionHandlingType != ExceptionHandling::ARM)
3266 if (getFunctionCFISectionType(*MF) == CFISection::None)
3273 case AArch64::EMITMTETAGGED: {
3275 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3276 ExceptionHandlingType != ExceptionHandling::ARM)
3279 if (getFunctionCFISectionType(*MF) != CFISection::None)
3284 case AArch64::AUTx16x17: {
3286 const Register Scratch = AArch64::X17;
3289 MI->getOperand(1).getImm(),
MI->getOperand(2));
3291 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3292 std::nullopt,
MI->getDeactivationSymbol());
3296 case AArch64::AUTxMxN: {
3298 const Register Scratch =
MI->getOperand(1).getReg();
3301 MI->getOperand(4).getImm(),
MI->getOperand(5));
3303 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3304 std::nullopt,
MI->getDeactivationSymbol());
3308 case AArch64::AUTPAC: {
3310 const Register Scratch = AArch64::X17;
3313 MI->getOperand(1).getImm(),
MI->getOperand(2));
3316 MI->getOperand(4).getImm(),
MI->getOperand(5));
3318 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3319 std::nullopt,
MI->getDeactivationSymbol());
3323 case AArch64::AUTRELLOADPAC: {
3325 const Register Scratch = AArch64::X17;
3328 MI->getOperand(1).getImm(),
MI->getOperand(2));
3331 MI->getOperand(4).getImm(),
MI->getOperand(5));
3333 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3334 MI->getOperand(6).getImm(),
3335 MI->getDeactivationSymbol());
3341 emitPtrauthSign(
MI);
3344 case AArch64::LOADauthptrstatic:
3345 LowerLOADauthptrstatic(*
MI);
3348 case AArch64::LOADgotPAC:
3349 case AArch64::MOVaddrPAC:
3350 LowerMOVaddrPAC(*
MI);
3353 case AArch64::LOADgotAUTH:
3354 LowerLOADgotAUTH(*
MI);
3359 emitPtrauthBranch(
MI);
3365 case AArch64::AUTH_TCRETURN:
3366 case AArch64::AUTH_TCRETURN_BTI: {
3369 const uint64_t Disc =
MI->getOperand(3).getImm();
3371 Register AddrDisc =
MI->getOperand(4).getReg();
3373 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3375 emitPtrauthTailCallHardening(
MI);
3378 if (Callee == AddrDisc)
3385 bool AddrDiscIsImplicitDef =
3386 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3387 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3388 AddrDiscIsImplicitDef);
3389 emitBLRA(
false,
Key, Callee, DiscReg);
3393 case AArch64::TCRETURNri:
3394 case AArch64::TCRETURNrix16x17:
3395 case AArch64::TCRETURNrix17:
3396 case AArch64::TCRETURNrinotx16:
3397 case AArch64::TCRETURNriALL: {
3398 emitPtrauthTailCallHardening(
MI);
3400 recordIfImportCall(
MI);
3404 EmitToStreamer(*OutStreamer, TmpInst);
3407 case AArch64::TCRETURNdi: {
3408 emitPtrauthTailCallHardening(
MI);
3412 recordIfImportCall(
MI);
3416 EmitToStreamer(*OutStreamer, TmpInst);
3419 case AArch64::SpeculationBarrierISBDSBEndBB: {
3424 EmitToStreamer(*OutStreamer, TmpInstDSB);
3428 EmitToStreamer(*OutStreamer, TmpInstISB);
3431 case AArch64::SpeculationBarrierSBEndBB: {
3435 EmitToStreamer(*OutStreamer, TmpInstSB);
3438 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3445 const MachineOperand &MO_Sym =
MI->getOperand(0);
3446 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3447 MCOperand SymTLSDescLo12, SymTLSDesc;
3450 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3457 EmitToStreamer(*OutStreamer, Adrp);
3465 EmitToStreamer(*OutStreamer, Ldr);
3468 Add.setOpcode(AArch64::ADDXri);
3471 Add.addOperand(SymTLSDescLo12);
3473 EmitToStreamer(*OutStreamer,
Add);
3482 EmitToStreamer(*OutStreamer, Blraa);
3486 case AArch64::TLSDESC_CALLSEQ: {
3494 const MachineOperand &MO_Sym =
MI->getOperand(0);
3495 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3496 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3500 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3507 EmitToStreamer(*OutStreamer, Adrp);
3510 if (STI->isTargetILP32()) {
3520 EmitToStreamer(*OutStreamer, Ldr);
3523 if (STI->isTargetILP32()) {
3524 Add.setOpcode(AArch64::ADDWri);
3528 Add.setOpcode(AArch64::ADDXri);
3532 Add.addOperand(SymTLSDescLo12);
3534 EmitToStreamer(*OutStreamer,
Add);
3539 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3541 EmitToStreamer(*OutStreamer, TLSDescCall);
3549 EmitToStreamer(*OutStreamer, Blr);
3554 case AArch64::JumpTableDest32:
3555 case AArch64::JumpTableDest16:
3556 case AArch64::JumpTableDest8:
3557 LowerJumpTableDest(*OutStreamer, *
MI);
3560 case AArch64::BR_JumpTable:
3561 LowerHardenedBRJumpTable(*
MI);
3564 case AArch64::FMOVH0:
3565 case AArch64::FMOVS0:
3566 case AArch64::FMOVD0:
3570 case AArch64::MOPSMemoryCopyPseudo:
3571 case AArch64::MOPSMemoryMovePseudo:
3572 case AArch64::MOPSMemorySetPseudo:
3573 case AArch64::MOPSMemorySetTaggingPseudo:
3574 LowerMOPS(*OutStreamer, *
MI);
3577 case TargetOpcode::STACKMAP:
3578 return LowerSTACKMAP(*OutStreamer,
SM, *
MI);
3580 case TargetOpcode::PATCHPOINT:
3581 return LowerPATCHPOINT(*OutStreamer,
SM, *
MI);
3583 case TargetOpcode::STATEPOINT:
3584 return LowerSTATEPOINT(*OutStreamer,
SM, *
MI);
3586 case TargetOpcode::FAULTING_OP:
3587 return LowerFAULTING_OP(*
MI);
3589 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3590 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3593 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3594 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3597 case TargetOpcode::PATCHABLE_TAIL_CALL:
3598 LowerPATCHABLE_TAIL_CALL(*
MI);
3600 case TargetOpcode::PATCHABLE_EVENT_CALL:
3601 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3602 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3603 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3605 case AArch64::KCFI_CHECK:
3606 LowerKCFI_CHECK(*
MI);
3609 case AArch64::HWASAN_CHECK_MEMACCESS:
3610 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3611 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3612 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3613 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3616 case AArch64::SEH_StackAlloc:
3620 case AArch64::SEH_SaveFPLR:
3624 case AArch64::SEH_SaveFPLR_X:
3625 assert(
MI->getOperand(0).getImm() < 0 &&
3626 "Pre increment SEH opcode must have a negative offset");
3630 case AArch64::SEH_SaveReg:
3632 MI->getOperand(1).getImm());
3635 case AArch64::SEH_SaveReg_X:
3636 assert(
MI->getOperand(1).getImm() < 0 &&
3637 "Pre increment SEH opcode must have a negative offset");
3639 -
MI->getOperand(1).getImm());
3642 case AArch64::SEH_SaveRegP:
3643 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3644 MI->getOperand(0).getImm() <= 28) {
3645 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3646 "Register paired with LR must be odd");
3648 MI->getOperand(2).getImm());
3651 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3652 "Non-consecutive registers not allowed for save_regp");
3654 MI->getOperand(2).getImm());
3657 case AArch64::SEH_SaveRegP_X:
3658 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3659 "Non-consecutive registers not allowed for save_regp_x");
3660 assert(
MI->getOperand(2).getImm() < 0 &&
3661 "Pre increment SEH opcode must have a negative offset");
3663 -
MI->getOperand(2).getImm());
3666 case AArch64::SEH_SaveFReg:
3668 MI->getOperand(1).getImm());
3671 case AArch64::SEH_SaveFReg_X:
3672 assert(
MI->getOperand(1).getImm() < 0 &&
3673 "Pre increment SEH opcode must have a negative offset");
3675 -
MI->getOperand(1).getImm());
3678 case AArch64::SEH_SaveFRegP:
3679 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3680 "Non-consecutive registers not allowed for save_regp");
3682 MI->getOperand(2).getImm());
3685 case AArch64::SEH_SaveFRegP_X:
3686 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3687 "Non-consecutive registers not allowed for save_regp_x");
3688 assert(
MI->getOperand(2).getImm() < 0 &&
3689 "Pre increment SEH opcode must have a negative offset");
3691 -
MI->getOperand(2).getImm());
3694 case AArch64::SEH_SetFP:
3698 case AArch64::SEH_AddFP:
3702 case AArch64::SEH_Nop:
3706 case AArch64::SEH_PrologEnd:
3710 case AArch64::SEH_EpilogStart:
3714 case AArch64::SEH_EpilogEnd:
3718 case AArch64::SEH_PACSignLR:
3722 case AArch64::SEH_SaveAnyRegI:
3723 assert(
MI->getOperand(1).getImm() <= 1008 &&
3724 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3726 MI->getOperand(1).getImm());
3729 case AArch64::SEH_SaveAnyRegIP:
3730 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3731 "Non-consecutive registers not allowed for save_any_reg");
3732 assert(
MI->getOperand(2).getImm() <= 1008 &&
3733 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3735 MI->getOperand(2).getImm());
3738 case AArch64::SEH_SaveAnyRegQP:
3739 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3740 "Non-consecutive registers not allowed for save_any_reg");
3741 assert(
MI->getOperand(2).getImm() >= 0 &&
3742 "SaveAnyRegQP SEH opcode offset must be non-negative");
3743 assert(
MI->getOperand(2).getImm() <= 1008 &&
3744 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3746 MI->getOperand(2).getImm());
3749 case AArch64::SEH_SaveAnyRegQPX:
3750 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3751 "Non-consecutive registers not allowed for save_any_reg");
3752 assert(
MI->getOperand(2).getImm() < 0 &&
3753 "SaveAnyRegQPX SEH opcode offset must be negative");
3754 assert(
MI->getOperand(2).getImm() >= -1008 &&
3755 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3757 -
MI->getOperand(2).getImm());
3760 case AArch64::SEH_AllocZ:
3761 assert(
MI->getOperand(0).getImm() >= 0 &&
3762 "AllocZ SEH opcode offset must be non-negative");
3763 assert(
MI->getOperand(0).getImm() <= 255 &&
3764 "AllocZ SEH opcode offset must fit into 8 bits");
3768 case AArch64::SEH_SaveZReg:
3769 assert(
MI->getOperand(1).getImm() >= 0 &&
3770 "SaveZReg SEH opcode offset must be non-negative");
3771 assert(
MI->getOperand(1).getImm() <= 255 &&
3772 "SaveZReg SEH opcode offset must fit into 8 bits");
3774 MI->getOperand(1).getImm());
3777 case AArch64::SEH_SavePReg:
3778 assert(
MI->getOperand(1).getImm() >= 0 &&
3779 "SavePReg SEH opcode offset must be non-negative");
3780 assert(
MI->getOperand(1).getImm() <= 255 &&
3781 "SavePReg SEH opcode offset must fit into 8 bits");
3783 MI->getOperand(1).getImm());
3788 recordIfImportCall(
MI);
3790 MCInstLowering.
Lower(
MI, TmpInst);
3791 EmitToStreamer(*OutStreamer, TmpInst);
3794 case AArch64::CBWPri:
3795 case AArch64::CBXPri:
3796 case AArch64::CBBAssertExt:
3797 case AArch64::CBHAssertExt:
3798 case AArch64::CBWPrr:
3799 case AArch64::CBXPrr:
3800 emitCBPseudoExpansion(
MI);
3804 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3809 MCInstLowering.
Lower(
MI, TmpInst);
3810 EmitToStreamer(*OutStreamer, TmpInst);
3813void AArch64AsmPrinter::recordIfImportCall(
3814 const llvm::MachineInstr *BranchInst) {
3815 if (!EnableImportCallOptimization)
3819 if (GV && GV->hasDLLImportStorageClass()) {
3820 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3825 .push_back({CallSiteSymbol, CalledSymbol});
3829void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3830 MCSymbol *LazyPointer) {
3847 EmitToStreamer(Adrp);
3855 MCOperand SymPageOff;
3862 EmitToStreamer(Ldr);
3865 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3866 .addReg(AArch64::X16)
3867 .addReg(AArch64::X16)
3870 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3872 .addReg(AArch64::X16));
3875void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3876 const GlobalIFunc &GI,
3877 MCSymbol *LazyPointer) {
3909 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3910 .addReg(AArch64::SP)
3911 .addReg(AArch64::FP)
3912 .addReg(AArch64::LR)
3913 .addReg(AArch64::SP)
3916 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3917 .addReg(AArch64::FP)
3918 .addReg(AArch64::SP)
3922 for (
int I = 0;
I != 4; ++
I)
3923 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3924 .addReg(AArch64::SP)
3925 .addReg(AArch64::X1 + 2 *
I)
3926 .addReg(AArch64::X0 + 2 *
I)
3927 .addReg(AArch64::SP)
3930 for (
int I = 0;
I != 4; ++
I)
3931 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3932 .addReg(AArch64::SP)
3933 .addReg(AArch64::D1 + 2 *
I)
3934 .addReg(AArch64::D0 + 2 *
I)
3935 .addReg(AArch64::SP)
3939 MCInstBuilder(AArch64::BL)
3952 EmitToStreamer(Adrp);
3960 MCOperand SymPageOff;
3967 EmitToStreamer(Ldr);
3970 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3971 .addReg(AArch64::X0)
3972 .addReg(AArch64::X16)
3975 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3976 .addReg(AArch64::X16)
3977 .addReg(AArch64::X0)
3981 for (
int I = 3;
I != -1; --
I)
3982 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3983 .addReg(AArch64::SP)
3984 .addReg(AArch64::D1 + 2 *
I)
3985 .addReg(AArch64::D0 + 2 *
I)
3986 .addReg(AArch64::SP)
3989 for (
int I = 3;
I != -1; --
I)
3990 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3991 .addReg(AArch64::SP)
3992 .addReg(AArch64::X1 + 2 *
I)
3993 .addReg(AArch64::X0 + 2 *
I)
3994 .addReg(AArch64::SP)
3997 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3998 .addReg(AArch64::SP)
3999 .addReg(AArch64::FP)
4000 .addReg(AArch64::LR)
4001 .addReg(AArch64::SP)
4004 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4006 .addReg(AArch64::X16));
4009const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4010 const Constant *BaseCV,
4020char AArch64AsmPrinter::ID = 0;
4023 "AArch64 Assembly Printer",
false,
false)
4027LLVMInitializeAArch64AsmPrinter() {
static cl::opt< PtrauthCheckMode > PtrauthAuthChecks("aarch64-ptrauth-auth-checks", cl::Hidden, cl::values(clEnumValN(Unchecked, "none", "don't test for failure"), clEnumValN(Poison, "poison", "poison on failure"), clEnumValN(Trap, "trap", "trap on failure")), cl::desc("Check pointer authentication auth/resign failures"), cl::init(Default))
#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond)
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
static bool targetSupportsIRelativeRelocation(const Triple &TT)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_EXTERNAL_VISIBILITY
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr unsigned SM(unsigned Version)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool printAsmMRegister(const X86AsmPrinter &P, const MachineOperand &MO, char Mode, raw_ostream &O)
static const AArch64AuthMCExpr * create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, bool HasAddressDiversity, MCContext &Ctx, SMLoc Loc=SMLoc())
const SetOfInstructions & getLOHRelated() const
unsigned getJumpTableEntrySize(int Idx) const
MCSymbol * getJumpTableEntryPCRelSymbol(int Idx) const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
std::optional< std::string > getOutliningStyle() const
const MILOHContainer & getLOHContainer() const
void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym)
bool shouldSignWithBKey() const
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MCSymbol * GetGlobalValueSymbol(const GlobalValue *GV, unsigned TargetFlags) const
void Lower(const MachineInstr *MI, MCInst &OutMI) const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
virtual void emitARM64WinCFISaveRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset)
virtual void emitAttributesSubsection(StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, AArch64BuildAttributes::SubsectionType ParameterType)
Build attributes implementation.
virtual void emitARM64WinCFISavePReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPACSignLR()
virtual void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFIAllocStack(unsigned Size)
virtual void emitARM64WinCFISaveFPLRX(int Offset)
virtual void emitARM64WinCFIAllocZ(int Offset)
virtual void emitDirectiveVariantPCS(MCSymbol *Symbol)
Callback used to implement the .variant_pcs directive.
virtual void emitARM64WinCFIAddFP(unsigned Size)
virtual void emitARM64WinCFISaveFPLR(int Offset)
virtual void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISetFP()
virtual void emitARM64WinCFIEpilogEnd()
virtual void emitARM64WinCFISaveZReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPrologEnd()
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFINop()
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
virtual void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, std::string String)
virtual void emitARM64WinCFIEpilogStart()
virtual void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset)
void setPreservesAll()
Set by analyses that do not transform their input at all.
const T & front() const
front - Get the first element.
bool empty() const
empty - Check if the array is empty.
This class is intended to be used as a driving class for all asm writers.
virtual void emitGlobalAlias(const Module &M, const GlobalAlias &GA)
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
virtual const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
virtual void emitXXStructor(const DataLayout &DL, const Constant *CV)
Targets can override this to change how global constants that are part of a C++ static/global constru...
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
virtual const MCExpr * lowerBlockAddressConstant(const BlockAddress &BA)
Lower the specified BlockAddress to an MCExpr.
Function * getFunction() const
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
@ AddrDiscriminator_CtorsDtors
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
ConstantInt * getKey() const
The Key ID, an i32 constant.
Constant * getDeactivationSymbol() const
bool hasAddressDiscriminator() const
Whether there is any non-null address discriminator.
ConstantInt * getDiscriminator() const
The integer discriminator, an i64 constant, or 0.
void recordFaultingOp(FaultKind FaultTy, const MCSymbol *FaultingLabel, const MCSymbol *HandlerLabel)
void serializeToFaultMapSection()
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const Constant * getAliasee() const
const Constant * getResolver() const
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
bool hasLocalLinkage() const
bool hasExternalWeakLinkage() const
Type * getValueType() const
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
LLVM_ABI MCSymbol * createLinkerPrivateSymbol(const Twine &Name)
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
MCSection * getDataSection() const
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
static constexpr unsigned NonUniqueID
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
virtual void emitCFIBKeyFrame()
virtual bool popSection()
Restore the current and previous section from the section stack.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc={})
Record a relocation described by the .reloc directive.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCFIMTETaggedFrame()
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
void pushSection()
Save the current and previous section on the section stack.
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
MCSection * getCurrentSectionOnly() const
void emitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ....
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
const MCSymbol * getAddSym() const
int64_t getConstant() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
CalledGlobalInfo tryGetCalledGlobal(const MachineInstr *MI) const
Tries to get the global and target flags for a call site, if the instruction is a call to a global.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
ExprStubListTy getAuthGVStubList()
ExprStubListTy getAuthGVStubList()
unsigned getSubReg() const
static MachineOperand CreateMCSymbol(MCSymbol *Sym, unsigned TargetFlags=0)
const GlobalValue * getGlobal() const
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const BlockAddress * getBlockAddress() const
void setOffset(int64_t Offset)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
int64_t getOffset() const
Return the offset from the symbol in this operand.
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static SectionKind getMetadata()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void push_back(const T &Elt)
constexpr const char * data() const
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)
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Implement std::hash so that hash_code can be used in STL containers.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...