80 cl::desc(
"Check pointer authentication auth/resign failures"),
83#define DEBUG_TYPE "asm-printer"
91 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
93 unsigned InstsEmitted;
95 bool EnableImportCallOptimization =
false;
97 SectionToImportedFunctionCalls;
102 AArch64AsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
104 MCInstLowering(OutContext, *
this), FM(*
this) {}
124 const MCSymbol *BranchLabel)
const override;
147 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
149 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
150 HwasanMemaccessTuple;
151 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
154 void emitHwasanMemaccessSymbols(
Module &M);
161 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
169 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
176 std::optional<AArch64PACKey::ID> PACKey,
201 bool MayUseAddrAsScratch =
false);
220 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
233 void emitFunctionHeaderComment()
override;
241 if (
auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
242 PSI = &PSIW->getPSI();
244 getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
245 SDPI = &SDPIW->getStaticDataProfileInfo();
252 if (STI->isTargetCOFF()) {
311 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
313 MInstToMCSymbol LOHInstToLabel;
316 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
336void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
339 if (
TT.isOSBinFormatCOFF()) {
340 emitCOFFFeatureSymbol(M);
341 emitCOFFReplaceableFunctionData(M);
343 if (
M.getModuleFlag(
"import-call-optimization"))
344 EnableImportCallOptimization =
true;
347 if (!
TT.isOSBinFormatELF())
355 unsigned BAFlags = 0;
356 unsigned GNUFlags = 0;
357 if (
const auto *BTE = mdconst::extract_or_null<ConstantInt>(
358 M.getModuleFlag(
"branch-target-enforcement"))) {
359 if (!BTE->isZero()) {
360 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
365 if (
const auto *GCS = mdconst::extract_or_null<ConstantInt>(
366 M.getModuleFlag(
"guarded-control-stack"))) {
367 if (!GCS->isZero()) {
368 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
373 if (
const auto *Sign = mdconst::extract_or_null<ConstantInt>(
374 M.getModuleFlag(
"sign-return-address"))) {
375 if (!Sign->isZero()) {
376 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
382 if (
const auto *PAP = mdconst::extract_or_null<ConstantInt>(
383 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
384 PAuthABIPlatform = PAP->getZExtValue();
388 if (
const auto *PAV = mdconst::extract_or_null<ConstantInt>(
389 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
390 PAuthABIVersion = PAV->getZExtValue();
394 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
396 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
399void AArch64AsmPrinter::emitFunctionHeaderComment() {
402 if (OutlinerString != std::nullopt)
403 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
406void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
409 if (
F.hasFnAttribute(
"patchable-function-entry")) {
411 if (
F.getFnAttribute(
"patchable-function-entry")
413 .getAsInteger(10, Num))
419 emitSled(
MI, SledKind::FUNCTION_ENTER);
422void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
423 emitSled(
MI, SledKind::FUNCTION_EXIT);
426void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
427 emitSled(
MI, SledKind::TAIL_CALL);
430void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
431 static const int8_t NoopsInSledCount = 7;
452 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
453 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
454 OutStreamer->emitLabel(CurSled);
455 auto Target = OutContext.createTempSymbol();
460 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::B).addImm(8));
462 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
463 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
465 OutStreamer->emitLabel(
Target);
466 recordSled(CurSled,
MI, Kind, 2);
469void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
474 PAuthABIPlatform = (
uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
475 PAuthABIVersion = (
uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
477 if (PAuthABIPlatform || PAuthABIVersion) {
481 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
482 AArch64BuildAttributes::SubsectionType::ULEB128);
486 PAuthABIPlatform,
"");
500 if (BTIValue || PACValue || GCSValue) {
504 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
505 AArch64BuildAttributes::SubsectionType::ULEB128);
533void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
535 auto &
O = *OutStreamer;
536 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
537 O.emitLabel(CurSled);
538 bool MachO =
TM.getTargetTriple().isOSBinFormatMachO();
540 OutContext.getOrCreateSymbol(
541 Twine(MachO ?
"_" :
"") +
542 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
545 O.AddComment(
"Begin XRay typed event");
557 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
558 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
559 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
565 O.AddComment(
"End XRay typed event");
573 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
575 O.AddComment(
"Begin XRay custom event");
583 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
584 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
586 O.AddComment(
"End XRay custom event");
594 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
600 assert(std::next(
MI.getIterator())->isCall() &&
601 "KCFI_CHECK not followed by a call instruction");
602 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
603 "KCFI_CHECK call target doesn't match call operand");
607 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
608 if (AddrReg == AArch64::XZR) {
612 emitMovXReg(AddrReg, AArch64::XZR);
618 for (
auto &Reg : ScratchRegs) {
624 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
625 "Invalid scratch registers for KCFI_CHECK");
629 int64_t PrefixNops = 0;
632 .getFnAttribute(
"patchable-function-prefix")
634 .getAsInteger(10, PrefixNops);
638 .addReg(ScratchRegs[0])
640 .addImm(-(PrefixNops * 4 + 4)));
644 const int64_t
Type =
MI.getOperand(1).getImm();
645 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
646 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
650 .addReg(AArch64::WZR)
651 .addReg(ScratchRegs[0])
652 .addReg(ScratchRegs[1])
656 EmitToStreamer(*OutStreamer,
666 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
670 AddrIndex = AddrReg - AArch64::X0;
680 assert(AddrIndex < 31 && TypeIndex < 31);
682 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
683 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BRK).addImm(ESR));
684 OutStreamer->emitLabel(
Pass);
687void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
695 if (Reg == AArch64::XZR)
699 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
701 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
702 uint32_t AccessInfo =
MI.getOperand(1).getImm();
704 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
706 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
707 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
709 MCSymbol *&
Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
710 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
713 if (!
TM.getTargetTriple().isOSBinFormatELF())
716 std::string SymName =
"__hwasan_check_x" + utostr(Reg - AArch64::X0) +
"_" +
719 SymName +=
"_fixed_" + utostr(FixedShadowOffset);
721 SymName +=
"_short_v2";
722 Sym = OutContext.getOrCreateSymbol(SymName);
725 EmitToStreamer(*OutStreamer,
730void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
731 if (HwasanMemaccessSymbols.empty())
736 std::unique_ptr<MCSubtargetInfo> STI(
737 TM.getTarget().createMCSubtargetInfo(
TT.str(),
"",
""));
738 assert(STI &&
"Unable to create subtarget info");
742 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
744 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
751 for (
auto &
P : HwasanMemaccessSymbols) {
752 unsigned Reg = std::get<0>(
P.first);
753 bool IsShort = std::get<1>(
P.first);
754 uint32_t AccessInfo = std::get<2>(
P.first);
755 bool IsFixedShadow = std::get<3>(
P.first);
756 uint64_t FixedShadowOffset = std::get<4>(
P.first);
758 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
761 bool HasMatchAllTag =
770 OutStreamer->switchSection(OutContext.getELFSection(
778 OutStreamer->emitLabel(
Sym);
781 .addReg(AArch64::X16)
791 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
793 .addReg(AArch64::W16)
794 .addReg(AArch64::X17)
795 .addReg(AArch64::X16)
800 .addReg(AArch64::W16)
801 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
802 .addReg(AArch64::X16)
808 .addReg(AArch64::XZR)
809 .addReg(AArch64::X16)
812 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
816 HandleMismatchOrPartialSym, OutContext)));
817 MCSymbol *ReturnSym = OutContext.createTempSymbol();
818 OutStreamer->emitLabel(ReturnSym);
819 EmitToStreamer(
MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
820 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
822 if (HasMatchAllTag) {
824 .addReg(AArch64::X17)
829 .addReg(AArch64::XZR)
830 .addReg(AArch64::X17)
841 .addReg(AArch64::WZR)
842 .addReg(AArch64::W16)
845 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
852 .addReg(AArch64::X17)
857 .addReg(AArch64::X17)
858 .addReg(AArch64::X17)
862 .addReg(AArch64::WZR)
863 .addReg(AArch64::W16)
864 .addReg(AArch64::W17)
872 .addReg(AArch64::X16)
876 .addReg(AArch64::W16)
877 .addReg(AArch64::X16)
881 .addReg(AArch64::XZR)
882 .addReg(AArch64::X16)
890 OutStreamer->emitLabel(HandleMismatchSym);
905 if (Reg != AArch64::X0)
906 emitMovXReg(AArch64::X0, Reg);
913 EmitToStreamer(
MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
919 .addReg(AArch64::X16)
924 .addReg(AArch64::X16)
925 .addReg(AArch64::X16)
929 EmitToStreamer(
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
937 const MCExpr *StubAuthPtrRef) {
940 OutStreamer.
emitValue(StubAuthPtrRef, 8);
943void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
944 emitHwasanMemaccessSymbols(M);
947 if (
TT.isOSBinFormatMachO()) {
954 if (!Stubs.empty()) {
956 OutStreamer->switchSection(
959 emitAlignment(
Align(8));
961 for (
const auto &Stub : Stubs)
964 OutStreamer->addBlankLine();
972 OutStreamer->emitSubsectionsViaSymbols();
975 if (
TT.isOSBinFormatELF()) {
981 if (!Stubs.empty()) {
984 emitAlignment(
Align(8));
986 for (
const auto &Stub : Stubs)
989 OutStreamer->addBlankLine();
999 const auto *PtrAuthELFGOTFlag = mdconst::extract_or_null<ConstantInt>(
1000 M.getModuleFlag(
"ptrauth-elf-got"));
1001 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1003 if (!GV.use_empty() && isa<Function>(GV) &&
1004 !GV.getName().starts_with(
"llvm."))
1005 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1010 FM.serializeToFaultMapSection();
1014 if (EnableImportCallOptimization &&
TT.isOSBinFormatCOFF()) {
1015 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1018 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1019 OutStreamer->emitBytes(
StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1030 for (
auto &[Section, CallsToImportedFuncs] :
1031 SectionToImportedFunctionCalls) {
1033 sizeof(
uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1034 OutStreamer->emitInt32(SectionSize);
1035 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1036 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1038 OutStreamer->emitInt32(0x13);
1039 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1040 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1046void AArch64AsmPrinter::emitLOHs() {
1049 for (
const auto &
D : AArch64FI->getLOHContainer()) {
1051 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1052 assert(LabelIt != LOHInstToLabel.end() &&
1053 "Label hasn't been inserted for LOH related instruction");
1056 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1061void AArch64AsmPrinter::emitFunctionBodyEnd() {
1062 if (!AArch64FI->getLOHRelated().empty())
1067MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1071 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
1072 return OutContext.getOrCreateSymbol(
1073 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1074 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
1079void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1097 PrintSymbolOperand(MO, O);
1108bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1132bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1135 assert(MO.
isReg() &&
"Should only get here with a register!");
1145bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1154 if (ExtraCode && ExtraCode[0]) {
1155 if (ExtraCode[1] != 0)
1158 switch (ExtraCode[0]) {
1166 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1180 switch (ExtraCode[0]) {
1182 RC = &AArch64::FPR8RegClass;
1185 RC = &AArch64::FPR16RegClass;
1188 RC = &AArch64::FPR32RegClass;
1191 RC = &AArch64::FPR64RegClass;
1194 RC = &AArch64::FPR128RegClass;
1197 RC = &AArch64::ZPRRegClass;
1202 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1215 if (AArch64::GPR32allRegClass.
contains(Reg) ||
1216 AArch64::GPR64allRegClass.
contains(Reg))
1220 if (AArch64::GPR64x8ClassRegClass.
contains(Reg))
1223 unsigned AltName = AArch64::NoRegAltName;
1225 if (AArch64::ZPRRegClass.
contains(Reg)) {
1226 RegClass = &AArch64::ZPRRegClass;
1227 }
else if (AArch64::PPRRegClass.
contains(Reg)) {
1228 RegClass = &AArch64::PPRRegClass;
1229 }
else if (AArch64::PNRRegClass.
contains(Reg)) {
1230 RegClass = &AArch64::PNRRegClass;
1232 RegClass = &AArch64::FPR128RegClass;
1233 AltName = AArch64::vreg;
1237 return printAsmRegInClass(MO, RegClass, AltName, O);
1244bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1246 const char *ExtraCode,
1248 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1252 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1257void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1259 unsigned NOps =
MI->getNumOperands();
1261 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1263 OS <<
MI->getDebugVariable()->getName();
1266 assert(
MI->isIndirectDebugValue());
1268 for (
unsigned I = 0, E = std::distance(
MI->debug_operands().begin(),
1269 MI->debug_operands().end());
1283 if (JumpTableIndices.
empty())
1286 const auto &
F = MF->getFunction();
1290 if (
TM.Options.EnableStaticDataPartitioning) {
1296 OutStreamer->switchSection(ReadOnlySec);
1299 for (
unsigned JTI : JumpTableIndices) {
1300 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1303 if (JTBBs.empty())
continue;
1305 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1307 OutStreamer->emitLabel(GetJTISymbol(JTI));
1309 const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1312 for (
auto *JTBB : JTBBs) {
1332AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1334 const MCSymbol *BranchLabel)
const {
1336 const auto Base = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1338 switch (AFI->getJumpTableEntrySize(JTI)) {
1340 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1343 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1346 EntrySize = codeview::JumpTableEntrySize::Int32;
1351 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1354void AArch64AsmPrinter::emitFunctionEntryLabel() {
1356 if (
TT.isOSBinFormatELF() &&
1358 MF->getFunction().getCallingConv() ==
1368 if (
TT.isWindowsArm64EC() && !MF->getFunction().hasLocalLinkage()) {
1373 OutStreamer->emitAssignment(
1380 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1381 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1387 MF->getFunction().getMetadata(
"arm64ec_unmangled_name", UnmangledNames);
1389 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1390 MCSymbol *UnmangledSym = MMI->getContext().getOrCreateSymbol(NameStr);
1391 if (std::optional<std::string> MangledName =
1394 MMI->getContext().getOrCreateSymbol(*MangledName);
1395 emitFunctionAlias(UnmangledSym, ECMangledSym);
1399 getSymbolFromMetadata(
"arm64ec_ecmangled_name"))
1400 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1404void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1406 if (
const auto *CPA = dyn_cast<ConstantPtrAuth>(CV))
1407 if (CPA->hasAddressDiscriminator() &&
1408 !CPA->hasSpecialAddressDiscriminator(
1411 "unexpected address discrimination value for ctors/dtors entry, only "
1412 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1421void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1423 if (
auto F = dyn_cast_or_null<Function>(GA.
getAliasee())) {
1428 if (
MDNode *
Node =
F->getMetadata(
"arm64ec_exp_name")) {
1429 StringRef ExpStr = cast<MDString>(
Node->getOperand(0))->getString();
1430 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1433 OutStreamer->beginCOFFSymbolDef(ExpSym);
1437 OutStreamer->endCOFFSymbolDef();
1439 OutStreamer->beginCOFFSymbolDef(
Sym);
1443 OutStreamer->endCOFFSymbolDef();
1445 OutStreamer->emitAssignment(
1464 Register DestReg =
MI.getOperand(0).getReg();
1465 Register ScratchReg =
MI.getOperand(1).getReg();
1467 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1468 Register TableReg =
MI.getOperand(2).getReg();
1469 Register EntryReg =
MI.getOperand(3).getReg();
1470 int JTIdx =
MI.getOperand(4).getIndex();
1471 int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
1481 Label = MF->getContext().createTempSymbol();
1482 AArch64FI->setJumpTableEntryInfo(JTIdx,
Size, Label);
1489 .addExpr(LabelExpr));
1494 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1495 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1496 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1502 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1506 .addImm(
Size == 1 ? 0 : 1));
1514 .addImm(
Size == 4 ? 0 : 2));
1517void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1519 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1521 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1522 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1541 assert(!AArch64FI->getJumpTableEntryPCRelSymbol(JTI) &&
1542 "unsupported compressed jump table");
1544 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1548 uint64_t MaxTableEntry = NumTableEntries - 1;
1549 if (isUInt<12>(MaxTableEntry)) {
1550 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXri)
1551 .addReg(AArch64::XZR)
1552 .addReg(AArch64::X16)
1553 .addImm(MaxTableEntry)
1556 emitMOVZ(AArch64::X17,
static_cast<uint16_t>(MaxTableEntry), 0);
1561 if ((MaxTableEntry >>
Offset) == 0)
1563 emitMOVK(AArch64::X17,
static_cast<uint16_t>(MaxTableEntry >>
Offset),
1566 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXrs)
1567 .addReg(AArch64::XZR)
1568 .addReg(AArch64::X16)
1569 .addReg(AArch64::X17)
1576 .addReg(AArch64::X16)
1577 .addReg(AArch64::X16)
1578 .addReg(AArch64::XZR)
1588 MCInstLowering.lowerOperand(JTMOHi, JTMCHi);
1589 MCInstLowering.lowerOperand(JTMOLo, JTMCLo);
1596 .addReg(AArch64::X17)
1597 .addReg(AArch64::X17)
1601 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::LDRSWroX)
1602 .addReg(AArch64::X16)
1603 .addReg(AArch64::X17)
1604 .addReg(AArch64::X16)
1608 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1610 AArch64FI->setJumpTableEntryInfo(JTI, 4, AdrLabel);
1615 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1618 .addReg(AArch64::X16)
1619 .addReg(AArch64::X17)
1620 .addReg(AArch64::X16)
1623 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1628 unsigned Opcode =
MI.getOpcode();
1630 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1632 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1633 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1634 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1635 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1636 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1637 if (Opcode == AArch64::MOPSMemorySetPseudo)
1638 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1639 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1640 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1643 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1644 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1646 for (
auto Op : Ops) {
1650 MCIB.addReg(
MI.getOperand(i++).getReg());
1651 MCIB.addReg(
MI.getOperand(i++).getReg());
1653 MCIB.addReg(
MI.getOperand(i++).getReg());
1655 MCIB.addReg(
MI.getOperand(i++).getReg());
1656 MCIB.addReg(
MI.getOperand(i++).getReg());
1657 MCIB.addReg(
MI.getOperand(i++).getReg());
1659 EmitToStreamer(OutStreamer, MCIB);
1668 MCSymbol *MILabel = Ctx.createTempSymbol();
1672 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1678 while (NumNOPBytes > 0) {
1679 if (MII ==
MBB.
end() || MII->isCall() ||
1680 MII->getOpcode() == AArch64::DBG_VALUE ||
1681 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1682 MII->getOpcode() == TargetOpcode::STACKMAP)
1689 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1690 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1698 MCSymbol *MILabel = Ctx.createTempSymbol();
1704 int64_t CallTarget = Opers.getCallTarget().getImm();
1705 unsigned EncodedBytes = 0;
1707 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1708 "High 16 bits of call target should be zero.");
1709 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1712 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1713 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1714 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1715 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1718 unsigned NumBytes = Opers.getNumPatchBytes();
1719 assert(NumBytes >= EncodedBytes &&
1720 "Patchpoint can't request size less than the length of a call.");
1721 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1722 "Invalid number of NOP bytes requested!");
1723 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1724 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1730 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1731 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1732 for (
unsigned i = 0; i < PatchBytes; i += 4)
1733 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1738 unsigned CallOpcode;
1739 switch (CallTarget.
getType()) {
1742 MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
1743 CallOpcode = AArch64::BL;
1747 CallOpcode = AArch64::BL;
1751 CallOpcode = AArch64::BLR;
1758 EmitToStreamer(OutStreamer,
1763 MCSymbol *MILabel = Ctx.createTempSymbol();
1768void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1777 unsigned OperandsBeginIdx = 4;
1780 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1784 FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
1787 MI.setOpcode(Opcode);
1795 lowerOperand(MO, Dest);
1796 MI.addOperand(Dest);
1806 .addReg(AArch64::XZR)
1811void AArch64AsmPrinter::emitMOVZ(
Register Dest,
uint64_t Imm,
unsigned Shift) {
1812 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1813 EmitToStreamer(*OutStreamer,
1820void AArch64AsmPrinter::emitMOVK(
Register Dest,
uint64_t Imm,
unsigned Shift) {
1821 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1822 EmitToStreamer(*OutStreamer,
1831 Register DestReg =
MI.getOperand(0).getReg();
1832 if (STI->hasZeroCycleZeroingFPR64() &&
1833 !STI->hasZeroCycleZeroingFPWorkaround() && STI->isNeonAvailable()) {
1835 if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
1836 DestReg = AArch64::D0 + (DestReg - AArch64::H0);
1837 else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
1838 DestReg = AArch64::D0 + (DestReg - AArch64::S0);
1840 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
1846 EmitToStreamer(*OutStreamer, MOVI);
1849 switch (
MI.getOpcode()) {
1851 case AArch64::FMOVH0:
1852 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1853 if (!STI->hasFullFP16())
1854 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1858 case AArch64::FMOVS0:
1863 case AArch64::FMOVD0:
1869 EmitToStreamer(*OutStreamer, FMov);
1876 bool MayUseAddrAsScratch) {
1877 assert(ScratchReg == AArch64::X16 || ScratchReg == AArch64::X17 ||
1878 !STI->isX16X17Safer());
1880 if (AddrDisc == AArch64::NoRegister)
1881 AddrDisc = AArch64::XZR;
1889 if (AddrDisc == AArch64::XZR) {
1890 emitMOVZ(ScratchReg, Disc, 0);
1897 assert(MayUseAddrAsScratch || ScratchReg != AddrDisc);
1898 bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17 ||
1899 !STI->isX16X17Safer();
1900 if (MayUseAddrAsScratch && AddrDiscIsSafe)
1901 ScratchReg = AddrDisc;
1903 emitMovXReg(ScratchReg, AddrDisc);
1905 emitMOVK(ScratchReg, Disc, 48);
1913void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
1946 if (Method == AuthCheckMethod::None)
1948 if (Method == AuthCheckMethod::DummyLoad) {
1953 assert(ShouldTrap && !OnFailure &&
"DummyLoad always traps on error");
1957 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
1958 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
1960 emitMovXReg(ScratchReg, TestedReg);
1962 if (Method == AuthCheckMethod::XPAC) {
1966 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
1971 assert(TestedReg == AArch64::LR &&
1972 "XPACHint mode is only compatible with checking the LR register");
1974 "XPACHint mode is only compatible with I-keys");
1980 .addReg(AArch64::XZR)
1990 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
2008 assert(!OnFailure &&
"Cannot specify OnFailure with ShouldTrap");
2011 EmitToStreamer(
MCInstBuilder(AArch64::BRK).addImm(0xc470 | Key));
2025 case AuthCheckMethod::XPACHint:
2028 case AuthCheckMethod::XPAC:
2030 emitMovXReg(TestedReg, ScratchReg);
2037 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
2057void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
2058 if (!AArch64FI->shouldSignReturnAddress(*MF))
2061 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
2062 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
2069 "Neither x16 nor x17 is available as a scratch register");
2072 emitPtrauthCheckAuthenticatedValue(
2073 AArch64::LR, ScratchReg, Key, LRCheckMethod,
2077void AArch64AsmPrinter::emitPtrauthAuthResign(
2080 std::optional<AArch64PACKey::ID> PACKey,
uint64_t PACDisc,
2082 const bool IsAUTPAC = PACKey.has_value();
2096 bool ShouldCheck =
true;
2098 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
2103 ShouldCheck = ShouldTrap =
false;
2110 ShouldCheck = ShouldTrap =
false;
2117 ShouldCheck = ShouldTrap =
true;
2122 assert(isUInt<16>(AUTDisc));
2123 Register AUTDiscReg = emitPtrauthDiscriminator(
2124 AUTDisc, AUTAddrDisc->
getReg(), Scratch, AUTAddrDisc->
isKill());
2125 bool AUTZero = AUTDiscReg == AArch64::XZR;
2136 EmitToStreamer(*OutStreamer, AUTInst);
2139 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2145 if (IsAUTPAC && !ShouldTrap)
2146 EndSym = createTempSymbol(
"resign_end_");
2148 emitPtrauthCheckAuthenticatedValue(AUTVal, Scratch, AUTKey,
2149 AArch64PAuth::AuthCheckMethod::XPAC,
2150 ShouldTrap, EndSym);
2160 assert(isUInt<16>(PACDisc));
2162 emitPtrauthDiscriminator(PACDisc, PACAddrDisc, Scratch);
2163 bool PACZero = PACDiscReg == AArch64::XZR;
2174 EmitToStreamer(*OutStreamer, PACInst);
2185 Register AddrDisc =
MI->getOperand(4).getReg();
2186 bool AddrDiscKilled =
MI->getOperand(4).isKill();
2190 Register ScratchReg = Val == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2191 assert(ScratchReg != AddrDisc &&
2192 "Neither X16 nor X17 is available as a scratch register");
2195 assert(isUInt<16>(Disc));
2196 Register DiscReg = emitPtrauthDiscriminator(
2197 Disc, AddrDisc, ScratchReg, AddrDiscKilled);
2198 bool IsZeroDisc = DiscReg == AArch64::XZR;
2209 EmitToStreamer(*OutStreamer, PACInst);
2212void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2213 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2214 unsigned BrTarget =
MI->getOperand(0).getReg();
2218 "Invalid auth call key");
2221 assert(isUInt<16>(Disc));
2223 unsigned AddrDisc =
MI->getOperand(3).getReg();
2229 if (BrTarget == AddrDisc)
2246 bool AddrDiscIsImplicitDef =
2247 IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17);
2248 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2249 AddrDiscIsImplicitDef);
2250 bool IsZeroDisc = DiscReg == AArch64::XZR;
2255 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
2257 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
2260 Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
2262 Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
2270 EmitToStreamer(*OutStreamer, BRInst);
2280 getDataLayout(),
Offset,
true);
2282 auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
2288 "cannot resolve target base/addend of ptrauth constant");
2306 "' out of range [0, " +
2312 if (!isUInt<16>(Disc)) {
2314 "' out of range [0, 0xFFFF]");
2323void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2324 unsigned DstReg =
MI.getOperand(0).getReg();
2326 const uint64_t KeyC =
MI.getOperand(2).getImm();
2328 "key is out of range [0, AArch64PACKey::LAST]");
2330 const uint64_t Disc =
MI.getOperand(3).getImm();
2331 assert(isUInt<16>(Disc) &&
2332 "constant discriminator is out of range [0, 0xffff]");
2341 if (
TM.getTargetTriple().isOSBinFormatELF()) {
2346 "non-zero offset for $auth_ptr$ stub slots is not supported");
2348 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym, Key, Disc);
2350 assert(
TM.getTargetTriple().isOSBinFormatMachO() &&
2351 "LOADauthptrstatic is implemented only for MachO/ELF");
2354 getObjFileLowering());
2357 "non-zero offset for $auth_ptr$ stub slots is not supported");
2359 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym, Key, Disc);
2368 MCInstLowering.lowerOperand(StubMOHi, StubMCHi);
2369 MCInstLowering.lowerOperand(StubMOLo, StubMCLo);
2382 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2383 const bool IsELFSignedGOT =
MI.getParent()
2386 ->hasELFSignedGOT();
2388 const uint64_t KeyC =
MI.getOperand(1).getImm();
2390 "key is out of range [0, AArch64PACKey::LAST]");
2392 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2393 const uint64_t Disc =
MI.getOperand(3).getImm();
2394 assert(isUInt<16>(Disc) &&
2395 "constant discriminator is out of range [0, 0xffff]");
2452 MCInstLowering.lowerOperand(GAMOHi, GAMCHi);
2453 MCInstLowering.lowerOperand(GAMOLo, GAMCLo);
2457 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2461 if (IsELFSignedGOT) {
2463 .addReg(AArch64::X17)
2464 .addReg(AArch64::X17)
2469 .addReg(AArch64::X16)
2470 .addReg(AArch64::X17)
2480 .addReg(AArch64::X16)
2481 .addReg(AArch64::X16)
2482 .addReg(AArch64::X17));
2484 if (!STI->hasFPAC()) {
2488 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2489 AArch64PAuth::AuthCheckMethod::XPAC,
2495 .addReg(AArch64::X16)
2496 .addReg(AArch64::X16)
2501 .addReg(AArch64::X16)
2502 .addReg(AArch64::X16)
2509 const bool IsNeg =
Offset < 0;
2510 if (isUInt<24>(AbsOffset)) {
2511 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2515 .addReg(AArch64::X16)
2516 .addReg(AArch64::X16)
2517 .addImm((AbsOffset >> BitPos) & 0xfff)
2522 EmitToStreamer(
MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2523 .addReg(AArch64::X17)
2524 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
2526 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
2527 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2528 uint64_t Shifted = UOffset >> BitPos;
2530 return Shifted != 0;
2531 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2532 if (((Shifted >>
I) & 0xffff) != 0xffff)
2536 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2537 emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
2540 .addReg(AArch64::X16)
2541 .addReg(AArch64::X16)
2542 .addReg(AArch64::X17)
2547 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2552 if (DiscReg != AArch64::XZR)
2554 EmitToStreamer(MIB);
2557void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2559 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2565 MCInstLowering.lowerOperand(GAMO, GAMC);
2569 .addReg(AuthResultReg)
2570 .addReg(AArch64::X17)
2579 MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
2580 MCInstLowering.lowerOperand(GALoOp, GAMCLo);
2586 .addReg(AArch64::X17)
2587 .addReg(AArch64::X17)
2592 .addReg(AuthResultReg)
2593 .addReg(AArch64::X17)
2600 UndefWeakSym = createTempSymbol(
"undef_weak");
2603 .addReg(AuthResultReg)
2612 .addReg(AuthResultReg)
2613 .addReg(AuthResultReg)
2614 .addReg(AArch64::X17));
2619 if (!STI->hasFPAC()) {
2623 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2624 AArch64PAuth::AuthCheckMethod::XPAC,
2628 emitMovXReg(DstReg, AuthResultReg);
2633AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2637 if (std::optional<uint16_t> BADisc =
2638 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2645void AArch64AsmPrinter::emitCBPseudoExpansion(
const MachineInstr *
MI) {
2647 bool Is32Bit =
false;
2649 switch (
MI->getOpcode()) {
2652 case AArch64::CBWPrr:
2655 case AArch64::CBXPrr:
2658 case AArch64::CBWPri:
2662 case AArch64::CBXPri:
2669 bool NeedsRegSwap =
false;
2670 bool NeedsImmDec =
false;
2671 bool NeedsImmInc =
false;
2680 MCOpC = IsImm ? (Is32Bit ? AArch64::CBEQWri : AArch64::CBEQXri)
2681 : (Is32Bit ? AArch64::CBEQWrr : AArch64::CBEQXrr);
2684 MCOpC = IsImm ? (Is32Bit ? AArch64::CBNEWri : AArch64::CBNEXri)
2685 : (Is32Bit ? AArch64::CBNEWrr : AArch64::CBNEXrr);
2688 MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2689 : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2690 NeedsImmDec = IsImm;
2693 MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2694 : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2695 NeedsRegSwap = !IsImm;
2698 MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
2699 : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
2702 MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
2703 : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
2704 NeedsRegSwap = !IsImm;
2705 NeedsImmInc = IsImm;
2708 MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2709 : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2710 NeedsImmDec = IsImm;
2713 MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2714 : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2715 NeedsRegSwap = !IsImm;
2718 MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
2719 : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
2722 MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
2723 : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
2724 NeedsRegSwap = !IsImm;
2725 NeedsImmInc = IsImm;
2733 lowerOperand(
MI->getOperand(1), Lhs);
2734 lowerOperand(
MI->getOperand(2), Rhs);
2735 lowerOperand(
MI->getOperand(3), Trgt);
2739 assert(Lhs.
isReg() &&
"Expected register operand for CB");
2740 assert(Rhs.
isReg() &&
"Expected register operand for CB");
2743 }
else if (NeedsImmDec) {
2747 }
else if (NeedsImmInc) {
2757 "CB immediate operand out-of-bounds");
2760 EmitToStreamer(*OutStreamer, Inst);
2765#include "AArch64GenMCPseudoLowering.inc"
2775 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
2780 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
2785 if (
MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
2786 EmitToStreamer(*OutStreamer, OutInst);
2790 if (
MI->getOpcode() == AArch64::ADRP) {
2791 for (
auto &Opd :
MI->operands()) {
2792 if (Opd.isSymbol() &&
StringRef(Opd.getSymbolName()) ==
2793 "swift_async_extendedFramePointerFlags") {
2794 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
2799 if (AArch64FI->getLOHRelated().count(
MI)) {
2801 MCSymbol *LOHLabel = createTempSymbol(
"loh");
2803 LOHInstToLabel[
MI] = LOHLabel;
2810 switch (
MI->getOpcode()) {
2813 "Unhandled tail call instruction");
2815 case AArch64::HINT: {
2820 if (CurrentPatchableFunctionEntrySym &&
2821 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
2822 MI == &MF->front().front()) {
2823 int64_t
Imm =
MI->getOperand(0).getImm();
2824 if ((Imm & 32) && (Imm & 6)) {
2826 MCInstLowering.Lower(
MI, Inst);
2827 EmitToStreamer(*OutStreamer, Inst);
2828 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
2829 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
2835 case AArch64::MOVMCSym: {
2836 Register DestReg =
MI->getOperand(0).getReg();
2844 MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
2845 MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
2852 EmitToStreamer(*OutStreamer, MovZ);
2860 EmitToStreamer(*OutStreamer, MovK);
2863 case AArch64::MOVIv2d_ns:
2871 if (STI->hasZeroCycleZeroingFPWorkaround() &&
2872 MI->getOperand(1).getImm() == 0) {
2874 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
2877 EmitToStreamer(*OutStreamer, TmpInst);
2882 case AArch64::DBG_VALUE:
2883 case AArch64::DBG_VALUE_LIST:
2887 PrintDebugValueComment(
MI,
OS);
2892 case AArch64::EMITBKEY: {
2894 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2895 ExceptionHandlingType != ExceptionHandling::ARM)
2898 if (getFunctionCFISectionType(*MF) == CFISection::None)
2905 case AArch64::EMITMTETAGGED: {
2907 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2908 ExceptionHandlingType != ExceptionHandling::ARM)
2911 if (getFunctionCFISectionType(*MF) != CFISection::None)
2916 case AArch64::AUTx16x17:
2917 emitPtrauthAuthResign(AArch64::X16,
2919 MI->getOperand(1).getImm(), &
MI->getOperand(2),
2920 AArch64::X17, std::nullopt, 0, 0);
2923 case AArch64::AUTxMxN:
2924 emitPtrauthAuthResign(
MI->getOperand(0).getReg(),
2926 MI->getOperand(4).getImm(), &
MI->getOperand(5),
2927 MI->getOperand(1).getReg(), std::nullopt, 0, 0);
2930 case AArch64::AUTPAC:
2931 emitPtrauthAuthResign(
2933 MI->getOperand(1).getImm(), &
MI->getOperand(2), AArch64::X17,
2935 MI->getOperand(4).getImm(),
MI->getOperand(5).getReg());
2939 emitPtrauthSign(
MI);
2942 case AArch64::LOADauthptrstatic:
2943 LowerLOADauthptrstatic(*
MI);
2946 case AArch64::LOADgotPAC:
2947 case AArch64::MOVaddrPAC:
2948 LowerMOVaddrPAC(*
MI);
2951 case AArch64::LOADgotAUTH:
2952 LowerLOADgotAUTH(*
MI);
2957 emitPtrauthBranch(
MI);
2963 case AArch64::AUTH_TCRETURN:
2964 case AArch64::AUTH_TCRETURN_BTI: {
2968 "Invalid auth key for tail-call return");
2970 const uint64_t Disc =
MI->getOperand(3).getImm();
2971 assert(isUInt<16>(Disc) &&
"Integer discriminator is too wide");
2973 Register AddrDisc =
MI->getOperand(4).getReg();
2975 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2977 emitPtrauthTailCallHardening(
MI);
2980 if (Callee == AddrDisc)
2987 bool AddrDiscIsImplicitDef =
2988 AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
2989 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
2990 AddrDiscIsImplicitDef);
2992 const bool IsZero = DiscReg == AArch64::XZR;
2993 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
2994 {AArch64::BRAB, AArch64::BRABZ}};
2997 TmpInst.
setOpcode(Opcodes[Key][IsZero]);
3001 EmitToStreamer(*OutStreamer, TmpInst);
3005 case AArch64::TCRETURNri:
3006 case AArch64::TCRETURNrix16x17:
3007 case AArch64::TCRETURNrix17:
3008 case AArch64::TCRETURNrinotx16:
3009 case AArch64::TCRETURNriALL: {
3010 emitPtrauthTailCallHardening(
MI);
3012 recordIfImportCall(
MI);
3016 EmitToStreamer(*OutStreamer, TmpInst);
3019 case AArch64::TCRETURNdi: {
3020 emitPtrauthTailCallHardening(
MI);
3023 MCInstLowering.lowerOperand(
MI->getOperand(0), Dest);
3024 recordIfImportCall(
MI);
3028 EmitToStreamer(*OutStreamer, TmpInst);
3031 case AArch64::SpeculationBarrierISBDSBEndBB: {
3036 EmitToStreamer(*OutStreamer, TmpInstDSB);
3040 EmitToStreamer(*OutStreamer, TmpInstISB);
3043 case AArch64::SpeculationBarrierSBEndBB: {
3047 EmitToStreamer(*OutStreamer, TmpInstSB);
3050 case AArch64::TLSDESC_AUTH_CALLSEQ: {
3062 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3063 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
3069 EmitToStreamer(*OutStreamer, Adrp);
3077 EmitToStreamer(*OutStreamer, Ldr);
3080 Add.setOpcode(AArch64::ADDXri);
3083 Add.addOperand(SymTLSDescLo12);
3085 EmitToStreamer(*OutStreamer,
Add);
3094 EmitToStreamer(*OutStreamer, Blraa);
3098 case AArch64::TLSDESC_CALLSEQ: {
3111 MCInstLowering.lowerOperand(MO_Sym,
Sym);
3112 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
3113 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
3119 EmitToStreamer(*OutStreamer, Adrp);
3122 if (STI->isTargetILP32()) {
3132 EmitToStreamer(*OutStreamer, Ldr);
3135 if (STI->isTargetILP32()) {
3136 Add.setOpcode(AArch64::ADDWri);
3140 Add.setOpcode(AArch64::ADDXri);
3144 Add.addOperand(SymTLSDescLo12);
3146 EmitToStreamer(*OutStreamer,
Add);
3151 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
3153 EmitToStreamer(*OutStreamer, TLSDescCall);
3161 EmitToStreamer(*OutStreamer, Blr);
3166 case AArch64::JumpTableDest32:
3167 case AArch64::JumpTableDest16:
3168 case AArch64::JumpTableDest8:
3169 LowerJumpTableDest(*OutStreamer, *
MI);
3172 case AArch64::BR_JumpTable:
3173 LowerHardenedBRJumpTable(*
MI);
3176 case AArch64::FMOVH0:
3177 case AArch64::FMOVS0:
3178 case AArch64::FMOVD0:
3182 case AArch64::MOPSMemoryCopyPseudo:
3183 case AArch64::MOPSMemoryMovePseudo:
3184 case AArch64::MOPSMemorySetPseudo:
3185 case AArch64::MOPSMemorySetTaggingPseudo:
3186 LowerMOPS(*OutStreamer, *
MI);
3189 case TargetOpcode::STACKMAP:
3190 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3192 case TargetOpcode::PATCHPOINT:
3193 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3195 case TargetOpcode::STATEPOINT:
3196 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3198 case TargetOpcode::FAULTING_OP:
3199 return LowerFAULTING_OP(*
MI);
3201 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3202 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3205 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3206 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3209 case TargetOpcode::PATCHABLE_TAIL_CALL:
3210 LowerPATCHABLE_TAIL_CALL(*
MI);
3212 case TargetOpcode::PATCHABLE_EVENT_CALL:
3213 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3214 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3215 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3217 case AArch64::KCFI_CHECK:
3218 LowerKCFI_CHECK(*
MI);
3221 case AArch64::HWASAN_CHECK_MEMACCESS:
3222 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3223 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3224 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3225 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3228 case AArch64::SEH_StackAlloc:
3232 case AArch64::SEH_SaveFPLR:
3236 case AArch64::SEH_SaveFPLR_X:
3237 assert(
MI->getOperand(0).getImm() < 0 &&
3238 "Pre increment SEH opcode must have a negative offset");
3242 case AArch64::SEH_SaveReg:
3244 MI->getOperand(1).getImm());
3247 case AArch64::SEH_SaveReg_X:
3248 assert(
MI->getOperand(1).getImm() < 0 &&
3249 "Pre increment SEH opcode must have a negative offset");
3251 -
MI->getOperand(1).getImm());
3254 case AArch64::SEH_SaveRegP:
3255 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3256 MI->getOperand(0).getImm() <= 28) {
3257 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3258 "Register paired with LR must be odd");
3260 MI->getOperand(2).getImm());
3263 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3264 "Non-consecutive registers not allowed for save_regp");
3266 MI->getOperand(2).getImm());
3269 case AArch64::SEH_SaveRegP_X:
3270 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3271 "Non-consecutive registers not allowed for save_regp_x");
3272 assert(
MI->getOperand(2).getImm() < 0 &&
3273 "Pre increment SEH opcode must have a negative offset");
3275 -
MI->getOperand(2).getImm());
3278 case AArch64::SEH_SaveFReg:
3280 MI->getOperand(1).getImm());
3283 case AArch64::SEH_SaveFReg_X:
3284 assert(
MI->getOperand(1).getImm() < 0 &&
3285 "Pre increment SEH opcode must have a negative offset");
3287 -
MI->getOperand(1).getImm());
3290 case AArch64::SEH_SaveFRegP:
3291 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3292 "Non-consecutive registers not allowed for save_regp");
3294 MI->getOperand(2).getImm());
3297 case AArch64::SEH_SaveFRegP_X:
3298 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3299 "Non-consecutive registers not allowed for save_regp_x");
3300 assert(
MI->getOperand(2).getImm() < 0 &&
3301 "Pre increment SEH opcode must have a negative offset");
3303 -
MI->getOperand(2).getImm());
3306 case AArch64::SEH_SetFP:
3310 case AArch64::SEH_AddFP:
3314 case AArch64::SEH_Nop:
3318 case AArch64::SEH_PrologEnd:
3322 case AArch64::SEH_EpilogStart:
3326 case AArch64::SEH_EpilogEnd:
3330 case AArch64::SEH_PACSignLR:
3334 case AArch64::SEH_SaveAnyRegQP:
3335 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3336 "Non-consecutive registers not allowed for save_any_reg");
3337 assert(
MI->getOperand(2).getImm() >= 0 &&
3338 "SaveAnyRegQP SEH opcode offset must be non-negative");
3339 assert(
MI->getOperand(2).getImm() <= 1008 &&
3340 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3342 MI->getOperand(2).getImm());
3345 case AArch64::SEH_SaveAnyRegQPX:
3346 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3347 "Non-consecutive registers not allowed for save_any_reg");
3348 assert(
MI->getOperand(2).getImm() < 0 &&
3349 "SaveAnyRegQPX SEH opcode offset must be negative");
3350 assert(
MI->getOperand(2).getImm() >= -1008 &&
3351 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3353 -
MI->getOperand(2).getImm());
3356 case AArch64::SEH_AllocZ:
3357 assert(
MI->getOperand(0).getImm() >= 0 &&
3358 "AllocZ SEH opcode offset must be non-negative");
3359 assert(
MI->getOperand(0).getImm() <= 255 &&
3360 "AllocZ SEH opcode offset must fit into 8 bits");
3364 case AArch64::SEH_SaveZReg:
3365 assert(
MI->getOperand(1).getImm() >= 0 &&
3366 "SaveZReg SEH opcode offset must be non-negative");
3367 assert(
MI->getOperand(1).getImm() <= 255 &&
3368 "SaveZReg SEH opcode offset must fit into 8 bits");
3370 MI->getOperand(1).getImm());
3373 case AArch64::SEH_SavePReg:
3374 assert(
MI->getOperand(1).getImm() >= 0 &&
3375 "SavePReg SEH opcode offset must be non-negative");
3376 assert(
MI->getOperand(1).getImm() <= 255 &&
3377 "SavePReg SEH opcode offset must fit into 8 bits");
3379 MI->getOperand(1).getImm());
3384 recordIfImportCall(
MI);
3386 MCInstLowering.Lower(
MI, TmpInst);
3387 EmitToStreamer(*OutStreamer, TmpInst);
3390 case AArch64::CBWPri:
3391 case AArch64::CBXPri:
3392 case AArch64::CBWPrr:
3393 case AArch64::CBXPrr:
3394 emitCBPseudoExpansion(
MI);
3400 MCInstLowering.Lower(
MI, TmpInst);
3401 EmitToStreamer(*OutStreamer, TmpInst);
3404void AArch64AsmPrinter::recordIfImportCall(
3406 if (!EnableImportCallOptimization)
3410 if (GV && GV->hasDLLImportStorageClass()) {
3411 auto *CallSiteSymbol = MMI->
getContext().createNamedTempSymbol(
"impcall");
3414 auto *CalledSymbol = MCInstLowering.GetGlobalValueSymbol(GV, OpFlags);
3416 .push_back({CallSiteSymbol, CalledSymbol});
3433 MCInstLowering.lowerOperand(
3438 EmitToStreamer(Adrp);
3447 MCInstLowering.lowerOperand(
3453 EmitToStreamer(Ldr);
3457 .addReg(AArch64::X16)
3458 .addReg(AArch64::X16)
3461 EmitToStreamer(
MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3466void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3501 .addReg(AArch64::SP)
3502 .addReg(AArch64::FP)
3503 .addReg(AArch64::LR)
3504 .addReg(AArch64::SP)
3508 .addReg(AArch64::FP)
3509 .addReg(AArch64::SP)
3513 for (
int I = 0;
I != 4; ++
I)
3515 .addReg(AArch64::SP)
3516 .addReg(AArch64::X1 + 2 *
I)
3517 .addReg(AArch64::X0 + 2 *
I)
3518 .addReg(AArch64::SP)
3521 for (
int I = 0;
I != 4; ++
I)
3523 .addReg(AArch64::SP)
3524 .addReg(AArch64::D1 + 2 *
I)
3525 .addReg(AArch64::D0 + 2 *
I)
3526 .addReg(AArch64::SP)
3538 MCInstLowering.lowerOperand(
3543 EmitToStreamer(Adrp);
3552 MCInstLowering.lowerOperand(
3558 EmitToStreamer(Ldr);
3562 .addReg(AArch64::X0)
3563 .addReg(AArch64::X16)
3567 .addReg(AArch64::X16)
3568 .addReg(AArch64::X0)
3572 for (
int I = 3;
I != -1; --
I)
3574 .addReg(AArch64::SP)
3575 .addReg(AArch64::D1 + 2 *
I)
3576 .addReg(AArch64::D0 + 2 *
I)
3577 .addReg(AArch64::SP)
3580 for (
int I = 3;
I != -1; --
I)
3582 .addReg(AArch64::SP)
3583 .addReg(AArch64::X1 + 2 *
I)
3584 .addReg(AArch64::X0 + 2 *
I)
3585 .addReg(AArch64::SP)
3589 .addReg(AArch64::SP)
3590 .addReg(AArch64::FP)
3591 .addReg(AArch64::LR)
3592 .addReg(AArch64::SP)
3595 EmitToStreamer(
MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3600const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV,
3603 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
3611char AArch64AsmPrinter::ID = 0;
3614 "AArch64 Assembly Printer",
false,
false)
3618LLVMInitializeAArch64AsmPrinter() {
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))
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
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")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_EXTERNAL_VISIBILITY
This file defines the DenseMap class.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
Register const TargetRegisterInfo * TRI
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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.
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())
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
std::optional< std::string > getOutliningStyle() 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.
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 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()
This implementation is used for AArch64 ELF targets (Linux in particular).
AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin.
Class for arbitrary precision integers.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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 emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
virtual const MCExpr * lowerConstantPtrAuth(const ConstantPtrAuth &CPA)
void emitXRayTable()
Emit a table with all XRay instrumentation points.
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 void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI, MCSymbol *LazyPointer)
virtual const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
virtual void SetupMachineFunction(MachineFunction &MF)
This should be called when a new MachineFunction is being processed from runOnMachineFunction.
void emitFunctionBody()
This method emits the body and trailer for a function.
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
virtual void emitEndOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the end of their file...
virtual void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI, MCSymbol *LazyPointer)
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
virtual bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const
virtual const MCSubtargetInfo * getIFuncMCSubtargetInfo() const
getSubtargetInfo() cannot be used where this is needed because we don't have a MachineFunction when w...
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
virtual bool PrintAsmMemoryOperand(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 as...
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 emitFunctionBodyEnd()
Targets can override this to emit stuff after the last basic block in the function.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual std::tuple< const MCSymbol *, uint64_t, const MCSymbol *, codeview::JumpTableEntrySize > getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr, const MCSymbol *BranchLabel) const
Gets information required to create a CodeView debug symbol for a jump table.
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.
The address of a basic block.
Function * getFunction() const
Conditional or Unconditional Branch instruction.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
A signed pointer, in the ptrauth sense.
@ AddrDiscriminator_CtorsDtors
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
ConstantInt * getKey() const
The Key ID, an i32 constant.
bool hasAddressDiscriminator() const
Whether there is any non-null address discriminator.
ConstantInt * getDiscriminator() const
The integer discriminator, an i64 constant, or 0.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
const Constant * getAliasee() const
const Constant * getResolver() const
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)
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
MCSection * getDataSection() const
Instances of this class represent operands of the MCInst class.
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.
Wrapper class representing physical registers. Should be passed by value.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
virtual void emitCFIBKeyFrame()
virtual void beginCOFFSymbolDef(const MCSymbol *Symbol)
Start emitting COFF symbol definition.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitCOFFSymbolType(int Type)
Emit the type of the symbol.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
virtual void endCOFFSymbolDef()
Marks the end of the symbol definition.
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()
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 ....
virtual void emitCOFFSymbolStorageClass(int StorageClass)
Emit the storage class of the symbol.
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
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 ...
StringRef getName() const
getName - Get the symbol name.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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...
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation for ELF targets.
ExprStubListTy getAuthGVStubList()
MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation for MachO targets.
ExprStubListTy getAuthGVStubList()
MachineOperand class - Representation of each machine instruction operand.
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.
A Module instance is used to store all the information related to an LLVM module.
Pass interface - Implemented by all 'passes'.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
MI-level patchpoint operands.
Wrapper class representing virtual and physical registers.
static SectionKind getMetadata()
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
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.
MI-level Statepoint operands.
StringRef - Represent a constant reference to a string, i.e.
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.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool regsOverlap(Register RegA, Register RegB) const
Returns true if the two registers are equal or alias each other.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isFunctionTy() const
True if this is an instance of FunctionType.
LLVM Value Representation.
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 LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an SmallVector or SmallString.
#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 ==...
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))
@ AArch64_VectorCall
Used between AArch64 Advanced SIMD functions.
@ AArch64_SVE_VectorCall
Used between AArch64 SVE functions.
@ C
The default llvm calling convention, compatible with C.
@ GNU_PROPERTY_AARCH64_FEATURE_1_BTI
@ GNU_PROPERTY_AARCH64_FEATURE_1_PAC
@ GNU_PROPERTY_AARCH64_FEATURE_1_GCS
@ S_REGULAR
S_REGULAR - Regular section.
Reg
All possible values of the reg field in the ModR/M byte.
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)
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.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
Target & getTheAArch64leTarget()
Target & getTheAArch64_32Target()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Target & getTheARM64_32Target()
static MCRegister getXRegFromWReg(MCRegister Reg)
Target & getTheARM64Target()
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)
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)
This struct is a compact representation of a valid (non-zero power of two) alignment.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...