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,
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();
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();
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();
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,
Value *DS) {
2241 const bool IsResign = SignSchema.has_value();
2255 bool ShouldCheck =
true;
2262 ShouldCheck = ShouldTrap =
false;
2269 ShouldCheck = ShouldTrap =
false;
2276 ShouldCheck = ShouldTrap =
true;
2282 emitPtrauthDiscriminator(AuthSchema.IntDisc, AuthSchema.AddrDisc, Scratch,
2283 AuthSchema.AddrDiscIsKilled);
2285 if (!emitDeactivationSymbolRelocation(DS))
2286 emitAUT(AuthSchema.Key, Pointer, AUTDiscReg);
2289 if (!IsResign && (!ShouldCheck || !ShouldTrap))
2295 if (IsResign && !ShouldTrap)
2296 EndSym = createTempSymbol(
"resign_end_");
2298 emitPtrauthCheckAuthenticatedValue(Pointer, Scratch, AuthSchema.Key,
2299 AArch64PAuth::AuthCheckMethod::XPAC,
2310 Register PACDiscReg = emitPtrauthDiscriminator(SignSchema->IntDisc,
2311 SignSchema->AddrDisc, Scratch);
2312 emitPAC(SignSchema->Key, Pointer, PACDiscReg);
2319void AArch64AsmPrinter::emitPtrauthSign(
const MachineInstr *
MI) {
2322 uint64_t Disc =
MI->getOperand(3).getImm();
2323 Register AddrDisc =
MI->getOperand(4).getReg();
2324 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2328 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2329 assert(ScratchReg != AddrDisc &&
2330 "Neither X16 nor X17 is available as a scratch register");
2333 Register DiscReg = emitPtrauthDiscriminator(
2334 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2336 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
2339 emitPAC(
Key, Val, DiscReg);
2342void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2343 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2344 unsigned BrTarget =
MI->getOperand(0).getReg();
2347 uint64_t Disc =
MI->getOperand(2).getImm();
2349 unsigned AddrDisc =
MI->getOperand(3).getReg();
2355 if (BrTarget == AddrDisc)
2372 bool AddrDiscIsImplicitDef =
2373 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2374 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2375 AddrDiscIsImplicitDef);
2376 emitBLRA(IsCall,
Key, BrTarget, DiscReg);
2379void AArch64AsmPrinter::emitAddImm(MCRegister
Reg, int64_t Addend,
2382 const uint64_t AbsOffset = (Addend > 0 ? Addend : -((uint64_t)Addend));
2383 const bool IsNeg = Addend < 0;
2385 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2388 MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri)
2391 .addImm((AbsOffset >> BitPos) & 0xfff)
2395 const uint64_t UAddend = Addend;
2396 EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2398 .addImm((IsNeg ? ~UAddend : UAddend) & 0xffff)
2400 auto NeedMovk = [IsNeg, UAddend](
int BitPos) ->
bool {
2401 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2402 uint64_t Shifted = UAddend >> BitPos;
2404 return Shifted != 0;
2405 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2406 if (((Shifted >>
I) & 0xffff) != 0xffff)
2410 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2411 emitMOVK(Tmp, (UAddend >> BitPos) & 0xffff, BitPos);
2413 EmitToStreamer(MCInstBuilder(AArch64::ADDXrs)
2422void AArch64AsmPrinter::emitAddress(MCRegister
Reg,
const MCExpr *Expr,
2423 MCRegister Tmp,
bool DSOLocal,
2424 const MCSubtargetInfo &STI) {
2430 MCInstBuilder(AArch64::ADRP)
2434 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2444 MCInstBuilder(AArch64::ADRP)
2449 MCInstBuilder(AArch64::LDRXui)
2460 if (!TT.isOSBinFormatELF())
2464 return TT.isOSGlibc() || TT.isAndroid() || TT.isOSFreeBSD() ||
2465 TT.isOSDragonFly() || TT.isOSNetBSD();
2519const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
2521 bool HasAddressDiversity,
bool IsDSOLocal,
const MCExpr *DSExpr) {
2522 const Triple &
TT = TM.getTargetTriple();
2534 auto STI = std::make_unique<AArch64Subtarget>(
2535 TT, TM.getTargetCPU(), TM.getTargetCPU(), TM.getTargetFeatureString(), TM,
2537 this->STI = STI.get();
2543 const MCSymbolELF *Group =
2558 .addReg(AArch64::X0)
2563 emitAddress(AArch64::X0, Target, AArch64::X16, IsDSOLocal, *STI);
2565 if (HasAddressDiversity) {
2570 emitAddress(AArch64::X1, PlacePlusDisc, AArch64::X16,
true,
2574 OutContext.reportError(SMLoc(),
"AArch64 PAC Discriminator '" +
2576 "' out of range [0, 0xFFFF]");
2578 emitMOVZ(AArch64::X1, Disc, 0);
2585 auto *PrePACInstExpr =
2597 const MCSymbolRefExpr *EmuPACRef =
2599 OutStreamer->
emitInstruction(MCInstBuilder(AArch64::B).addExpr(EmuPACRef),
2606 MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
2614AArch64AsmPrinter::lowerConstantPtrAuth(
const ConstantPtrAuth &CPA) {
2615 MCContext &Ctx = OutContext;
2620 getDataLayout(),
Offset,
true);
2638 const MCExpr *DSExpr =
nullptr;
2650 "' out of range [0, " +
2658 if (
auto *IFuncSym = emitPAuthRelocationAsIRelative(
2660 BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
2665 "' out of range [0, 0xFFFF]");
2671 "expressions on this target");
2678void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2679 unsigned DstReg =
MI.getOperand(0).getReg();
2680 const MachineOperand &GAOp =
MI.getOperand(1);
2681 const uint64_t KeyC =
MI.getOperand(2).getImm();
2683 "key is out of range [0, AArch64PACKey::LAST]");
2685 const uint64_t Disc =
MI.getOperand(3).getImm();
2687 "constant discriminator is out of range [0, 0xffff]");
2696 if (TM.getTargetTriple().isOSBinFormatELF()) {
2698 static_cast<const AArch64_ELFTargetObjectFile &
>(getObjFileLowering());
2701 "non-zero offset for $auth_ptr$ stub slots is not supported");
2703 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2705 assert(TM.getTargetTriple().isOSBinFormatMachO() &&
2706 "LOADauthptrstatic is implemented only for MachO/ELF");
2708 const auto &TLOF =
static_cast<const AArch64_MachoTargetObjectFile &
>(
2709 getObjFileLowering());
2712 "non-zero offset for $auth_ptr$ stub slots is not supported");
2714 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym,
Key, Disc);
2717 MachineOperand StubMOHi =
2721 MCOperand StubMCHi, StubMCLo;
2728 MCInstBuilder(AArch64::ADRP).addReg(DstReg).
addOperand(StubMCHi));
2730 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRXui)
2736void AArch64AsmPrinter::LowerMOVaddrPAC(
const MachineInstr &
MI) {
2737 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2738 const bool IsELFSignedGOT =
MI.getParent()
2740 ->getInfo<AArch64FunctionInfo>()
2741 ->hasELFSignedGOT();
2742 MachineOperand GAOp =
MI.getOperand(0);
2743 const uint64_t KeyC =
MI.getOperand(1).getImm();
2745 "key is out of range [0, AArch64PACKey::LAST]");
2747 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2748 const uint64_t Disc =
MI.getOperand(3).getImm();
2795 MachineOperand GAMOHi(GAOp), GAMOLo(GAOp);
2796 MCOperand GAMCHi, GAMCLo;
2809 MCInstBuilder(AArch64::ADRP)
2810 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2814 if (IsELFSignedGOT) {
2815 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2816 .addReg(AArch64::X17)
2817 .addReg(AArch64::X17)
2821 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2822 .addReg(AArch64::X16)
2823 .addReg(AArch64::X17)
2831 emitAUT(AuthKey, AArch64::X16, AArch64::X17);
2833 if (!STI->hasFPAC())
2834 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2835 AArch64PAuth::AuthCheckMethod::XPAC);
2837 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2838 .addReg(AArch64::X16)
2839 .addReg(AArch64::X16)
2843 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2844 .addReg(AArch64::X16)
2845 .addReg(AArch64::X16)
2850 emitAddImm(AArch64::X16,
Offset, AArch64::X17);
2851 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2853 emitPAC(
Key, AArch64::X16, DiscReg);
2856void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2858 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2859 const MachineOperand &GAMO =
MI.getOperand(1);
2866 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).
addOperand(GAMC));
2867 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2868 .addReg(AuthResultReg)
2869 .addReg(AArch64::X17)
2872 MachineOperand GAHiOp(GAMO);
2873 MachineOperand GALoOp(GAMO);
2877 MCOperand GAMCHi, GAMCLo;
2882 MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).
addOperand(GAMCHi));
2884 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
2885 .addReg(AArch64::X17)
2886 .addReg(AArch64::X17)
2890 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
2891 .addReg(AuthResultReg)
2892 .addReg(AArch64::X17)
2899 UndefWeakSym = createTempSymbol(
"undef_weak");
2901 MCInstBuilder(AArch64::CBZX)
2902 .addReg(AuthResultReg)
2910 emitAUT(AuthKey, AuthResultReg, AArch64::X17);
2915 if (!STI->hasFPAC()) {
2916 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2917 AArch64PAuth::AuthCheckMethod::XPAC);
2919 emitMovXReg(DstReg, AuthResultReg);
2924AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2928 if (std::optional<uint16_t> BADisc =
2929 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2936void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
2940 switch (
MI->getOpcode()) {
2943 case AArch64::CBBAssertExt:
2947 case AArch64::CBHAssertExt:
2951 case AArch64::CBWPrr:
2954 case AArch64::CBXPrr:
2957 case AArch64::CBWPri:
2961 case AArch64::CBXPri:
2969 bool NeedsRegSwap =
false;
2970 bool NeedsImmDec =
false;
2971 bool NeedsImmInc =
false;
2973#define GET_CB_OPC(IsImm, Width, ImmCond, RegCond) \
2975 ? (Width == 32 ? AArch64::CB##ImmCond##Wri : AArch64::CB##ImmCond##Xri) \
2977 ? AArch64::CBB##RegCond##Wrr \
2978 : (Width == 16 ? AArch64::CBH##RegCond##Wrr \
2979 : (Width == 32 ? AArch64::CB##RegCond##Wrr \
2980 : AArch64::CB##RegCond##Xrr))))
2996 NeedsImmDec = IsImm;
3000 NeedsRegSwap = !IsImm;
3007 NeedsRegSwap = !IsImm;
3008 NeedsImmInc = IsImm;
3012 NeedsImmDec = IsImm;
3016 NeedsRegSwap = !IsImm;
3023 NeedsRegSwap = !IsImm;
3024 NeedsImmInc = IsImm;
3032 MCOperand Lhs, Rhs, Trgt;
3033 lowerOperand(
MI->getOperand(1), Lhs);
3034 lowerOperand(
MI->getOperand(2), Rhs);
3035 lowerOperand(
MI->getOperand(3), Trgt);
3039 assert(Lhs.
isReg() &&
"Expected register operand for CB");
3040 assert(Rhs.
isReg() &&
"Expected register operand for CB");
3043 }
else if (NeedsImmDec) {
3047 }
else if (NeedsImmInc) {
3057 "CB immediate operand out-of-bounds");
3060 EmitToStreamer(*OutStreamer, Inst);
3065#include "AArch64GenMCPseudoLowering.inc"
3067void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst) {
3074void AArch64AsmPrinter::emitInstruction(
const MachineInstr *
MI) {
3075 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->
getFeatureBits());
3080 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
3085 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
3086 EmitToStreamer(*OutStreamer, OutInst);
3090 if (
MI->getOpcode() == AArch64::ADRP) {
3091 for (
auto &Opd :
MI->operands()) {
3092 if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
3093 "swift_async_extendedFramePointerFlags") {
3094 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
3101 MCSymbol *LOHLabel = createTempSymbol(
"loh");
3103 LOHInstToLabel[
MI] = LOHLabel;
3107 AArch64TargetStreamer *TS =
3110 switch (
MI->getOpcode()) {
3113 "Unhandled tail call instruction");
3115 case AArch64::HINT: {
3120 if (CurrentPatchableFunctionEntrySym &&
3121 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
3123 int64_t
Imm =
MI->getOperand(0).getImm();
3124 if ((Imm & 32) && (Imm & 6)) {
3126 MCInstLowering.
Lower(
MI, Inst);
3127 EmitToStreamer(*OutStreamer, Inst);
3128 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
3129 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
3135 case AArch64::MOVMCSym: {
3136 Register DestReg =
MI->getOperand(0).getReg();
3137 const MachineOperand &MO_Sym =
MI->getOperand(1);
3138 MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
3139 MCOperand Hi_MCSym, Lo_MCSym;
3152 EmitToStreamer(*OutStreamer, MovZ);
3160 EmitToStreamer(*OutStreamer, MovK);
3163 case AArch64::MOVIv2d_ns:
3171 if (STI->hasZeroCycleZeroingFPWorkaround() &&
3172 MI->getOperand(1).getImm() == 0) {
3174 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
3177 EmitToStreamer(*OutStreamer, TmpInst);
3182 case AArch64::DBG_VALUE:
3183 case AArch64::DBG_VALUE_LIST:
3185 SmallString<128> TmpStr;
3186 raw_svector_ostream OS(TmpStr);
3187 PrintDebugValueComment(
MI, OS);
3192 case AArch64::EMITBKEY: {
3194 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3195 ExceptionHandlingType != ExceptionHandling::ARM)
3198 if (getFunctionCFISectionType(*MF) == CFISection::None)
3205 case AArch64::EMITMTETAGGED: {
3207 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
3208 ExceptionHandlingType != ExceptionHandling::ARM)
3211 if (getFunctionCFISectionType(*MF) != CFISection::None)
3216 case AArch64::AUTx16x17: {
3218 const Register Scratch = AArch64::X17;
3221 MI->getOperand(1).getImm(),
MI->getOperand(2));
3223 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3224 MI->getDeactivationSymbol());
3228 case AArch64::AUTxMxN: {
3230 const Register Scratch =
MI->getOperand(1).getReg();
3233 MI->getOperand(4).getImm(),
MI->getOperand(5));
3235 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, std::nullopt,
3236 MI->getDeactivationSymbol());
3240 case AArch64::AUTPAC: {
3242 const Register Scratch = AArch64::X17;
3245 MI->getOperand(1).getImm(),
MI->getOperand(2));
3248 MI->getOperand(4).getImm(),
MI->getOperand(5));
3250 emitPtrauthAuthResign(Pointer, Scratch, AuthSchema, SignSchema,
3251 MI->getDeactivationSymbol());
3256 emitPtrauthSign(
MI);
3259 case AArch64::LOADauthptrstatic:
3260 LowerLOADauthptrstatic(*
MI);
3263 case AArch64::LOADgotPAC:
3264 case AArch64::MOVaddrPAC:
3265 LowerMOVaddrPAC(*
MI);
3268 case AArch64::LOADgotAUTH:
3269 LowerLOADgotAUTH(*
MI);
3274 emitPtrauthBranch(
MI);
3280 case AArch64::AUTH_TCRETURN:
3281 case AArch64::AUTH_TCRETURN_BTI: {
3284 const uint64_t Disc =
MI->getOperand(3).getImm();
3286 Register AddrDisc =
MI->getOperand(4).getReg();
3288 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
3290 emitPtrauthTailCallHardening(
MI);
3293 if (Callee == AddrDisc)
3300 bool AddrDiscIsImplicitDef =
3301 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
3302 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
3303 AddrDiscIsImplicitDef);
3304 emitBLRA(
false,
Key, Callee, DiscReg);
3308 case AArch64::TCRETURNri:
3309 case AArch64::TCRETURNrix16x17:
3310 case AArch64::TCRETURNrix17:
3311 case AArch64::TCRETURNrinotx16:
3312 case AArch64::TCRETURNriALL: {
3313 emitPtrauthTailCallHardening(
MI);
3315 recordIfImportCall(
MI);
3319 EmitToStreamer(*OutStreamer, TmpInst);
3322 case AArch64::TCRETURNdi: {
3323 emitPtrauthTailCallHardening(
MI);
3327 recordIfImportCall(
MI);
3331 EmitToStreamer(*OutStreamer, TmpInst);
3334 case AArch64::SpeculationBarrierISBDSBEndBB: {
3339 EmitToStreamer(*OutStreamer, TmpInstDSB);
3343 EmitToStreamer(*OutStreamer, TmpInstISB);
3346 case AArch64::SpeculationBarrierSBEndBB: {
3350 EmitToStreamer(*OutStreamer, TmpInstSB);
3353 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3360 const MachineOperand &MO_Sym =
MI->getOperand(0);
3361 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3362 MCOperand SymTLSDescLo12, SymTLSDesc;
3365 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3372 EmitToStreamer(*OutStreamer, Adrp);
3380 EmitToStreamer(*OutStreamer, Ldr);
3383 Add.setOpcode(AArch64::ADDXri);
3386 Add.addOperand(SymTLSDescLo12);
3388 EmitToStreamer(*OutStreamer,
Add);
3397 EmitToStreamer(*OutStreamer, Blraa);
3401 case AArch64::TLSDESC_CALLSEQ: {
3409 const MachineOperand &MO_Sym =
MI->getOperand(0);
3410 MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
3411 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
3415 MCInstLowering.
lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3422 EmitToStreamer(*OutStreamer, Adrp);
3425 if (STI->isTargetILP32()) {
3435 EmitToStreamer(*OutStreamer, Ldr);
3438 if (STI->isTargetILP32()) {
3439 Add.setOpcode(AArch64::ADDWri);
3443 Add.setOpcode(AArch64::ADDXri);
3447 Add.addOperand(SymTLSDescLo12);
3449 EmitToStreamer(*OutStreamer,
Add);
3454 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3456 EmitToStreamer(*OutStreamer, TLSDescCall);
3464 EmitToStreamer(*OutStreamer, Blr);
3469 case AArch64::JumpTableDest32:
3470 case AArch64::JumpTableDest16:
3471 case AArch64::JumpTableDest8:
3472 LowerJumpTableDest(*OutStreamer, *
MI);
3475 case AArch64::BR_JumpTable:
3476 LowerHardenedBRJumpTable(*
MI);
3479 case AArch64::FMOVH0:
3480 case AArch64::FMOVS0:
3481 case AArch64::FMOVD0:
3485 case AArch64::MOPSMemoryCopyPseudo:
3486 case AArch64::MOPSMemoryMovePseudo:
3487 case AArch64::MOPSMemorySetPseudo:
3488 case AArch64::MOPSMemorySetTaggingPseudo:
3489 LowerMOPS(*OutStreamer, *
MI);
3492 case TargetOpcode::STACKMAP:
3493 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3495 case TargetOpcode::PATCHPOINT:
3496 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3498 case TargetOpcode::STATEPOINT:
3499 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3501 case TargetOpcode::FAULTING_OP:
3502 return LowerFAULTING_OP(*
MI);
3504 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3505 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3508 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3509 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3512 case TargetOpcode::PATCHABLE_TAIL_CALL:
3513 LowerPATCHABLE_TAIL_CALL(*
MI);
3515 case TargetOpcode::PATCHABLE_EVENT_CALL:
3516 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3517 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3518 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3520 case AArch64::KCFI_CHECK:
3521 LowerKCFI_CHECK(*
MI);
3524 case AArch64::HWASAN_CHECK_MEMACCESS:
3525 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3526 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3527 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3528 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3531 case AArch64::SEH_StackAlloc:
3535 case AArch64::SEH_SaveFPLR:
3539 case AArch64::SEH_SaveFPLR_X:
3540 assert(
MI->getOperand(0).getImm() < 0 &&
3541 "Pre increment SEH opcode must have a negative offset");
3545 case AArch64::SEH_SaveReg:
3547 MI->getOperand(1).getImm());
3550 case AArch64::SEH_SaveReg_X:
3551 assert(
MI->getOperand(1).getImm() < 0 &&
3552 "Pre increment SEH opcode must have a negative offset");
3554 -
MI->getOperand(1).getImm());
3557 case AArch64::SEH_SaveRegP:
3558 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3559 MI->getOperand(0).getImm() <= 28) {
3560 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3561 "Register paired with LR must be odd");
3563 MI->getOperand(2).getImm());
3566 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3567 "Non-consecutive registers not allowed for save_regp");
3569 MI->getOperand(2).getImm());
3572 case AArch64::SEH_SaveRegP_X:
3573 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3574 "Non-consecutive registers not allowed for save_regp_x");
3575 assert(
MI->getOperand(2).getImm() < 0 &&
3576 "Pre increment SEH opcode must have a negative offset");
3578 -
MI->getOperand(2).getImm());
3581 case AArch64::SEH_SaveFReg:
3583 MI->getOperand(1).getImm());
3586 case AArch64::SEH_SaveFReg_X:
3587 assert(
MI->getOperand(1).getImm() < 0 &&
3588 "Pre increment SEH opcode must have a negative offset");
3590 -
MI->getOperand(1).getImm());
3593 case AArch64::SEH_SaveFRegP:
3594 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3595 "Non-consecutive registers not allowed for save_regp");
3597 MI->getOperand(2).getImm());
3600 case AArch64::SEH_SaveFRegP_X:
3601 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3602 "Non-consecutive registers not allowed for save_regp_x");
3603 assert(
MI->getOperand(2).getImm() < 0 &&
3604 "Pre increment SEH opcode must have a negative offset");
3606 -
MI->getOperand(2).getImm());
3609 case AArch64::SEH_SetFP:
3613 case AArch64::SEH_AddFP:
3617 case AArch64::SEH_Nop:
3621 case AArch64::SEH_PrologEnd:
3625 case AArch64::SEH_EpilogStart:
3629 case AArch64::SEH_EpilogEnd:
3633 case AArch64::SEH_PACSignLR:
3637 case AArch64::SEH_SaveAnyRegI:
3638 assert(
MI->getOperand(1).getImm() <= 1008 &&
3639 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3641 MI->getOperand(1).getImm());
3644 case AArch64::SEH_SaveAnyRegIP:
3645 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3646 "Non-consecutive registers not allowed for save_any_reg");
3647 assert(
MI->getOperand(2).getImm() <= 1008 &&
3648 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3650 MI->getOperand(2).getImm());
3653 case AArch64::SEH_SaveAnyRegQP:
3654 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3655 "Non-consecutive registers not allowed for save_any_reg");
3656 assert(
MI->getOperand(2).getImm() >= 0 &&
3657 "SaveAnyRegQP SEH opcode offset must be non-negative");
3658 assert(
MI->getOperand(2).getImm() <= 1008 &&
3659 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3661 MI->getOperand(2).getImm());
3664 case AArch64::SEH_SaveAnyRegQPX:
3665 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3666 "Non-consecutive registers not allowed for save_any_reg");
3667 assert(
MI->getOperand(2).getImm() < 0 &&
3668 "SaveAnyRegQPX SEH opcode offset must be negative");
3669 assert(
MI->getOperand(2).getImm() >= -1008 &&
3670 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3672 -
MI->getOperand(2).getImm());
3675 case AArch64::SEH_AllocZ:
3676 assert(
MI->getOperand(0).getImm() >= 0 &&
3677 "AllocZ SEH opcode offset must be non-negative");
3678 assert(
MI->getOperand(0).getImm() <= 255 &&
3679 "AllocZ SEH opcode offset must fit into 8 bits");
3683 case AArch64::SEH_SaveZReg:
3684 assert(
MI->getOperand(1).getImm() >= 0 &&
3685 "SaveZReg SEH opcode offset must be non-negative");
3686 assert(
MI->getOperand(1).getImm() <= 255 &&
3687 "SaveZReg SEH opcode offset must fit into 8 bits");
3689 MI->getOperand(1).getImm());
3692 case AArch64::SEH_SavePReg:
3693 assert(
MI->getOperand(1).getImm() >= 0 &&
3694 "SavePReg SEH opcode offset must be non-negative");
3695 assert(
MI->getOperand(1).getImm() <= 255 &&
3696 "SavePReg SEH opcode offset must fit into 8 bits");
3698 MI->getOperand(1).getImm());
3703 recordIfImportCall(
MI);
3705 MCInstLowering.
Lower(
MI, TmpInst);
3706 EmitToStreamer(*OutStreamer, TmpInst);
3709 case AArch64::CBWPri:
3710 case AArch64::CBXPri:
3711 case AArch64::CBBAssertExt:
3712 case AArch64::CBHAssertExt:
3713 case AArch64::CBWPrr:
3714 case AArch64::CBXPrr:
3715 emitCBPseudoExpansion(
MI);
3719 if (emitDeactivationSymbolRelocation(
MI->getDeactivationSymbol()))
3724 MCInstLowering.
Lower(
MI, TmpInst);
3725 EmitToStreamer(*OutStreamer, TmpInst);
3728void AArch64AsmPrinter::recordIfImportCall(
3729 const llvm::MachineInstr *BranchInst) {
3730 if (!EnableImportCallOptimization)
3734 if (GV && GV->hasDLLImportStorageClass()) {
3735 auto *CallSiteSymbol = MMI->getContext().createNamedTempSymbol(
"impcall");
3740 .push_back({CallSiteSymbol, CalledSymbol});
3744void AArch64AsmPrinter::emitMachOIFuncStubBody(
Module &M,
const GlobalIFunc &GI,
3745 MCSymbol *LazyPointer) {
3762 EmitToStreamer(Adrp);
3770 MCOperand SymPageOff;
3777 EmitToStreamer(Ldr);
3780 EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
3781 .addReg(AArch64::X16)
3782 .addReg(AArch64::X16)
3785 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3787 .addReg(AArch64::X16));
3790void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3791 const GlobalIFunc &GI,
3792 MCSymbol *LazyPointer) {
3824 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3825 .addReg(AArch64::SP)
3826 .addReg(AArch64::FP)
3827 .addReg(AArch64::LR)
3828 .addReg(AArch64::SP)
3831 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3832 .addReg(AArch64::FP)
3833 .addReg(AArch64::SP)
3837 for (
int I = 0;
I != 4; ++
I)
3838 EmitToStreamer(MCInstBuilder(AArch64::STPXpre)
3839 .addReg(AArch64::SP)
3840 .addReg(AArch64::X1 + 2 *
I)
3841 .addReg(AArch64::X0 + 2 *
I)
3842 .addReg(AArch64::SP)
3845 for (
int I = 0;
I != 4; ++
I)
3846 EmitToStreamer(MCInstBuilder(AArch64::STPDpre)
3847 .addReg(AArch64::SP)
3848 .addReg(AArch64::D1 + 2 *
I)
3849 .addReg(AArch64::D0 + 2 *
I)
3850 .addReg(AArch64::SP)
3854 MCInstBuilder(AArch64::BL)
3867 EmitToStreamer(Adrp);
3875 MCOperand SymPageOff;
3882 EmitToStreamer(Ldr);
3885 EmitToStreamer(MCInstBuilder(AArch64::STRXui)
3886 .addReg(AArch64::X0)
3887 .addReg(AArch64::X16)
3890 EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
3891 .addReg(AArch64::X16)
3892 .addReg(AArch64::X0)
3896 for (
int I = 3;
I != -1; --
I)
3897 EmitToStreamer(MCInstBuilder(AArch64::LDPDpost)
3898 .addReg(AArch64::SP)
3899 .addReg(AArch64::D1 + 2 *
I)
3900 .addReg(AArch64::D0 + 2 *
I)
3901 .addReg(AArch64::SP)
3904 for (
int I = 3;
I != -1; --
I)
3905 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3906 .addReg(AArch64::SP)
3907 .addReg(AArch64::X1 + 2 *
I)
3908 .addReg(AArch64::X0 + 2 *
I)
3909 .addReg(AArch64::SP)
3912 EmitToStreamer(MCInstBuilder(AArch64::LDPXpost)
3913 .addReg(AArch64::SP)
3914 .addReg(AArch64::FP)
3915 .addReg(AArch64::LR)
3916 .addReg(AArch64::SP)
3919 EmitToStreamer(MCInstBuilder(TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3921 .addReg(AArch64::X16));
3924const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
3925 const Constant *BaseCV,
3935char AArch64AsmPrinter::ID = 0;
3938 "AArch64 Assembly Printer",
false,
false)
3942LLVMInitializeAArch64AsmPrinter() {
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)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static bool printAsmMRegister(const X86AsmPrinter &P, const MachineOperand &MO, char Mode, raw_ostream &O)
static const AArch64AuthMCExpr * create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, bool HasAddressDiversity, MCContext &Ctx, SMLoc Loc=SMLoc())
const SetOfInstructions & getLOHRelated() const
unsigned getJumpTableEntrySize(int Idx) const
MCSymbol * getJumpTableEntryPCRelSymbol(int Idx) const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
std::optional< std::string > getOutliningStyle() const
const MILOHContainer & getLOHContainer() const
void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym)
bool shouldSignWithBKey() const
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=AArch64::NoRegAltName)
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MCSymbol * GetGlobalValueSymbol(const GlobalValue *GV, unsigned TargetFlags) const
void Lower(const MachineInstr *MI, MCInst &OutMI) const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
virtual void emitARM64WinCFISaveRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset)
virtual void emitAttributesSubsection(StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, AArch64BuildAttributes::SubsectionType ParameterType)
Build attributes implementation.
virtual void emitARM64WinCFISavePReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPACSignLR()
virtual void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFIAllocStack(unsigned Size)
virtual void emitARM64WinCFISaveFPLRX(int Offset)
virtual void emitARM64WinCFIAllocZ(int Offset)
virtual void emitDirectiveVariantPCS(MCSymbol *Symbol)
Callback used to implement the .variant_pcs directive.
virtual void emitARM64WinCFIAddFP(unsigned Size)
virtual void emitARM64WinCFISaveFPLR(int Offset)
virtual void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset)
virtual void emitARM64WinCFISetFP()
virtual void emitARM64WinCFIEpilogEnd()
virtual void emitARM64WinCFISaveZReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFIPrologEnd()
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFINop()
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
virtual void emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, std::string String)
virtual void emitARM64WinCFIEpilogStart()
virtual void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset)
void setPreservesAll()
Set by analyses that do not transform their input at all.
const T & front() const
front - Get the first element.
bool empty() const
empty - Check if the array is empty.
This class is intended to be used as a driving class for all asm writers.
virtual void emitGlobalAlias(const Module &M, const GlobalAlias &GA)
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
virtual const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
virtual void emitXXStructor(const DataLayout &DL, const Constant *CV)
Targets can override this to change how global constants that are part of a C++ static/global constru...
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
virtual const MCExpr * lowerBlockAddressConstant(const BlockAddress &BA)
Lower the specified BlockAddress to an MCExpr.
Function * getFunction() const
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
@ AddrDiscriminator_CtorsDtors
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
ConstantInt * getKey() const
The Key ID, an i32 constant.
Constant * getDeactivationSymbol() const
bool hasAddressDiscriminator() const
Whether there is any non-null address discriminator.
ConstantInt * getDiscriminator() const
The integer discriminator, an i64 constant, or 0.
void recordFaultingOp(FaultKind FaultTy, const MCSymbol *FaultingLabel, const MCSymbol *HandlerLabel)
void serializeToFaultMapSection()
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const Constant * getAliasee() const
const Constant * getResolver() const
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
bool hasLocalLinkage() const
bool hasExternalWeakLinkage() const
Type * getValueType() const
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
LLVM_ABI MCSymbol * createLinkerPrivateSymbol(const Twine &Name)
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
MCSection * getDataSection() const
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
static constexpr unsigned NonUniqueID
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
virtual void emitCFIBKeyFrame()
virtual bool popSection()
Restore the current and previous section from the section stack.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc={})
Record a relocation described by the .reloc directive.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCFIMTETaggedFrame()
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
void pushSection()
Save the current and previous section on the section stack.
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
MCSection * getCurrentSectionOnly() const
void emitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ....
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
const MCSymbol * getAddSym() const
int64_t getConstant() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
CalledGlobalInfo tryGetCalledGlobal(const MachineInstr *MI) const
Tries to get the global and target flags for a call site, if the instruction is a call to a global.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
ExprStubListTy getAuthGVStubList()
ExprStubListTy getAuthGVStubList()
unsigned getSubReg() const
static MachineOperand CreateMCSymbol(MCSymbol *Sym, unsigned TargetFlags=0)
const GlobalValue * getGlobal() const
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const BlockAddress * getBlockAddress() const
void setOffset(int64_t Offset)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
int64_t getOffset() const
Return the offset from the symbol in this operand.
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static SectionKind getMetadata()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void push_back(const T &Elt)
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
virtual MCSection * getSectionForJumpTable(const Function &F, const TargetMachine &TM) const
Primary interface to the complete machine description for the target machine.
MCRegister getRegister(unsigned i) const
Return the specified register in the class.
bool regsOverlap(Register RegA, Register RegB) const
Returns true if the two registers are equal or alias each other.
Triple - Helper class for working with autoconf configuration names.
bool isFunctionTy() const
True if this is an instance of FunctionType.
LLVM 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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
scope_exit(Callable) -> scope_exit< Callable >
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
std::string utostr(uint64_t X, bool isNeg=false)
static unsigned getBranchOpcodeForKey(bool IsCall, AArch64PACKey::ID K, bool Zero)
Return B(L)RA opcode to be used for an authenticated branch or call using the given key,...
Target & getTheAArch64leTarget()
auto dyn_cast_or_null(const Y &Val)
Target & getTheAArch64_32Target()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Target & getTheARM64_32Target()
static MCRegister getXRegFromWReg(MCRegister Reg)
Target & getTheARM64Target()
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static MCRegister getXRegFromXRegTuple(MCRegister RegTuple)
static unsigned getPACOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return PAC opcode to be used for a ptrauth sign using the given key, or its PAC*Z variant that doesn'...
static MCRegister getWRegFromXReg(MCRegister Reg)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static unsigned getAUTOpcodeForKey(AArch64PACKey::ID K, bool Zero)
Return AUT opcode to be used for a ptrauth auth using the given key, or its AUT*Z variant that doesn'...
@ MCSA_WeakAntiDep
.weak_anti_dep (COFF)
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
Implement std::hash so that hash_code can be used in STL containers.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...