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;
101 bool PtrauthInitFini =
false;
102 bool PtrauthInitFiniAddressDisc =
false;
104 unsigned InstsEmitted;
106 bool EnableImportCallOptimization =
false;
108 SectionToImportedFunctionCalls;
109 unsigned PAuthIFuncNextUniqueID = 1;
114 AArch64AsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
116 MCInstLowering(OutContext, *this), FM(*this) {}
118 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
122 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const {
123 return MCInstLowering.lowerOperand(MO, MCOp);
126 const MCExpr *lowerConstantPtrAuth(
const ConstantPtrAuth &CPA)
override;
128 const MCExpr *lowerBlockAddressConstant(
const BlockAddress &BA)
override;
130 void emitStartOfAsmFile(
Module &M)
override;
131 void emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
132 ArrayRef<unsigned> JumpTableIndices)
override;
135 getCodeViewJumpTableInfo(
int JTI,
const MachineInstr *BranchInstr,
136 const MCSymbol *BranchLabel)
const override;
138 void emitFunctionEntryLabel()
override;
140 void emitXXStructor(
const DataLayout &
DL,
const Constant *CV)
override;
142 void LowerJumpTableDest(MCStreamer &OutStreamer,
const MachineInstr &
MI);
144 void LowerHardenedBRJumpTable(
const MachineInstr &
MI);
146 void LowerMOPS(MCStreamer &OutStreamer,
const MachineInstr &
MI);
148 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &
SM,
149 const MachineInstr &
MI);
150 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
151 const MachineInstr &
MI);
152 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
153 const MachineInstr &
MI);
154 void LowerFAULTING_OP(
const MachineInstr &
MI);
156 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI);
157 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI);
158 void LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI);
159 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
161 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
162 HwasanMemaccessTuple;
163 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
164 void LowerKCFI_CHECK(
const MachineInstr &
MI);
165 void LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI);
166 void emitHwasanMemaccessSymbols(
Module &M);
168 void emitSled(
const MachineInstr &
MI, SledKind Kind);
176 if (STI->isX16X17Safer())
177 return Reg == AArch64::X16 ||
Reg == AArch64::X17;
183 void emitPtrauthBranch(
const MachineInstr *
MI);
185 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
189 const MCSymbol *OnFailure =
nullptr);
192 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
194 struct PtrAuthSchema {
196 const MachineOperand &AddrDiscOp);
203 bool AddrDiscIsKilled;
220 PtrAuthSchema AuthSchema,
221 std::optional<PtrAuthSchema> SignSchema,
222 std::optional<int64_t> Addend,
Value *DS);
227 bool emitDeactivationSymbolRelocation(
Value *DS);
230 void emitPtrauthSign(
const MachineInstr *
MI);
254 bool MayClobberAddrDisc =
false);
257 void LowerLOADauthptrstatic(
const MachineInstr &
MI);
261 void LowerMOVaddrPAC(
const MachineInstr &
MI);
266 void LowerLOADgotAUTH(
const MachineInstr &
MI);
268 void emitAddImm(MCRegister Val, int64_t Addend, MCRegister Tmp);
269 void emitAddress(MCRegister
Reg,
const MCExpr *Expr, MCRegister Tmp,
270 bool DSOLocal,
const MCSubtargetInfo &STI);
272 const MCExpr *emitPAuthRelocationAsIRelative(
274 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr);
278 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
281 void emitAttributes(
unsigned Flags, uint64_t PAuthABIPlatform,
282 uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
285 void emitCBPseudoExpansion(
const MachineInstr *
MI);
287 void EmitToStreamer(MCStreamer &S,
const MCInst &Inst);
288 void EmitToStreamer(
const MCInst &Inst) {
289 EmitToStreamer(*OutStreamer, Inst);
294 void emitFunctionHeaderComment()
override;
296 void getAnalysisUsage(AnalysisUsage &AU)
const override {
301 bool runOnMachineFunction(MachineFunction &MF)
override {
302 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
303 PSI = &PSIW->getPSI();
305 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
306 SDPI = &SDPIW->getStaticDataProfileInfo();
308 AArch64FI = MF.
getInfo<AArch64FunctionInfo>();
311 SetupMachineFunction(MF);
313 if (STI->isTargetCOFF()) {
320 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
321 OutStreamer->emitCOFFSymbolStorageClass(Scl);
322 OutStreamer->emitCOFFSymbolType(
Type);
323 OutStreamer->endCOFFSymbolDef();
337 const Constant *BaseCV =
nullptr,
338 uint64_t
Offset = 0)
override;
341 void printOperand(
const MachineInstr *
MI,
unsigned OpNum, raw_ostream &O);
343 bool printAsmRegInClass(
const MachineOperand &MO,
347 bool PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
348 const char *ExtraCode, raw_ostream &O)
override;
349 bool PrintAsmMemoryOperand(
const MachineInstr *
MI,
unsigned OpNum,
350 const char *ExtraCode, raw_ostream &O)
override;
352 void PrintDebugValueComment(
const MachineInstr *
MI, raw_ostream &OS);
354 void emitFunctionBodyEnd()
override;
355 void emitGlobalAlias(
const Module &M,
const GlobalAlias &GA)
override;
357 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
358 void emitEndOfAsmFile(
Module &M)
override;
360 AArch64FunctionInfo *AArch64FI =
nullptr;
366 void emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift);
367 void emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift);
375 void emitFMov0(
const MachineInstr &
MI);
376 void emitFMov0AsFMov(
const MachineInstr &
MI,
Register DestReg);
378 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
380 MInstToMCSymbol LOHInstToLabel;
382 bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()
const override {
383 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
386 const MCSubtargetInfo *getIFuncMCSubtargetInfo()
const override {
390 void emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
391 MCSymbol *LazyPointer)
override;
392 void emitMachOIFuncStubHelperBody(
Module &M,
const GlobalIFunc &GI,
393 MCSymbol *LazyPointer)
override;
398 void recordIfImportCall(
const MachineInstr *BranchInst);
405 Metadata *Flag = M.getModuleFlag(Name);
410 assert((
Value == 0 ||
Value == 1) &&
"Boolean flag is expected, if present");
414void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
415 const Triple &
TT = TM.getTargetTriple();
417 if (
TT.isOSBinFormatCOFF()) {
418 emitCOFFFeatureSymbol(M);
419 emitCOFFReplaceableFunctionData(M);
421 if (
M.getModuleFlag(
"import-call-optimization"))
422 EnableImportCallOptimization =
true;
427 M,
"ptrauth-init-fini-address-discrimination");
429 if (!
TT.isOSBinFormatELF())
434 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
437 unsigned BAFlags = 0;
438 unsigned GNUFlags = 0;
440 M.getModuleFlag(
"branch-target-enforcement"))) {
441 if (!BTE->isZero()) {
442 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
448 M.getModuleFlag(
"guarded-control-stack"))) {
449 if (!GCS->isZero()) {
450 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
456 M.getModuleFlag(
"sign-return-address"))) {
457 if (!Sign->isZero()) {
458 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
463 uint64_t PAuthABIPlatform = -1;
465 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
466 PAuthABIPlatform = PAP->getZExtValue();
469 uint64_t PAuthABIVersion = -1;
471 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
472 PAuthABIVersion = PAV->getZExtValue();
480 PAuthABIVersion == 0) {
481 PAuthABIPlatform = uint64_t(-1);
482 PAuthABIVersion = uint64_t(-1);
486 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
488 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
491void AArch64AsmPrinter::emitFunctionHeaderComment() {
492 const AArch64FunctionInfo *FI = MF->
getInfo<AArch64FunctionInfo>();
494 if (OutlinerString != std::nullopt)
495 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
498void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
501 if (
F.hasFnAttribute(
"patchable-function-entry")) {
503 if (
F.getFnAttribute(
"patchable-function-entry")
505 .getAsInteger(10, Num))
511 emitSled(
MI, SledKind::FUNCTION_ENTER);
514void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
515 emitSled(
MI, SledKind::FUNCTION_EXIT);
518void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
519 emitSled(
MI, SledKind::TAIL_CALL);
522void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
523 static const int8_t NoopsInSledCount = 7;
544 OutStreamer->emitCodeAlignment(
Align(4), getSubtargetInfo());
545 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
546 OutStreamer->emitLabel(CurSled);
547 auto Target = OutContext.createTempSymbol();
552 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
554 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
555 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::NOP));
557 OutStreamer->emitLabel(Target);
558 recordSled(CurSled,
MI, Kind, 2);
561void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
562 uint64_t PAuthABIPlatform,
563 uint64_t PAuthABIVersion,
564 AArch64TargetStreamer *TS) {
566 PAuthABIPlatform = (uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
567 PAuthABIVersion = (uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
569 if (PAuthABIPlatform || PAuthABIVersion) {
573 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
574 AArch64BuildAttributes::SubsectionType::ULEB128);
578 PAuthABIPlatform,
"");
592 if (BTIValue || PACValue || GCSValue) {
596 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
597 AArch64BuildAttributes::SubsectionType::ULEB128);
625void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
627 auto &
O = *OutStreamer;
628 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
629 O.emitLabel(CurSled);
630 bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
632 OutContext.getOrCreateSymbol(
633 Twine(MachO ?
"_" :
"") +
634 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
637 O.AddComment(
"Begin XRay typed event");
638 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(9));
639 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
645 EmitToStreamer(O, MCInstBuilder(AArch64::STRXui)
649 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
650 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
651 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
652 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
653 EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
657 O.AddComment(
"End XRay typed event");
658 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
665 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
667 O.AddComment(
"Begin XRay custom event");
668 EmitToStreamer(O, MCInstBuilder(AArch64::B).addImm(6));
669 EmitToStreamer(O, MCInstBuilder(AArch64::STPXpre)
675 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
676 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
677 EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
678 O.AddComment(
"End XRay custom event");
679 EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
686 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
690void AArch64AsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
692 assert(std::next(
MI.getIterator())->isCall() &&
693 "KCFI_CHECK not followed by a call instruction");
694 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
695 "KCFI_CHECK call target doesn't match call operand");
699 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
700 if (AddrReg == AArch64::XZR) {
704 emitMovXReg(AddrReg, AArch64::XZR);
710 for (
auto &
Reg : ScratchRegs) {
716 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
717 "Invalid scratch registers for KCFI_CHECK");
722 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
723 "patchable-function-prefix");
726 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
727 .addReg(ScratchRegs[0])
729 .addImm(-(PrefixNops * 4 + 4)));
733 const int64_t
Type =
MI.getOperand(1).getImm();
734 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
735 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
738 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
739 .addReg(AArch64::WZR)
740 .addReg(ScratchRegs[0])
741 .addReg(ScratchRegs[1])
745 EmitToStreamer(*OutStreamer,
746 MCInstBuilder(AArch64::Bcc)
755 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
759 AddrIndex = AddrReg - AArch64::X0;
769 assert(AddrIndex < 31 && TypeIndex < 31);
771 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
772 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(ESR));
773 OutStreamer->emitLabel(
Pass);
776void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
784 if (
Reg == AArch64::XZR)
788 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
790 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
791 uint32_t AccessInfo =
MI.getOperand(1).getImm();
793 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
795 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
796 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
798 MCSymbol *&Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
799 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
802 if (!TM.getTargetTriple().isOSBinFormatELF())
805 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - AArch64::X0) +
"_" +
808 SymName +=
"_fixed_" +
utostr(FixedShadowOffset);
810 SymName +=
"_short_v2";
811 Sym = OutContext.getOrCreateSymbol(SymName);
814 EmitToStreamer(*OutStreamer,
815 MCInstBuilder(AArch64::BL)
819void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
820 if (HwasanMemaccessSymbols.empty())
823 const Triple &
TT = TM.getTargetTriple();
827 auto STI = std::make_unique<AArch64Subtarget>(
828 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
830 this->STI = STI.get();
833 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
835 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
837 const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
839 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
842 for (
auto &
P : HwasanMemaccessSymbols) {
843 unsigned Reg = std::get<0>(
P.first);
844 bool IsShort = std::get<1>(
P.first);
845 uint32_t AccessInfo = std::get<2>(
P.first);
846 bool IsFixedShadow = std::get<3>(
P.first);
847 uint64_t FixedShadowOffset = std::get<4>(
P.first);
848 const MCSymbolRefExpr *HwasanTagMismatchRef =
849 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
852 bool HasMatchAllTag =
854 uint8_t MatchAllTag =
861 OutStreamer->switchSection(OutContext.getELFSection(
867 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
868 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Hidden);
869 OutStreamer->emitLabel(Sym);
871 EmitToStreamer(MCInstBuilder(AArch64::SBFMXri)
872 .addReg(AArch64::X16)
882 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
883 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
884 .addReg(AArch64::W16)
885 .addReg(AArch64::X17)
886 .addReg(AArch64::X16)
890 EmitToStreamer(MCInstBuilder(AArch64::LDRBBroX)
891 .addReg(AArch64::W16)
892 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
893 .addReg(AArch64::X16)
898 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
899 .addReg(AArch64::XZR)
900 .addReg(AArch64::X16)
903 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
904 EmitToStreamer(MCInstBuilder(AArch64::Bcc)
907 HandleMismatchOrPartialSym, OutContext)));
908 MCSymbol *ReturnSym = OutContext.createTempSymbol();
909 OutStreamer->emitLabel(ReturnSym);
910 EmitToStreamer(MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
911 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
913 if (HasMatchAllTag) {
914 EmitToStreamer(MCInstBuilder(AArch64::UBFMXri)
915 .addReg(AArch64::X17)
919 EmitToStreamer(MCInstBuilder(AArch64::SUBSXri)
920 .addReg(AArch64::XZR)
921 .addReg(AArch64::X17)
925 MCInstBuilder(AArch64::Bcc)
931 EmitToStreamer(MCInstBuilder(AArch64::SUBSWri)
932 .addReg(AArch64::WZR)
933 .addReg(AArch64::W16)
936 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
938 MCInstBuilder(AArch64::Bcc)
942 EmitToStreamer(MCInstBuilder(AArch64::ANDXri)
943 .addReg(AArch64::X17)
947 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
948 .addReg(AArch64::X17)
949 .addReg(AArch64::X17)
952 EmitToStreamer(MCInstBuilder(AArch64::SUBSWrs)
953 .addReg(AArch64::WZR)
954 .addReg(AArch64::W16)
955 .addReg(AArch64::W17)
958 MCInstBuilder(AArch64::Bcc)
962 EmitToStreamer(MCInstBuilder(AArch64::ORRXri)
963 .addReg(AArch64::X16)
966 EmitToStreamer(MCInstBuilder(AArch64::LDRBBui)
967 .addReg(AArch64::W16)
968 .addReg(AArch64::X16)
971 MCInstBuilder(AArch64::SUBSXrs)
972 .addReg(AArch64::XZR)
973 .addReg(AArch64::X16)
977 MCInstBuilder(AArch64::Bcc)
981 OutStreamer->emitLabel(HandleMismatchSym);
984 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
990 EmitToStreamer(MCInstBuilder(AArch64::STPXi)
996 if (
Reg != AArch64::X0)
997 emitMovXReg(AArch64::X0,
Reg);
1000 if (CompileKernel) {
1004 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
1009 EmitToStreamer(MCInstBuilder(AArch64::ADRP)
1010 .addReg(AArch64::X16)
1014 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
1015 .addReg(AArch64::X16)
1016 .addReg(AArch64::X16)
1020 EmitToStreamer(MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1023 this->STI =
nullptr;
1028 const MCExpr *StubAuthPtrRef) {
1031 OutStreamer.
emitValue(StubAuthPtrRef, 8);
1034void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
1035 emitHwasanMemaccessSymbols(M);
1037 const Triple &
TT = TM.getTargetTriple();
1038 if (
TT.isOSBinFormatMachO()) {
1040 MachineModuleInfoMachO &MMIMacho =
1041 MMI->getObjFileInfo<MachineModuleInfoMachO>();
1045 if (!Stubs.empty()) {
1047 OutStreamer->switchSection(
1050 emitAlignment(
Align(8));
1052 for (
const auto &Stub : Stubs)
1055 OutStreamer->addBlankLine();
1063 OutStreamer->emitSubsectionsViaSymbols();
1066 if (
TT.isOSBinFormatELF()) {
1068 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
1072 if (!Stubs.empty()) {
1073 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1075 emitAlignment(
Align(8));
1077 for (
const auto &Stub : Stubs)
1080 OutStreamer->addBlankLine();
1091 M.getModuleFlag(
"ptrauth-elf-got"));
1092 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1093 for (
const GlobalValue &GV :
M.global_values())
1095 !GV.getName().starts_with(
"llvm."))
1096 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1105 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1106 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1109 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1110 OutStreamer->emitBytes(StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1121 for (
auto &[Section, CallsToImportedFuncs] :
1122 SectionToImportedFunctionCalls) {
1124 sizeof(uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1125 OutStreamer->emitInt32(SectionSize);
1126 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1127 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1129 OutStreamer->emitInt32(0x13);
1130 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1131 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1137void AArch64AsmPrinter::emitLOHs() {
1141 for (
const MachineInstr *
MI :
D.getArgs()) {
1142 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1143 assert(LabelIt != LOHInstToLabel.end() &&
1144 "Label hasn't been inserted for LOH related instruction");
1147 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1152void AArch64AsmPrinter::emitFunctionBodyEnd() {
1158MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1162 if (!getDataLayout().getLinkerPrivateGlobalPrefix().
empty())
1163 return OutContext.getOrCreateSymbol(
1164 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1165 Twine(getFunctionNumber()) +
"_" + Twine(CPID));
1170void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1172 const MachineOperand &MO =
MI->getOperand(OpNum);
1188 PrintSymbolOperand(MO, O);
1199bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1223bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1225 unsigned AltName, raw_ostream &O) {
1226 assert(MO.
isReg() &&
"Should only get here with a register!");
1227 const TargetRegisterInfo *RI = STI->getRegisterInfo();
1236bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1237 const char *ExtraCode, raw_ostream &O) {
1238 const MachineOperand &MO =
MI->getOperand(OpNum);
1245 if (ExtraCode && ExtraCode[0]) {
1246 if (ExtraCode[1] != 0)
1249 switch (ExtraCode[0]) {
1257 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1271 switch (ExtraCode[0]) {
1273 RC = &AArch64::FPR8RegClass;
1276 RC = &AArch64::FPR16RegClass;
1279 RC = &AArch64::FPR32RegClass;
1282 RC = &AArch64::FPR64RegClass;
1285 RC = &AArch64::FPR128RegClass;
1288 RC = &AArch64::ZPRRegClass;
1293 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1314 unsigned AltName = AArch64::NoRegAltName;
1317 RegClass = &AArch64::ZPRRegClass;
1319 RegClass = &AArch64::PPRRegClass;
1321 RegClass = &AArch64::PNRRegClass;
1323 RegClass = &AArch64::FPR128RegClass;
1324 AltName = AArch64::vreg;
1328 return printAsmRegInClass(MO, RegClass, AltName, O);
1335bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1337 const char *ExtraCode,
1339 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1342 const MachineOperand &MO =
MI->getOperand(OpNum);
1343 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1348void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1350 unsigned NOps =
MI->getNumOperands();
1352 OS <<
'\t' << MAI.getCommentString() <<
"DEBUG_VALUE: ";
1354 OS <<
MI->getDebugVariable()->getName();
1357 assert(
MI->isIndirectDebugValue());
1369void AArch64AsmPrinter::emitJumpTableImpl(
const MachineJumpTableInfo &MJTI,
1370 ArrayRef<unsigned> JumpTableIndices) {
1372 if (JumpTableIndices.
empty())
1374 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
1378 MCSection *ReadOnlySec =
nullptr;
1379 if (TM.Options.EnableStaticDataPartitioning) {
1385 OutStreamer->switchSection(ReadOnlySec);
1387 auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1388 for (
unsigned JTI : JumpTableIndices) {
1389 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1392 if (JTBBs.empty())
continue;
1394 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1396 OutStreamer->emitLabel(GetJTISymbol(JTI));
1401 for (
auto *JTBB : JTBBs) {
1402 const MCExpr *
Value =
1421AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1422 const MachineInstr *BranchInstr,
1423 const MCSymbol *BranchLabel)
const {
1424 const auto AFI = MF->
getInfo<AArch64FunctionInfo>();
1427 switch (AFI->getJumpTableEntrySize(JTI)) {
1429 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1432 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1435 EntrySize = codeview::JumpTableEntrySize::Int32;
1440 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1443void AArch64AsmPrinter::emitFunctionEntryLabel() {
1444 const Triple &
TT = TM.getTargetTriple();
1445 if (
TT.isOSBinFormatELF() &&
1448 CallingConv::AArch64_SVE_VectorCall ||
1449 MF->
getInfo<AArch64FunctionInfo>()->isSVECC())) {
1451 static_cast<AArch64TargetStreamer *
>(OutStreamer->getTargetStreamer());
1462 OutStreamer->emitAssignment(
1466 auto getSymbolFromMetadata = [&](StringRef
Name) {
1470 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1477 for (MDNode *Node : UnmangledNames) {
1479 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1480 if (std::optional<std::string> MangledName =
1483 MMI->getContext().getOrCreateSymbol(*MangledName);
1484 emitFunctionAlias(UnmangledSym, ECMangledSym);
1487 if (MCSymbol *ECMangledSym =
1488 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1489 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1493void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1494 const Constant *CV) {
1497 "ctors/dtors are to be signed by asm printer");
1499 if (PtrauthInitFini) {
1505 ConstantInt *IntDisc = ConstantInt::get(
1509 if (PtrauthInitFiniAddressDisc) {
1523void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1524 const GlobalAlias &GA) {
1530 if (MDNode *Node =
F->getMetadata(
"arm64ec_exp_name")) {
1532 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1535 OutStreamer->beginCOFFSymbolDef(ExpSym);
1539 OutStreamer->endCOFFSymbolDef();
1541 OutStreamer->beginCOFFSymbolDef(Sym);
1545 OutStreamer->endCOFFSymbolDef();
1546 OutStreamer->emitSymbolAttribute(Sym,
MCSA_Weak);
1547 OutStreamer->emitAssignment(
1564void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
1565 const llvm::MachineInstr &
MI) {
1566 Register DestReg =
MI.getOperand(0).getReg();
1567 Register ScratchReg =
MI.getOperand(1).getReg();
1569 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1570 Register TableReg =
MI.getOperand(2).getReg();
1571 Register EntryReg =
MI.getOperand(3).getReg();
1572 int JTIdx =
MI.getOperand(4).getIndex();
1578 MF->
getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
1589 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
1591 .addExpr(LabelExpr));
1596 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1597 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1598 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1603 EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
1604 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1608 .addImm(
Size == 1 ? 0 : 1));
1612 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1616 .addImm(
Size == 4 ? 0 : 2));
1619void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1621 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1623 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1624 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1640 MachineOperand JTOp =
MI.getOperand(0);
1644 "unsupported compressed jump table");
1646 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1650 uint64_t MaxTableEntry = NumTableEntries - 1;
1652 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXri)
1653 .addReg(AArch64::XZR)
1654 .addReg(AArch64::X16)
1655 .addImm(MaxTableEntry)
1658 emitMOVZ(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry), 0);
1663 if ((MaxTableEntry >>
Offset) == 0)
1665 emitMOVK(AArch64::X17,
static_cast<uint16_t
>(MaxTableEntry >>
Offset),
1668 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
1669 .addReg(AArch64::XZR)
1670 .addReg(AArch64::X16)
1671 .addReg(AArch64::X17)
1677 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CSELXr)
1678 .addReg(AArch64::X16)
1679 .addReg(AArch64::X16)
1680 .addReg(AArch64::XZR)
1684 MachineOperand JTMOHi(JTOp), JTMOLo(JTOp);
1685 MCOperand JTMCHi, JTMCLo;
1695 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(JTMCHi));
1697 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri)
1698 .addReg(AArch64::X17)
1699 .addReg(AArch64::X17)
1703 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1704 .addReg(AArch64::X16)
1705 .addReg(AArch64::X17)
1706 .addReg(AArch64::X16)
1717 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1719 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1720 .addReg(AArch64::X16)
1721 .addReg(AArch64::X17)
1722 .addReg(AArch64::X16)
1725 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1728void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
1729 const llvm::MachineInstr &
MI) {
1730 unsigned Opcode =
MI.getOpcode();
1732 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1734 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1735 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1736 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1737 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1738 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1739 if (Opcode == AArch64::MOPSMemorySetPseudo)
1740 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1741 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1742 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1745 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1746 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1748 for (
auto Op :
Ops) {
1750 auto MCIB = MCInstBuilder(
Op);
1752 MCIB.addReg(
MI.getOperand(i++).getReg());
1753 MCIB.addReg(
MI.getOperand(i++).getReg());
1755 MCIB.addReg(
MI.getOperand(i++).getReg());
1757 MCIB.addReg(
MI.getOperand(i++).getReg());
1758 MCIB.addReg(
MI.getOperand(i++).getReg());
1759 MCIB.addReg(
MI.getOperand(i++).getReg());
1761 EmitToStreamer(OutStreamer, MCIB);
1765void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &
SM,
1766 const MachineInstr &
MI) {
1767 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
1770 MCSymbol *MILabel = Ctx.createTempSymbol();
1773 SM.recordStackMap(*MILabel,
MI);
1774 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1777 const MachineBasicBlock &
MBB = *
MI.getParent();
1780 while (NumNOPBytes > 0) {
1781 if (MII ==
MBB.
end() || MII->isCall() ||
1782 MII->getOpcode() == AArch64::DBG_VALUE ||
1783 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1784 MII->getOpcode() == TargetOpcode::STACKMAP)
1791 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1792 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1797void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
1798 const MachineInstr &
MI) {
1800 MCSymbol *MILabel = Ctx.createTempSymbol();
1802 SM.recordPatchPoint(*MILabel,
MI);
1804 PatchPointOpers Opers(&
MI);
1806 int64_t CallTarget = Opers.getCallTarget().getImm();
1807 unsigned EncodedBytes = 0;
1809 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1810 "High 16 bits of call target should be zero.");
1811 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1814 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1815 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1816 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1817 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1820 unsigned NumBytes = Opers.getNumPatchBytes();
1821 assert(NumBytes >= EncodedBytes &&
1822 "Patchpoint can't request size less than the length of a call.");
1823 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1824 "Invalid number of NOP bytes requested!");
1825 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1826 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1829void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
1830 const MachineInstr &
MI) {
1831 StatepointOpers SOpers(&
MI);
1832 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1833 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1834 for (
unsigned i = 0; i < PatchBytes; i += 4)
1835 EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::NOP));
1838 const MachineOperand &CallTarget = SOpers.getCallTarget();
1839 MCOperand CallTargetMCOp;
1840 unsigned CallOpcode;
1841 switch (CallTarget.
getType()) {
1844 MCInstLowering.
lowerOperand(CallTarget, CallTargetMCOp);
1845 CallOpcode = AArch64::BL;
1849 CallOpcode = AArch64::BL;
1853 CallOpcode = AArch64::BLR;
1860 EmitToStreamer(OutStreamer,
1861 MCInstBuilder(CallOpcode).
addOperand(CallTargetMCOp));
1865 MCSymbol *MILabel = Ctx.createTempSymbol();
1867 SM.recordStatepoint(*MILabel,
MI);
1870void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1879 unsigned OperandsBeginIdx = 4;
1882 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1889 MI.setOpcode(Opcode);
1894 for (
const MachineOperand &MO :
1897 lowerOperand(MO, Dest);
1898 MI.addOperand(Dest);
1906 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1908 .addReg(AArch64::XZR)
1913void AArch64AsmPrinter::emitMOVZ(
Register Dest, uint64_t Imm,
unsigned Shift) {
1914 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1915 EmitToStreamer(*OutStreamer,
1916 MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1922void AArch64AsmPrinter::emitMOVK(
Register Dest, uint64_t Imm,
unsigned Shift) {
1923 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1924 EmitToStreamer(*OutStreamer,
1925 MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1934 bool IsZeroDisc = Disc == AArch64::XZR;
1946 EmitToStreamer(AUTInst);
1951 bool IsZeroDisc = Disc == AArch64::XZR;
1963 EmitToStreamer(PACInst);
1968 bool IsZeroDisc = Disc == AArch64::XZR;
1978 EmitToStreamer(Inst);
1981void AArch64AsmPrinter::emitFMov0(
const MachineInstr &
MI) {
1982 Register DestReg =
MI.getOperand(0).getReg();
1983 if (!STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1984 if (STI->hasZeroCycleZeroingFPR64()) {
1986 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
1987 if (AArch64::FPR16RegClass.
contains(DestReg))
1988 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
1989 &AArch64::FPR64RegClass);
1990 else if (AArch64::FPR32RegClass.
contains(DestReg))
1991 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
1992 &AArch64::FPR64RegClass);
2000 EmitToStreamer(*OutStreamer, MOVI);
2001 ++NumZCZeroingInstrsFPR;
2002 }
else if (STI->hasZeroCycleZeroingFPR128()) {
2004 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2005 if (AArch64::FPR16RegClass.
contains(DestReg)) {
2006 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::hsub,
2007 &AArch64::FPR128RegClass);
2008 }
else if (AArch64::FPR32RegClass.
contains(DestReg)) {
2009 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::ssub,
2010 &AArch64::FPR128RegClass);
2013 DestReg =
TRI->getMatchingSuperReg(DestReg, AArch64::dsub,
2014 &AArch64::FPR128RegClass);
2021 EmitToStreamer(*OutStreamer, MOVI);
2022 ++NumZCZeroingInstrsFPR;
2024 emitFMov0AsFMov(
MI, DestReg);
2027 emitFMov0AsFMov(
MI, DestReg);
2031void AArch64AsmPrinter::emitFMov0AsFMov(
const MachineInstr &
MI,
2034 switch (
MI.getOpcode()) {
2037 case AArch64::FMOVH0:
2038 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
2039 if (!STI->hasFullFP16())
2040 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
2044 case AArch64::FMOVS0:
2049 case AArch64::FMOVD0:
2055 EmitToStreamer(*OutStreamer, FMov);
2058Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint64_t Disc,
2061 bool MayClobberAddrDisc) {
2062 assert(isPtrauthRegSafe(ScratchReg) &&
2063 "Safe scratch register must be provided by the caller");
2067 if (AddrDisc == AArch64::NoRegister)
2068 AddrDisc = AArch64::XZR;
2076 if (AddrDisc == AArch64::XZR) {
2077 emitMOVZ(ScratchReg, Disc, 0);
2084 if (MayClobberAddrDisc && isPtrauthRegSafe(AddrDisc)) {
2085 ScratchReg = AddrDisc;
2087 emitMovXReg(ScratchReg, AddrDisc);
2088 assert(ScratchReg != AddrDisc &&
2089 "Forbidden to clobber AddrDisc, but have to");
2092 emitMOVK(ScratchReg, Disc, 48);
2106void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
2138 if (Method == AuthCheckMethod::None)
2140 if (Method == AuthCheckMethod::DummyLoad) {
2141 EmitToStreamer(MCInstBuilder(AArch64::LDRWui)
2145 assert(!OnFailure &&
"DummyLoad always traps on error");
2149 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
2150 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
2152 emitMovXReg(ScratchReg, TestedReg);
2154 if (Method == AuthCheckMethod::XPAC) {
2158 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
2163 assert(TestedReg == AArch64::LR &&
2164 "XPACHint mode is only compatible with checking the LR register");
2166 "XPACHint mode is only compatible with I-keys");
2167 EmitToStreamer(MCInstBuilder(AArch64::XPACLRI));
2171 EmitToStreamer(MCInstBuilder(AArch64::SUBSXrs)
2172 .addReg(AArch64::XZR)
2179 MCInstBuilder(AArch64::Bcc)
2182 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2184 EmitToStreamer(MCInstBuilder(AArch64::EORXrs)
2191 MCInstBuilder(AArch64::TBZX)
2202 EmitToStreamer(MCInstBuilder(AArch64::BRK).addImm(0xc470 |
Key));
2216 case AuthCheckMethod::XPACHint:
2219 case AuthCheckMethod::XPAC:
2221 emitMovXReg(TestedReg, ScratchReg);
2228 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2233 EmitToStreamer(MCInstBuilder(AArch64::B).addExpr(OnFailureExpr));
2245void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2249 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2250 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2253 const AArch64RegisterInfo *
TRI = STI->getRegisterInfo();
2257 "Neither x16 nor x17 is available as a scratch register");
2260 emitPtrauthCheckAuthenticatedValue(AArch64::LR, ScratchReg,
Key,
2264bool AArch64AsmPrinter::emitDeactivationSymbolRelocation(
Value *DS) {
2270 EmitToStreamer(MCInstBuilder(AArch64::NOP));
2273 MCSymbol *Dot = OutContext.createTempSymbol();
2278 OutContext.getOrCreateSymbol(
DS->getName()), OutContext);
2284AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateImmReg(
2286 PtrAuthSchema Schema;
2288 Schema.IntDisc = IntDisc;
2289 Schema.AddrDisc = AddrDiscOp.
getReg();
2290 Schema.AddrDiscIsKilled = AddrDiscOp.
isKill();
2291 Schema.PCDisc = AArch64::NoRegister;
2295AArch64AsmPrinter::PtrAuthSchema AArch64AsmPrinter::PtrAuthSchema::CreateRegReg(
2297 assert(PCDisc != AArch64::NoRegister &&
2298 "Use CreateImmReg for non-PC schemas");
2299 PtrAuthSchema Schema;
2302 Schema.AddrDisc = AddrDisc;
2303 Schema.AddrDiscIsKilled =
false;
2304 Schema.PCDisc = PCDisc;
2308void AArch64AsmPrinter::emitPtrauthApplyIndirectAddend(
Register Pointer,
2313 EmitToStreamer(MCInstBuilder(AArch64::LDRSWpre)
2323 for (
int BitPos = 0; BitPos != 24 && (Addend >> BitPos); BitPos += 12) {
2325 MCInstBuilder(AArch64::ADDXri)
2328 .addImm((Addend >> BitPos) & 0xfff)
2334 emitMOVZ(Scratch, Addend & 0xffff, 0);
2336 if (
unsigned Fragment = (Addend >>
Offset) & 0xffff)
2337 emitMOVK(Scratch, Fragment,
Offset);
2341 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2348 EmitToStreamer(MCInstBuilder(AArch64::LDRSWui)
2354 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2361void AArch64AsmPrinter::emitPtrauthAuthResign(
2363 std::optional<PtrAuthSchema> SignSchema, std::optional<int64_t> Addend,
2365 const bool IsResign = SignSchema.has_value();
2366 const bool WithPC = AuthSchema.PCDisc != AArch64::NoRegister;
2367 assert(!SignSchema || SignSchema->PCDisc == AArch64::NoRegister);
2381 bool ShouldCheck =
true;
2388 ShouldCheck = ShouldTrap =
false;
2395 ShouldCheck = ShouldTrap =
false;
2402 ShouldCheck = ShouldTrap =
true;
2407 assert(Pointer == AArch64::X17 && Scratch == AArch64::X16 &&
2408 "AUTPCPAC must use x17/x16 as Pointer/Scratch");
2410 assert(AuthSchema.AddrDisc == AArch64::X16 &&
2411 "AUTPCPAC requires address discriminator in X16");
2413 assert(AuthSchema.PCDisc == AArch64::X15 &&
2414 "AUTPCPAC requires PC discriminator in X15");
2416 assert(AuthSchema.IntDisc == 0 &&
"AUTPCPAC does not support IntDisc");
2420 "AUTPCPAC only supports AUT-ing with IA/IB");
2422 if (!emitDeactivationSymbolRelocation(DS)) {
2424 ? AArch64::AUTIB171615
2425 : AArch64::AUTIA171615;
2426 EmitToStreamer(MCInstBuilder(AutOpc));
2431 emitPtrauthDiscriminator(AuthSchema.IntDisc, AuthSchema.AddrDisc,
2432 Scratch, AuthSchema.AddrDiscIsKilled);
2433 if (!emitDeactivationSymbolRelocation(DS))
2434 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2438 if (!IsResign && (!ShouldCheck || !ShouldTrap))
2444 if (IsResign && !ShouldTrap)
2445 EndSym = createTempSymbol(
"resign_end_");
2447 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2448 AArch64PAuth::AuthCheckMethod::XPAC,
2458 if (Addend.has_value())
2459 emitPtrauthApplyIndirectAddend(Pointer, Scratch, *Addend);
2462 Register PACDiscReg = emitPtrauthDiscriminator(SignSchema->IntDisc,
2463 SignSchema->AddrDisc, Scratch);
2464 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2471void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2474 uint64_t Disc =
MI->getOperand(3).getImm();
2475 Register AddrDisc =
MI->getOperand(4).getReg();
2476 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2480 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2481 assert(ScratchReg != AddrDisc &&
2482 "Neither X16 nor X17 is available as a scratch register");
2485 Register DiscReg = emitPtrauthDiscriminator(
2486 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2488 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2491 emitPAC(
Key, Val, DiscReg);
2494void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2495 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2496 unsigned BrTarget =
MI->getOperand(0).getReg();
2499 uint64_t Disc =
MI->getOperand(2).getImm();
2501 unsigned AddrDisc =
MI->getOperand(3).getReg();
2507 if (BrTarget == AddrDisc)
2524 bool AddrDiscIsImplicitDef =
2525 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2526 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2527 AddrDiscIsImplicitDef);
2528 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2531void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2534 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2535 const bool IsNeg = Addend < 0;
2537 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2540 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2543 .addImm((AbsOffset >> BitPos) & 0xfff)
2547 const uint64_t UAddend = Addend;
2548 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2550 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2552 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2553 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2554 uint64_t Shifted = UAddend >> BitPos;
2556 return Shifted != 0;
2557 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2558 if (((Shifted >>
I) & 0xffff) != 0xffff)
2562 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2563 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2565 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2574void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2575 MCRegister Tmp,
bool DSOLocal,
2576 const MCSubtargetInfo &STI) {
2582 MCInstBuilder(AArch64::ADRP)
2586 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2596 MCInstBuilder(AArch64::ADRP)
2601 MCInstBuilder(AArch64::LDRXui)
2612 if (!TT.isOSBinFormatELF())
2616 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2617 TT.isOSDragonFly() || TT.isOSNetBSD();
2671const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2673 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2674 const Triple &
TT = TM.getTargetTriple();
2686 auto STI = std::make_unique<AArch64Subtarget>(
2687 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2689 this->STI = STI.get();
2695 const MCSymbolELF *Group =
2710 .addReg(AArch64::X0)
2715 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2717 if (HasAddressDiversity) {
2722 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2726 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2728 "' out of range [0, 0xFFFF]");
2730 emitMOVZ(AArch64::X1, Disc, 0);
2737 auto *PrePACInstExpr =
2749 const MCSymbolRefExpr *EmuPACRef =
2751 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2758 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2767AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2768 MCContext &Ctx = OutContext;
2773 getDataLayout(),
Offset,
true);
2793 const MCExpr *DSExpr =
nullptr;
2805 "' out of range [0, " +
2813 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2815 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2820 "' out of range [0, 0xFFFF]");
2826 "expressions on this target");
2833void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2834 unsigned DstReg =
MI.getOperand(0).getReg();
2835 const MachineOperand &GAOp =
MI.getOperand(1);
2836 const uint64_t KeyC =
MI.getOperand(2).getImm();
2838 "key is out of range [0, AArch64PACKey::LAST]");
2840 const uint64_t Disc =
MI.getOperand(3).getImm();
2842 "constant discriminator is out of range [0, 0xffff]");
2851 if (TM.getTargetTriple().isOSBinFormatELF()) {
2853 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2856 "non-zero offset for $auth_ptr$ stub slots is not supported");
2858 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2860 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2861 "LOADauthptrstatic is implemented only for MachO/ELF");
2863 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2864 getObjFileLowering());
2867 "non-zero offset for $auth_ptr$ stub slots is not supported");
2869 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2872 MachineOperand StubMOHi =
2876 MCOperand StubMCHi, StubMCLo;
2883 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2885 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2891void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2892 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2893 const bool IsELFSignedGOT =
MI.getParent()
2895 ->getInfo<AArch64FunctionInfo>()
2896 ->hasELFSignedGOT();
2897 MachineOperand GAOp =
MI.getOperand(0);
2898 const uint64_t KeyC =
MI.getOperand(1).getImm();
2900 "key is out of range [0, AArch64PACKey::LAST]");
2902 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2903 const uint64_t Disc =
MI.getOperand(3).getImm();
2950 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2951 MCOperand GAMCHi, GAMCLo;
2964 MCInstBuilder(AArch64::ADRP)
2965 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2969 if (IsELFSignedGOT) {
2970 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2971 .addReg(AArch64::X17)
2972 .addReg(AArch64::X17)
2976 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2977 .addReg(AArch64::X16)
2978 .addReg(AArch64::X17)
2986 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2988 if (!STI->hasFPAC())
2989 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2990 AArch64PAuth::AuthCheckMethod::XPAC);
2992 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2993 .addReg(AArch64::X16)
2994 .addReg(AArch64::X16)
2998 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2999 .addReg(AArch64::X16)
3000 .addReg(AArch64::X16)
3005 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
3006 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
3008 emitPAC(
Key, AArch64::X16, DiscReg);
3011void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
3013 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
3014 const MachineOperand &GAMO =
MI.getOperand(1);
3021 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
3022 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3023 .addReg(AuthResultReg)
3024 .addReg(AArch64::X17)
3027 MachineOperand GAHiOp(GAMO);
3028 MachineOperand GALoOp(GAMO);
3032 MCOperand GAMCHi, GAMCLo;
3037 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
3039 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3040 .addReg(AArch64::X17)
3041 .addReg(AArch64::X17)
3045 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3046 .addReg(AuthResultReg)
3047 .addReg(AArch64::X17)
3054 UndefWeakSym = createTempSymbol(
"undef_weak");
3056 MCInstBuilder(AArch64::CBZX)
3057 .addReg(AuthResultReg)
3065 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
3070 if (!STI->hasFPAC()) {
3071 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
3072 AArch64PAuth::AuthCheckMethod::XPAC);
3074 emitMovXReg(DstReg, AuthResultReg);
3079AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
3083 if (std::optional<uint16_t> BADisc =
3084 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
3091void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
3095 switch (
MI->getOpcode()) {
3098 case AArch64::CBBAssertExt:
3102 case AArch64::CBHAssertExt:
3106 case AArch64::CBWPrr:
3109 case AArch64::CBXPrr:
3112 case AArch64::CBWPri:
3116 case AArch64::CBXPri:
3124 bool NeedsRegSwap =
false;
3125 bool NeedsImmDec =
false;
3126 bool NeedsImmInc =
false;
3128#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
3130 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
3132 ? AArch64::CBB##RegCond##Wrr \
3133 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
3134 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
3135 : AArch64::CB##RegCond##Xrr))))
3151 NeedsImmDec = IsImm;
3155 NeedsRegSwap = !IsImm;
3162 NeedsRegSwap = !IsImm;
3163 NeedsImmInc = IsImm;
3167 NeedsImmDec = IsImm;
3171 NeedsRegSwap = !IsImm;
3178 NeedsRegSwap = !IsImm;
3179 NeedsImmInc = IsImm;
3187 MCOperand Lhs, Rhs, Trgt;
3188 lowerOperand(
MI->getOperand(1), Lhs);
3189 lowerOperand(
MI->getOperand(2), Rhs);
3190 lowerOperand(
MI->getOperand(3), Trgt);
3194 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3195 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3198 }
else if (NeedsImmDec) {
3202 }
else if (NeedsImmInc) {
3212 "CB immediate operand out-of-bounds");
3215 EmitToStreamer(*OutStreamer, Inst);
3220#include "AArch64GenMCPseudoLowering.inc"
3222void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3229void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3230 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3235 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3240 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3241 EmitToStreamer(*OutStreamer, OutInst);
3245 if (
MI->getOpcode() == AArch64::ADRP) {
3246 for (
auto &Opd :
MI->operands()) {
3247 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3248 "swift_async_extendedFramePointerFlags") {
3249 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3256 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3258 LOHInstToLabel[
MI] = LOHLabel;
3262 AArch64TargetStreamer *TS =
3265 switch (
MI->getOpcode()) {
3268 "Unhandled tail call instruction");
3270 case AArch64::READ_REGISTER_GPR64:
3274 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
3275 .addReg(
MI->getOperand(0).getReg())
3276 .addReg(AArch64::XZR)
3277 .addReg(
MI->getOperand(1).getImm())
3280 case AArch64::READ_REGISTER_FPR64:
3282 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::FMOVDr)
3283 .addReg(
MI->getOperand(0).getReg())
3284 .addReg(
MI->getOperand(1).getImm()));
3286 case AArch64::HINT: {
3291 if (CurrentPatchableFunctionEntrySym &&
3292 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3294 int64_t
Imm =
MI->getOperand(0).getImm();
3295 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38) {
3297 MCInstLowering.
Lower(
MI, Inst);
3298 EmitToStreamer(*OutStreamer, Inst);
3299 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3300 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3306 case AArch64::MOVMCSym: {
3307 Register DestReg =
MI->getOperand(0).getReg();
3308 const MachineOperand &MO_Sym =
MI->getOperand(1);
3309 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3310 MCOperand Hi_MCSym, Lo_MCSym;
3323 EmitToStreamer(*OutStreamer, MovZ);
3331 EmitToStreamer(*OutStreamer, MovK);
3334 case AArch64::MOVIv2d_ns:
3342 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3343 MI->getOperand(1).getImm() == 0) {
3345 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3348 EmitToStreamer(*OutStreamer, TmpInst);
3353 case AArch64::DBG_VALUE:
3354 case AArch64::DBG_VALUE_LIST:
3356 SmallString<128> TmpStr;
3357 raw_svector_ostream OS(TmpStr);
3358 PrintDebugValueComment(
MI, OS);
3363 case AArch64::EMITBKEY: {
3365 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3366 ExceptionHandlingType != ExceptionHandling::ARM)
3369 if (getFunctionCFISectionType(*MF) == CFISection::None)
3376 case AArch64::EMITMTETAGGED: {
3378 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3379 ExceptionHandlingType != ExceptionHandling::ARM)
3382 if (getFunctionCFISectionType(*MF) != CFISection::None)
3387 case AArch64::AUTx16x17: {
3389 const Register Scratch = AArch64::X17;
3391 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3393 MI->getOperand(1).getImm(),
MI->getOperand(2));
3395 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3396 std::nullopt,
MI->getDeactivationSymbol());
3400 case AArch64::AUTxMxN: {
3402 const Register Scratch =
MI->getOperand(1).getReg();
3404 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3406 MI->getOperand(4).getImm(),
MI->getOperand(5));
3408 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3409 std::nullopt,
MI->getDeactivationSymbol());
3413 case AArch64::AUTPAC: {
3415 const Register Scratch = AArch64::X17;
3417 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3419 MI->getOperand(1).getImm(),
MI->getOperand(2));
3421 auto SignSchema = PtrAuthSchema::CreateImmReg(
3423 MI->getOperand(4).getImm(),
MI->getOperand(5));
3425 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3426 std::nullopt,
MI->getDeactivationSymbol());
3430 case AArch64::AUTPCPAC: {
3431 auto AuthSchema = PtrAuthSchema::CreateRegReg(
3435 auto SignSchema = PtrAuthSchema::CreateImmReg(
3437 MI->getOperand(2).getImm(),
MI->getOperand(3));
3439 emitPtrauthAuthResign(AArch64::X17, AArch64::X16,
3440 AuthSchema, SignSchema, std::nullopt,
3441 MI->getDeactivationSymbol());
3445 case AArch64::AUTRELLOADPAC: {
3447 const Register Scratch = AArch64::X17;
3449 auto AuthSchema = PtrAuthSchema::CreateImmReg(
3451 MI->getOperand(1).getImm(),
MI->getOperand(2));
3453 auto SignSchema = PtrAuthSchema::CreateImmReg(
3455 MI->getOperand(4).getImm(),
MI->getOperand(5));
3457 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3458 MI->getOperand(6).getImm(),
3459 MI->getDeactivationSymbol());
3465 emitPtrauthSign(
MI);
3468 case AArch64::LOADauthptrstatic:
3469 LowerLOADauthptrstatic(*
MI);
3472 case AArch64::LOADgotPAC:
3473 case AArch64::MOVaddrPAC:
3474 LowerMOVaddrPAC(*
MI);
3477 case AArch64::LOADgotAUTH:
3478 LowerLOADgotAUTH(*
MI);
3483 emitPtrauthBranch(
MI);
3489 case AArch64::AUTH_TCRETURN:
3490 case AArch64::AUTH_TCRETURN_BTI: {
3493 const uint64_t Disc =
MI->getOperand(3).getImm();
3495 Register AddrDisc =
MI->getOperand(4).getReg();
3497 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3499 emitPtrauthTailCallHardening(
MI);
3502 if (Callee == AddrDisc)
3509 bool AddrDiscIsImplicitDef =
3510 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3511 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3512 AddrDiscIsImplicitDef);
3513 emitBLRA(
false,
Key, Callee, DiscReg);
3517 case AArch64::TCRETURNri:
3518 case AArch64::TCRETURNrix16x17:
3519 case AArch64::TCRETURNrix17:
3520 case AArch64::TCRETURNrinotx16:
3521 case AArch64::TCRETURNriALL: {
3522 emitPtrauthTailCallHardening(
MI);
3524 recordIfImportCall(
MI);
3528 EmitToStreamer(*OutStreamer, TmpInst);
3531 case AArch64::TCRETURNdi: {
3532 emitPtrauthTailCallHardening(
MI);
3536 recordIfImportCall(
MI);
3540 EmitToStreamer(*OutStreamer, TmpInst);
3543 case AArch64::SpeculationBarrierISBDSBEndBB: {
3548 EmitToStreamer(*OutStreamer, TmpInstDSB);
3552 EmitToStreamer(*OutStreamer, TmpInstISB);
3555 case AArch64::SpeculationBarrierSBEndBB: {
3559 EmitToStreamer(*OutStreamer, TmpInstSB);
3562 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3569 const MachineOperand &MO_Sym =
MI->getOperand(0);
3570 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3571 MCOperand SymTLSDescLo12, SymTLSDesc;
3574 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3581 EmitToStreamer(*OutStreamer, Adrp);
3589 EmitToStreamer(*OutStreamer, Ldr);
3592 Add.setOpcode(AArch64::ADDXri);
3595 Add.addOperand(SymTLSDescLo12);
3597 EmitToStreamer(*OutStreamer,
Add);
3606 EmitToStreamer(*OutStreamer, Blraa);
3610 case AArch64::TLSDESC_CALLSEQ: {
3618 const MachineOperand &MO_Sym =
MI->getOperand(0);
3619 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3620 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3624 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3631 EmitToStreamer(*OutStreamer, Adrp);
3634 if (STI->isTargetILP32()) {
3644 EmitToStreamer(*OutStreamer, Ldr);
3647 if (STI->isTargetILP32()) {
3648 Add.setOpcode(AArch64::ADDWri);
3652 Add.setOpcode(AArch64::ADDXri);
3656 Add.addOperand(SymTLSDescLo12);
3658 EmitToStreamer(*OutStreamer,
Add);
3663 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3665 EmitToStreamer(*OutStreamer, TLSDescCall);
3673 EmitToStreamer(*OutStreamer, Blr);
3678 case AArch64::JumpTableDest32:
3679 case AArch64::JumpTableDest16:
3680 case AArch64::JumpTableDest8:
3681 LowerJumpTableDest(*OutStreamer, *
MI);
3684 case AArch64::BR_JumpTable:
3685 LowerHardenedBRJumpTable(*
MI);
3688 case AArch64::FMOVH0:
3689 case AArch64::FMOVS0:
3690 case AArch64::FMOVD0:
3694 case AArch64::MOPSMemoryCopyPseudo:
3695 case AArch64::MOPSMemoryMovePseudo:
3696 case AArch64::MOPSMemorySetPseudo:
3697 case AArch64::MOPSMemorySetTaggingPseudo:
3698 LowerMOPS(*OutStreamer, *
MI);
3701 case TargetOpcode::STACKMAP:
3702 return LowerSTACKMAP(*OutStreamer,
SM, *
MI);
3704 case TargetOpcode::PATCHPOINT:
3705 return LowerPATCHPOINT(*OutStreamer,
SM, *
MI);
3707 case TargetOpcode::STATEPOINT:
3708 return LowerSTATEPOINT(*OutStreamer,
SM, *
MI);
3710 case TargetOpcode::FAULTING_OP:
3711 return LowerFAULTING_OP(*
MI);
3713 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3714 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3717 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3718 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3721 case TargetOpcode::PATCHABLE_TAIL_CALL:
3722 LowerPATCHABLE_TAIL_CALL(*
MI);
3724 case TargetOpcode::PATCHABLE_EVENT_CALL:
3725 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3726 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3727 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3729 case AArch64::KCFI_CHECK:
3730 LowerKCFI_CHECK(*
MI);
3733 case AArch64::HWASAN_CHECK_MEMACCESS:
3734 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3735 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3736 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3737 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3740 case AArch64::SEH_StackAlloc:
3744 case AArch64::SEH_SaveFPLR:
3748 case AArch64::SEH_SaveFPLR_X:
3749 assert(
MI->getOperand(0).getImm() < 0 &&
3750 "Pre increment SEH opcode must have a negative offset");
3754 case AArch64::SEH_SaveReg:
3756 MI->getOperand(1).getImm());
3759 case AArch64::SEH_SaveReg_X:
3760 assert(
MI->getOperand(1).getImm() < 0 &&
3761 "Pre increment SEH opcode must have a negative offset");
3763 -
MI->getOperand(1).getImm());
3766 case AArch64::SEH_SaveRegP:
3767 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3768 MI->getOperand(0).getImm() <= 28) {
3769 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3770 "Register paired with LR must be odd");
3772 MI->getOperand(2).getImm());
3775 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3776 "Non-consecutive registers not allowed for save_regp");
3778 MI->getOperand(2).getImm());
3781 case AArch64::SEH_SaveRegP_X:
3782 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3783 "Non-consecutive registers not allowed for save_regp_x");
3784 assert(
MI->getOperand(2).getImm() < 0 &&
3785 "Pre increment SEH opcode must have a negative offset");
3787 -
MI->getOperand(2).getImm());
3790 case AArch64::SEH_SaveFReg:
3792 MI->getOperand(1).getImm());
3795 case AArch64::SEH_SaveFReg_X:
3796 assert(
MI->getOperand(1).getImm() < 0 &&
3797 "Pre increment SEH opcode must have a negative offset");
3799 -
MI->getOperand(1).getImm());
3802 case AArch64::SEH_SaveFRegP:
3803 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3804 "Non-consecutive registers not allowed for save_regp");
3806 MI->getOperand(2).getImm());
3809 case AArch64::SEH_SaveFRegP_X:
3810 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3811 "Non-consecutive registers not allowed for save_regp_x");
3812 assert(
MI->getOperand(2).getImm() < 0 &&
3813 "Pre increment SEH opcode must have a negative offset");
3815 -
MI->getOperand(2).getImm());
3818 case AArch64::SEH_SetFP:
3822 case AArch64::SEH_AddFP:
3826 case AArch64::SEH_Nop:
3830 case AArch64::SEH_PrologEnd:
3834 case AArch64::SEH_EpilogStart:
3838 case AArch64::SEH_EpilogEnd:
3842 case AArch64::SEH_PACSignLR:
3846 case AArch64::SEH_SaveAnyRegI:
3847 assert(
MI->getOperand(1).getImm() <= 1008 &&
3848 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3850 MI->getOperand(1).getImm());
3853 case AArch64::SEH_SaveAnyRegIP:
3854 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3855 "Non-consecutive registers not allowed for save_any_reg");
3856 assert(
MI->getOperand(2).getImm() <= 1008 &&
3857 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3859 MI->getOperand(2).getImm());
3862 case AArch64::SEH_SaveAnyRegQP:
3863 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3864 "Non-consecutive registers not allowed for save_any_reg");
3865 assert(
MI->getOperand(2).getImm() >= 0 &&
3866 "SaveAnyRegQP SEH opcode offset must be non-negative");
3867 assert(
MI->getOperand(2).getImm() <= 1008 &&
3868 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3870 MI->getOperand(2).getImm());
3873 case AArch64::SEH_SaveAnyRegQPX:
3874 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3875 "Non-consecutive registers not allowed for save_any_reg");
3876 assert(
MI->getOperand(2).getImm() < 0 &&
3877 "SaveAnyRegQPX SEH opcode offset must be negative");
3878 assert(
MI->getOperand(2).getImm() >= -1008 &&
3879 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3881 -
MI->getOperand(2).getImm());
3884 case AArch64::SEH_AllocZ:
3885 assert(
MI->getOperand(0).getImm() >= 0 &&
3886 "AllocZ SEH opcode offset must be non-negative");
3887 assert(
MI->getOperand(0).getImm() <= 255 &&
3888 "AllocZ SEH opcode offset must fit into 8 bits");
3892 case AArch64::SEH_SaveZReg:
3893 assert(
MI->getOperand(1).getImm() >= 0 &&
3894 "SaveZReg SEH opcode offset must be non-negative");
3895 assert(
MI->getOperand(1).getImm() <= 255 &&
3896 "SaveZReg SEH opcode offset must fit into 8 bits");
3898 MI->getOperand(1).getImm());
3901 case AArch64::SEH_SavePReg:
3902 assert(
MI->getOperand(1).getImm() >= 0 &&
3903 "SavePReg SEH opcode offset must be non-negative");
3904 assert(
MI->getOperand(1).getImm() <= 255 &&
3905 "SavePReg SEH opcode offset must fit into 8 bits");
3907 MI->getOperand(1).getImm());
3912 recordIfImportCall(
MI);
3914 MCInstLowering.
Lower(
MI, TmpInst);
3915 EmitToStreamer(*OutStreamer, TmpInst);
3918 case AArch64::CBWPri:
3919 case AArch64::CBXPri:
3920 case AArch64::CBBAssertExt:
3921 case AArch64::CBHAssertExt:
3922 case AArch64::CBWPrr:
3923 case AArch64::CBXPrr:
3924 emitCBPseudoExpansion(
MI);
3928 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3933 MCInstLowering.
Lower(
MI, TmpInst);
3934 EmitToStreamer(*OutStreamer, TmpInst);
3937void AArch64AsmPrinter::recordIfImportCall(
3938 const llvm::MachineInstr *BranchInst) {
3939 if (!EnableImportCallOptimization)
3943 if (GV && GV->hasDLLImportStorageClass()) {
3944 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3949 .push_back({CallSiteSymbol, CalledSymbol});
3953void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3954 MCSymbol *LazyPointer) {
3971 EmitToStreamer(Adrp);
3979 MCOperand SymPageOff;
3986 EmitToStreamer(Ldr);
3989 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3990 .addReg(AArch64::X16)
3991 .addReg(AArch64::X16)
3994 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3996 .addReg(AArch64::X16));
3999void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
4000 const GlobalIFunc &GI,
4001 MCSymbol *LazyPointer) {
4033 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4034 .addReg(AArch64::SP)
4035 .addReg(AArch64::FP)
4036 .addReg(AArch64::LR)
4037 .addReg(AArch64::SP)
4040 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4041 .addReg(AArch64::FP)
4042 .addReg(AArch64::SP)
4046 for (
int I = 0;
I != 4; ++
I)
4047 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
4048 .addReg(AArch64::SP)
4049 .addReg(AArch64::X1 + 2 *
I)
4050 .addReg(AArch64::X0 + 2 *
I)
4051 .addReg(AArch64::SP)
4054 for (
int I = 0;
I != 4; ++
I)
4055 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
4056 .addReg(AArch64::SP)
4057 .addReg(AArch64::D1 + 2 *
I)
4058 .addReg(AArch64::D0 + 2 *
I)
4059 .addReg(AArch64::SP)
4063 MCInstBuilder(AArch64::BL)
4076 EmitToStreamer(Adrp);
4084 MCOperand SymPageOff;
4091 EmitToStreamer(Ldr);
4094 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
4095 .addReg(AArch64::X0)
4096 .addReg(AArch64::X16)
4099 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
4100 .addReg(AArch64::X16)
4101 .addReg(AArch64::X0)
4105 for (
int I = 3;
I != -1; --
I)
4106 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
4107 .addReg(AArch64::SP)
4108 .addReg(AArch64::D1 + 2 *
I)
4109 .addReg(AArch64::D0 + 2 *
I)
4110 .addReg(AArch64::SP)
4113 for (
int I = 3;
I != -1; --
I)
4114 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4115 .addReg(AArch64::SP)
4116 .addReg(AArch64::X1 + 2 *
I)
4117 .addReg(AArch64::X0 + 2 *
I)
4118 .addReg(AArch64::SP)
4121 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
4122 .addReg(AArch64::SP)
4123 .addReg(AArch64::FP)
4124 .addReg(AArch64::LR)
4125 .addReg(AArch64::SP)
4128 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
4130 .addReg(AArch64::X16));
4133const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
4134 const Constant *BaseCV,
4144char AArch64AsmPrinter::ID = 0;
4147 "AArch64 Assembly Printer",
false,
false)
4151LLVMInitializeAArch64AsmPrinter() {
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 getOptionalBooleanModuleFlag(Module &M, StringRef Name)
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 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
Get the first element.
bool empty() const
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
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
@ AddrDiscriminator_CtorsDtors
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
static LLVM_ABI ConstantPtrAuth * get(Constant *Ptr, ConstantInt *Key, ConstantInt *Disc, Constant *AddrDisc, Constant *DeactivationSymbol)
Return a pointer signed with the specified parameters.
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.
LLVM_ABI void recordFaultingOp(FaultKind FaultTy, const MCSymbol *FaultingLabel, const MCSymbol *HandlerLabel)
LLVM_ABI 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
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
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)
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
static constexpr unsigned NonUniqueID
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
virtual void emitCFIBKeyFrame()
virtual bool popSection()
Restore the current and previous section from the section stack.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc={})
Record a relocation described by the .reloc directive.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCFIMTETaggedFrame()
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
void pushSection()
Save the current and previous section on the section stack.
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
MCSection * getCurrentSectionOnly() const
void emitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ....
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
const MCSymbol * getAddSym() const
int64_t getConstant() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
CalledGlobalInfo tryGetCalledGlobal(const MachineInstr *MI) const
Tries to get the global and target flags for a call site, if the instruction is a call to a global.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
ExprStubListTy getAuthGVStubList()
ExprStubListTy getAuthGVStubList()
unsigned getSubReg() const
static MachineOperand CreateMCSymbol(MCSymbol *Sym, unsigned TargetFlags=0)
const GlobalValue * getGlobal() const
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const BlockAddress * getBlockAddress() const
void setOffset(int64_t Offset)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
int64_t getOffset() const
Return the offset from the symbol in this operand.
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static SectionKind getMetadata()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
constexpr const char * data() const
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.
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.
LLVM_ABI 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.
constexpr AArch64PACKey::ID InitFiniKey
PAuth key to be used with function pointers in .init_array and .fini_array.
AuthCheckMethod
Variants of check performed on an authenticated pointer.
constexpr unsigned InitFiniPointerConstantDiscriminator
Constant discriminator to be used with function pointers in .init_array and .fini_array.
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.
@ C
The default llvm calling convention, compatible with C.
@ AARCH64_PAUTH_PLATFORM_LLVM_LINUX
@ 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.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
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.
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,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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)
MCRegisterClass TargetRegisterClass
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,...