78 cl::desc(
"Check pointer authentication auth/resign failures"),
82 "aarch64-win-import-call-optimization",
cl::Hidden,
83 cl::desc(
"Enable import call optimization for AArch64 Windows"),
86#define DEBUG_TYPE "asm-printer"
94 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
96 unsigned InstsEmitted;
99 SectionToImportedFunctionCalls;
102 AArch64AsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
103 :
AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *
this),
123 const MCSymbol *BranchLabel)
const override;
146 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
148 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
149 HwasanMemaccessTuple;
150 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
153 void emitHwasanMemaccessSymbols(
Module &M);
160 void emitPtrauthCheckAuthenticatedValue(
Register TestedReg,
168 void emitPtrauthTailCallHardening(
const MachineInstr *TC);
193 bool MayUseAddrAsScratch =
false);
212 void emitAttributes(
unsigned Flags,
uint64_t PAuthABIPlatform,
222 void emitFunctionHeaderComment()
override;
235 if (STI->isTargetCOFF()) {
292 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
294 MInstToMCSymbol LOHInstToLabel;
297 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
317void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
320 if (
TT.isOSBinFormatCOFF()) {
323 OutStreamer->beginCOFFSymbolDef(S);
326 OutStreamer->endCOFFSymbolDef();
327 int64_t Feat00Value = 0;
329 if (
M.getModuleFlag(
"cfguard")) {
331 Feat00Value |= COFF::Feat00Flags::GuardCF;
334 if (
M.getModuleFlag(
"ehcontguard")) {
336 Feat00Value |= COFF::Feat00Flags::GuardEHCont;
339 if (
M.getModuleFlag(
"ms-kernel")) {
341 Feat00Value |= COFF::Feat00Flags::Kernel;
345 OutStreamer->emitAssignment(
349 if (!
TT.isOSBinFormatELF())
357 unsigned BAFlags = 0;
358 unsigned GNUFlags = 0;
359 if (
const auto *BTE = mdconst::extract_or_null<ConstantInt>(
360 M.getModuleFlag(
"branch-target-enforcement"))) {
361 if (!BTE->isZero()) {
362 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_BTI_Flag;
367 if (
const auto *GCS = mdconst::extract_or_null<ConstantInt>(
368 M.getModuleFlag(
"guarded-control-stack"))) {
369 if (!GCS->isZero()) {
370 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_GCS_Flag;
375 if (
const auto *Sign = mdconst::extract_or_null<ConstantInt>(
376 M.getModuleFlag(
"sign-return-address"))) {
377 if (!Sign->isZero()) {
378 BAFlags |= AArch64BuildAttributes::FeatureAndBitsFlag::Feature_PAC_Flag;
384 if (
const auto *PAP = mdconst::extract_or_null<ConstantInt>(
385 M.getModuleFlag(
"aarch64-elf-pauthabi-platform"))) {
386 PAuthABIPlatform = PAP->getZExtValue();
390 if (
const auto *PAV = mdconst::extract_or_null<ConstantInt>(
391 M.getModuleFlag(
"aarch64-elf-pauthabi-version"))) {
392 PAuthABIVersion = PAV->getZExtValue();
396 emitAttributes(BAFlags, PAuthABIPlatform, PAuthABIVersion, TS);
398 TS->emitNoteSection(GNUFlags, PAuthABIPlatform, PAuthABIVersion);
401void AArch64AsmPrinter::emitFunctionHeaderComment() {
404 if (OutlinerString != std::nullopt)
405 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
408void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
411 if (
F.hasFnAttribute(
"patchable-function-entry")) {
413 if (
F.getFnAttribute(
"patchable-function-entry")
415 .getAsInteger(10, Num))
421 emitSled(
MI, SledKind::FUNCTION_ENTER);
424void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
425 emitSled(
MI, SledKind::FUNCTION_EXIT);
428void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
429 emitSled(
MI, SledKind::TAIL_CALL);
432void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
433 static const int8_t NoopsInSledCount = 7;
454 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
455 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
456 OutStreamer->emitLabel(CurSled);
457 auto Target = OutContext.createTempSymbol();
462 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::B).addImm(8));
464 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
465 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
467 OutStreamer->emitLabel(
Target);
468 recordSled(CurSled,
MI, Kind, 2);
471void AArch64AsmPrinter::emitAttributes(
unsigned Flags,
476 PAuthABIPlatform = (
uint64_t(-1) == PAuthABIPlatform) ? 0 : PAuthABIPlatform;
477 PAuthABIVersion = (
uint64_t(-1) == PAuthABIVersion) ? 0 : PAuthABIVersion;
479 if (PAuthABIPlatform || PAuthABIVersion) {
483 AArch64BuildAttributes::SubsectionOptional::REQUIRED,
484 AArch64BuildAttributes::SubsectionType::ULEB128);
488 PAuthABIPlatform,
"",
false);
502 if (BTIValue || PACValue || GCSValue) {
506 AArch64BuildAttributes::SubsectionOptional::OPTIONAL,
507 AArch64BuildAttributes::SubsectionType::ULEB128);
538void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
540 auto &
O = *OutStreamer;
541 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
542 O.emitLabel(CurSled);
543 bool MachO =
TM.getTargetTriple().isOSBinFormatMachO();
545 OutContext.getOrCreateSymbol(
546 Twine(MachO ?
"_" :
"") +
547 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
550 O.AddComment(
"Begin XRay typed event");
562 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
563 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
564 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
570 O.AddComment(
"End XRay typed event");
578 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
580 O.AddComment(
"Begin XRay custom event");
588 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
589 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
591 O.AddComment(
"End XRay custom event");
599 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
605 assert(std::next(
MI.getIterator())->isCall() &&
606 "KCFI_CHECK not followed by a call instruction");
607 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
608 "KCFI_CHECK call target doesn't match call operand");
612 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
613 if (AddrReg == AArch64::XZR) {
617 emitMovXReg(AddrReg, AArch64::XZR);
623 for (
auto &Reg : ScratchRegs) {
629 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
630 "Invalid scratch registers for KCFI_CHECK");
634 int64_t PrefixNops = 0;
637 .getFnAttribute(
"patchable-function-prefix")
639 .getAsInteger(10, PrefixNops);
643 .addReg(ScratchRegs[0])
645 .addImm(-(PrefixNops * 4 + 4)));
649 const int64_t
Type =
MI.getOperand(1).getImm();
650 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
651 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
655 .addReg(AArch64::WZR)
656 .addReg(ScratchRegs[0])
657 .addReg(ScratchRegs[1])
661 EmitToStreamer(*OutStreamer,
671 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
675 AddrIndex = AddrReg - AArch64::X0;
685 assert(AddrIndex < 31 && TypeIndex < 31);
687 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
688 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BRK).addImm(ESR));
689 OutStreamer->emitLabel(
Pass);
692void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
700 if (Reg == AArch64::XZR)
704 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
706 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
707 uint32_t AccessInfo =
MI.getOperand(1).getImm();
709 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
711 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
712 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
714 MCSymbol *&
Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
715 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
718 if (!
TM.getTargetTriple().isOSBinFormatELF())
721 std::string SymName =
"__hwasan_check_x" + utostr(Reg - AArch64::X0) +
"_" +
724 SymName +=
"_fixed_" + utostr(FixedShadowOffset);
726 SymName +=
"_short_v2";
727 Sym = OutContext.getOrCreateSymbol(SymName);
730 EmitToStreamer(*OutStreamer,
735void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
736 if (HwasanMemaccessSymbols.empty())
741 std::unique_ptr<MCSubtargetInfo> STI(
742 TM.getTarget().createMCSubtargetInfo(
TT.str(),
"",
""));
743 assert(STI &&
"Unable to create subtarget info");
747 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
749 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
756 for (
auto &
P : HwasanMemaccessSymbols) {
757 unsigned Reg = std::get<0>(
P.first);
758 bool IsShort = std::get<1>(
P.first);
759 uint32_t AccessInfo = std::get<2>(
P.first);
760 bool IsFixedShadow = std::get<3>(
P.first);
761 uint64_t FixedShadowOffset = std::get<4>(
P.first);
763 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
766 bool HasMatchAllTag =
775 OutStreamer->switchSection(OutContext.getELFSection(
783 OutStreamer->emitLabel(
Sym);
786 .addReg(AArch64::X16)
796 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
798 .addReg(AArch64::W16)
799 .addReg(AArch64::X17)
800 .addReg(AArch64::X16)
805 .addReg(AArch64::W16)
806 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
807 .addReg(AArch64::X16)
813 .addReg(AArch64::XZR)
814 .addReg(AArch64::X16)
817 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
821 HandleMismatchOrPartialSym, OutContext)));
822 MCSymbol *ReturnSym = OutContext.createTempSymbol();
823 OutStreamer->emitLabel(ReturnSym);
824 EmitToStreamer(
MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
825 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
827 if (HasMatchAllTag) {
829 .addReg(AArch64::X17)
834 .addReg(AArch64::XZR)
835 .addReg(AArch64::X17)
846 .addReg(AArch64::WZR)
847 .addReg(AArch64::W16)
850 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
857 .addReg(AArch64::X17)
862 .addReg(AArch64::X17)
863 .addReg(AArch64::X17)
867 .addReg(AArch64::WZR)
868 .addReg(AArch64::W16)
869 .addReg(AArch64::W17)
877 .addReg(AArch64::X16)
881 .addReg(AArch64::W16)
882 .addReg(AArch64::X16)
886 .addReg(AArch64::XZR)
887 .addReg(AArch64::X16)
895 OutStreamer->emitLabel(HandleMismatchSym);
910 if (Reg != AArch64::X0)
911 emitMovXReg(AArch64::X0, Reg);
918 EmitToStreamer(
MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
925 .addReg(AArch64::X16)
927 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
931 .addReg(AArch64::X16)
932 .addReg(AArch64::X16)
934 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
936 EmitToStreamer(
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
944 const MCExpr *StubAuthPtrRef) {
947 OutStreamer.
emitValue(StubAuthPtrRef, 8);
950void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
951 emitHwasanMemaccessSymbols(M);
954 if (
TT.isOSBinFormatMachO()) {
961 if (!Stubs.empty()) {
963 OutStreamer->switchSection(
966 emitAlignment(
Align(8));
968 for (
const auto &Stub : Stubs)
971 OutStreamer->addBlankLine();
982 if (
TT.isOSBinFormatELF()) {
988 if (!Stubs.empty()) {
991 emitAlignment(
Align(8));
993 for (
const auto &Stub : Stubs)
996 OutStreamer->addBlankLine();
1006 const auto *PtrAuthELFGOTFlag = mdconst::extract_or_null<ConstantInt>(
1007 M.getModuleFlag(
"ptrauth-elf-got"));
1008 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
1010 if (!GV.use_empty() && isa<Function>(GV) &&
1011 !GV.getName().starts_with(
"llvm."))
1012 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
1017 FM.serializeToFaultMapSection();
1022 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
1025 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
1026 OutStreamer->emitBytes(
StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
1037 for (
auto &[Section, CallsToImportedFuncs] :
1038 SectionToImportedFunctionCalls) {
1040 sizeof(
uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
1041 OutStreamer->emitInt32(SectionSize);
1042 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
1043 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
1045 OutStreamer->emitInt32(0x13);
1046 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
1047 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
1053void AArch64AsmPrinter::emitLOHs() {
1056 for (
const auto &
D : AArch64FI->getLOHContainer()) {
1058 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
1059 assert(LabelIt != LOHInstToLabel.end() &&
1060 "Label hasn't been inserted for LOH related instruction");
1063 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
1068void AArch64AsmPrinter::emitFunctionBodyEnd() {
1069 if (!AArch64FI->getLOHRelated().empty())
1074MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1078 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
1079 return OutContext.getOrCreateSymbol(
1080 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1081 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
1086void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1104 PrintSymbolOperand(MO, O);
1115bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1139bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1142 assert(MO.
isReg() &&
"Should only get here with a register!");
1152bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1161 if (ExtraCode && ExtraCode[0]) {
1162 if (ExtraCode[1] != 0)
1165 switch (ExtraCode[0]) {
1173 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1187 switch (ExtraCode[0]) {
1189 RC = &AArch64::FPR8RegClass;
1192 RC = &AArch64::FPR16RegClass;
1195 RC = &AArch64::FPR32RegClass;
1198 RC = &AArch64::FPR64RegClass;
1201 RC = &AArch64::FPR128RegClass;
1204 RC = &AArch64::ZPRRegClass;
1209 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1222 if (AArch64::GPR32allRegClass.
contains(Reg) ||
1223 AArch64::GPR64allRegClass.
contains(Reg))
1227 if (AArch64::GPR64x8ClassRegClass.
contains(Reg))
1230 unsigned AltName = AArch64::NoRegAltName;
1232 if (AArch64::ZPRRegClass.
contains(Reg)) {
1233 RegClass = &AArch64::ZPRRegClass;
1234 }
else if (AArch64::PPRRegClass.
contains(Reg)) {
1235 RegClass = &AArch64::PPRRegClass;
1236 }
else if (AArch64::PNRRegClass.
contains(Reg)) {
1237 RegClass = &AArch64::PNRRegClass;
1239 RegClass = &AArch64::FPR128RegClass;
1240 AltName = AArch64::vreg;
1244 return printAsmRegInClass(MO, RegClass, AltName, O);
1251bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1253 const char *ExtraCode,
1255 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1259 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1264void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1266 unsigned NOps =
MI->getNumOperands();
1268 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1270 OS <<
MI->getDebugVariable()->getName();
1273 assert(
MI->isIndirectDebugValue());
1275 for (
unsigned I = 0, E = std::distance(
MI->debug_operands().begin(),
1276 MI->debug_operands().end());
1287void AArch64AsmPrinter::emitJumpTableInfo() {
1292 if (
JT.empty())
return;
1296 OutStreamer->switchSection(ReadOnlySec);
1299 for (
unsigned JTI = 0, e =
JT.size(); JTI !=
e; ++JTI) {
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 MF->getFunction().getCallingConv() ==
1366 if (
TM.getTargetTriple().isWindowsArm64EC() &&
1367 !MF->getFunction().hasLocalLinkage()) {
1372 OutStreamer->emitAssignment(
1374 MMI->getContext()));
1380 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1381 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1387 getSymbolFromMetadata(
"arm64ec_unmangled_name")) {
1388 MCSymbol *ECMangledSym = getSymbolFromMetadata(
"arm64ec_ecmangled_name");
1394 emitFunctionAlias(UnmangledSym, ECMangledSym);
1395 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1399 emitFunctionAlias(UnmangledSym, CurrentFnSym);
1405void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1407 if (
const auto *CPA = dyn_cast<ConstantPtrAuth>(CV))
1408 if (CPA->hasAddressDiscriminator() &&
1409 !CPA->hasSpecialAddressDiscriminator(
1412 "unexpected address discrimination value for ctors/dtors entry, only "
1413 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1422void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1424 if (
auto F = dyn_cast_or_null<Function>(GA.
getAliasee())) {
1429 if (
MDNode *
Node =
F->getMetadata(
"arm64ec_exp_name")) {
1430 StringRef ExpStr = cast<MDString>(
Node->getOperand(0))->getString();
1431 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1434 OutStreamer->beginCOFFSymbolDef(ExpSym);
1438 OutStreamer->endCOFFSymbolDef();
1440 OutStreamer->beginCOFFSymbolDef(
Sym);
1444 OutStreamer->endCOFFSymbolDef();
1446 OutStreamer->emitAssignment(
1448 MMI->getContext()));
1466 Register DestReg =
MI.getOperand(0).getReg();
1467 Register ScratchReg =
MI.getOperand(1).getReg();
1469 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1470 Register TableReg =
MI.getOperand(2).getReg();
1471 Register EntryReg =
MI.getOperand(3).getReg();
1472 int JTIdx =
MI.getOperand(4).getIndex();
1473 int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
1483 Label = MF->getContext().createTempSymbol();
1484 AArch64FI->setJumpTableEntryInfo(JTIdx,
Size, Label);
1491 .addExpr(LabelExpr));
1496 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1497 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1498 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1504 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1508 .addImm(
Size == 1 ? 0 : 1));
1516 .addImm(
Size == 4 ? 0 : 2));
1519void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1521 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1523 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1524 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1543 assert(!AArch64FI->getJumpTableEntryPCRelSymbol(JTI) &&
1544 "unsupported compressed jump table");
1546 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1550 uint64_t MaxTableEntry = NumTableEntries - 1;
1551 if (isUInt<12>(MaxTableEntry)) {
1552 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXri)
1553 .addReg(AArch64::XZR)
1554 .addReg(AArch64::X16)
1555 .addImm(MaxTableEntry)
1558 emitMOVZ(AArch64::X17,
static_cast<uint16_t>(MaxTableEntry), 0);
1563 if ((MaxTableEntry >>
Offset) == 0)
1565 emitMOVK(AArch64::X17,
static_cast<uint16_t>(MaxTableEntry >>
Offset),
1568 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXrs)
1569 .addReg(AArch64::XZR)
1570 .addReg(AArch64::X16)
1571 .addReg(AArch64::X17)
1578 .addReg(AArch64::X16)
1579 .addReg(AArch64::X16)
1580 .addReg(AArch64::XZR)
1590 MCInstLowering.lowerOperand(JTMOHi, JTMCHi);
1591 MCInstLowering.lowerOperand(JTMOLo, JTMCLo);
1598 .addReg(AArch64::X17)
1599 .addReg(AArch64::X17)
1603 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::LDRSWroX)
1604 .addReg(AArch64::X16)
1605 .addReg(AArch64::X17)
1606 .addReg(AArch64::X16)
1610 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1612 AArch64FI->setJumpTableEntryInfo(JTI, 4, AdrLabel);
1617 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1620 .addReg(AArch64::X16)
1621 .addReg(AArch64::X17)
1622 .addReg(AArch64::X16)
1625 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1630 unsigned Opcode =
MI.getOpcode();
1632 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1634 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1635 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1636 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1637 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1638 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1639 if (Opcode == AArch64::MOPSMemorySetPseudo)
1640 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1641 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1642 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1645 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1646 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1648 for (
auto Op : Ops) {
1652 MCIB.addReg(
MI.getOperand(i++).getReg());
1653 MCIB.addReg(
MI.getOperand(i++).getReg());
1655 MCIB.addReg(
MI.getOperand(i++).getReg());
1657 MCIB.addReg(
MI.getOperand(i++).getReg());
1658 MCIB.addReg(
MI.getOperand(i++).getReg());
1659 MCIB.addReg(
MI.getOperand(i++).getReg());
1661 EmitToStreamer(OutStreamer, MCIB);
1670 MCSymbol *MILabel = Ctx.createTempSymbol();
1674 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1680 while (NumNOPBytes > 0) {
1681 if (MII ==
MBB.
end() || MII->isCall() ||
1682 MII->getOpcode() == AArch64::DBG_VALUE ||
1683 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1684 MII->getOpcode() == TargetOpcode::STACKMAP)
1691 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1692 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1700 MCSymbol *MILabel = Ctx.createTempSymbol();
1706 int64_t CallTarget = Opers.getCallTarget().getImm();
1707 unsigned EncodedBytes = 0;
1709 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1710 "High 16 bits of call target should be zero.");
1711 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1714 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1715 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1716 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1717 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1720 unsigned NumBytes = Opers.getNumPatchBytes();
1721 assert(NumBytes >= EncodedBytes &&
1722 "Patchpoint can't request size less than the length of a call.");
1723 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1724 "Invalid number of NOP bytes requested!");
1725 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1726 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1732 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1733 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1734 for (
unsigned i = 0; i < PatchBytes; i += 4)
1735 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1740 unsigned CallOpcode;
1741 switch (CallTarget.
getType()) {
1744 MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
1745 CallOpcode = AArch64::BL;
1749 CallOpcode = AArch64::BL;
1753 CallOpcode = AArch64::BLR;
1760 EmitToStreamer(OutStreamer,
1765 MCSymbol *MILabel = Ctx.createTempSymbol();
1770void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1779 unsigned OperandsBeginIdx = 4;
1782 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1786 FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
1789 MI.setOpcode(Opcode);
1797 lowerOperand(MO, Dest);
1798 MI.addOperand(Dest);
1808 .addReg(AArch64::XZR)
1813void AArch64AsmPrinter::emitMOVZ(
Register Dest,
uint64_t Imm,
unsigned Shift) {
1814 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1815 EmitToStreamer(*OutStreamer,
1822void AArch64AsmPrinter::emitMOVK(
Register Dest,
uint64_t Imm,
unsigned Shift) {
1823 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1824 EmitToStreamer(*OutStreamer,
1833 Register DestReg =
MI.getOperand(0).getReg();
1834 if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() &&
1835 STI->isNeonAvailable()) {
1837 if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
1838 DestReg = AArch64::D0 + (DestReg - AArch64::H0);
1839 else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
1840 DestReg = AArch64::D0 + (DestReg - AArch64::S0);
1842 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
1845 MOVI.setOpcode(AArch64::MOVID);
1848 EmitToStreamer(*OutStreamer, MOVI);
1851 switch (
MI.getOpcode()) {
1853 case AArch64::FMOVH0:
1854 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1855 if (!STI->hasFullFP16())
1856 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1860 case AArch64::FMOVS0:
1865 case AArch64::FMOVD0:
1871 EmitToStreamer(*OutStreamer, FMov);
1878 bool MayUseAddrAsScratch) {
1879 assert(ScratchReg == AArch64::X16 || ScratchReg == AArch64::X17);
1881 if (AddrDisc == AArch64::NoRegister)
1882 AddrDisc = AArch64::XZR;
1890 if (AddrDisc == AArch64::XZR) {
1891 emitMOVZ(ScratchReg, Disc, 0);
1898 assert(MayUseAddrAsScratch || ScratchReg != AddrDisc);
1899 bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
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(
const MachineInstr *
MI) {
2078 const bool IsAUTPAC =
MI->getOpcode() == AArch64::AUTPAC;
2092 bool ShouldCheck =
true;
2094 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
2099 ShouldCheck = ShouldTrap =
false;
2106 ShouldCheck = ShouldTrap =
false;
2113 ShouldCheck = ShouldTrap =
true;
2118 uint64_t AUTDisc =
MI->getOperand(1).getImm();
2119 unsigned AUTAddrDisc =
MI->getOperand(2).getReg();
2122 assert(isUInt<16>(AUTDisc));
2124 emitPtrauthDiscriminator(AUTDisc, AUTAddrDisc, AArch64::X17);
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(AArch64::X16, AArch64::X17, AUTKey,
2149 AArch64PAuth::AuthCheckMethod::XPAC,
2150 ShouldTrap, EndSym);
2160 uint64_t PACDisc =
MI->getOperand(4).getImm();
2161 unsigned PACAddrDisc =
MI->getOperand(5).getReg();
2164 assert(isUInt<16>(PACDisc));
2166 emitPtrauthDiscriminator(PACDisc, PACAddrDisc, AArch64::X17);
2167 bool PACZero = PACDiscReg == AArch64::XZR;
2178 EmitToStreamer(*OutStreamer, PACInst);
2185void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2186 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2187 unsigned BrTarget =
MI->getOperand(0).getReg();
2191 "Invalid auth call key");
2194 assert(isUInt<16>(Disc));
2196 unsigned AddrDisc =
MI->getOperand(3).getReg();
2202 if (BrTarget == AddrDisc)
2210 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2212 bool IsZeroDisc = DiscReg == AArch64::XZR;
2217 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
2219 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
2222 Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
2224 Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
2232 EmitToStreamer(*OutStreamer, BRInst);
2242 getDataLayout(),
Offset,
true);
2244 auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
2250 "cannot resolve target base/addend of ptrauth constant");
2268 "' out of range [0, " +
2272 if (!isUInt<16>(Disc))
2274 "' out of range [0, 0xFFFF]");
2281void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2282 unsigned DstReg =
MI.getOperand(0).getReg();
2284 const uint64_t KeyC =
MI.getOperand(2).getImm();
2286 "key is out of range [0, AArch64PACKey::LAST]");
2288 const uint64_t Disc =
MI.getOperand(3).getImm();
2289 assert(isUInt<16>(Disc) &&
2290 "constant discriminator is out of range [0, 0xffff]");
2299 if (
TM.getTargetTriple().isOSBinFormatELF()) {
2304 "non-zero offset for $auth_ptr$ stub slots is not supported");
2306 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym, Key, Disc);
2308 assert(
TM.getTargetTriple().isOSBinFormatMachO() &&
2309 "LOADauthptrstatic is implemented only for MachO/ELF");
2312 getObjFileLowering());
2315 "non-zero offset for $auth_ptr$ stub slots is not supported");
2317 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym, Key, Disc);
2326 MCInstLowering.lowerOperand(StubMOHi, StubMCHi);
2327 MCInstLowering.lowerOperand(StubMOLo, StubMCLo);
2340 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2341 const bool IsELFSignedGOT =
MI.getParent()
2344 ->hasELFSignedGOT();
2346 const uint64_t KeyC =
MI.getOperand(1).getImm();
2348 "key is out of range [0, AArch64PACKey::LAST]");
2350 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2351 const uint64_t Disc =
MI.getOperand(3).getImm();
2352 assert(isUInt<16>(Disc) &&
2353 "constant discriminator is out of range [0, 0xffff]");
2410 MCInstLowering.lowerOperand(GAMOHi, GAMCHi);
2411 MCInstLowering.lowerOperand(GAMOLo, GAMCLo);
2415 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2419 if (IsELFSignedGOT) {
2421 .addReg(AArch64::X17)
2422 .addReg(AArch64::X17)
2427 .addReg(AArch64::X16)
2428 .addReg(AArch64::X17)
2438 .addReg(AArch64::X16)
2439 .addReg(AArch64::X16)
2440 .addReg(AArch64::X17));
2442 if (!STI->hasFPAC()) {
2446 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2447 AArch64PAuth::AuthCheckMethod::XPAC,
2453 .addReg(AArch64::X16)
2454 .addReg(AArch64::X16)
2459 .addReg(AArch64::X16)
2460 .addReg(AArch64::X16)
2467 const bool IsNeg =
Offset < 0;
2468 if (isUInt<24>(AbsOffset)) {
2469 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2473 .addReg(AArch64::X16)
2474 .addReg(AArch64::X16)
2475 .addImm((AbsOffset >> BitPos) & 0xfff)
2480 EmitToStreamer(
MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2481 .addReg(AArch64::X17)
2482 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
2484 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
2485 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2486 uint64_t Shifted = UOffset >> BitPos;
2488 return Shifted != 0;
2489 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2490 if (((Shifted >>
I) & 0xffff) != 0xffff)
2494 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2495 emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
2498 .addReg(AArch64::X16)
2499 .addReg(AArch64::X16)
2500 .addReg(AArch64::X17)
2505 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2510 if (DiscReg != AArch64::XZR)
2512 EmitToStreamer(MIB);
2515void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2517 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2523 MCInstLowering.lowerOperand(GAMO, GAMC);
2527 .addReg(AuthResultReg)
2528 .addReg(AArch64::X17)
2537 MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
2538 MCInstLowering.lowerOperand(GALoOp, GAMCLo);
2544 .addReg(AArch64::X17)
2545 .addReg(AArch64::X17)
2550 .addReg(AuthResultReg)
2551 .addReg(AArch64::X17)
2558 UndefWeakSym = createTempSymbol(
"undef_weak");
2561 .addReg(AuthResultReg)
2570 .addReg(AuthResultReg)
2571 .addReg(AuthResultReg)
2572 .addReg(AArch64::X17));
2577 if (!STI->hasFPAC()) {
2581 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2582 AArch64PAuth::AuthCheckMethod::XPAC,
2586 emitMovXReg(DstReg, AuthResultReg);
2591AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2595 if (std::optional<uint16_t> BADisc =
2596 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2605#include "AArch64GenMCPseudoLowering.inc"
2615 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
2620 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
2625 if (
MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
2626 EmitToStreamer(*OutStreamer, OutInst);
2630 if (
MI->getOpcode() == AArch64::ADRP) {
2631 for (
auto &Opd :
MI->operands()) {
2632 if (Opd.isSymbol() &&
StringRef(Opd.getSymbolName()) ==
2633 "swift_async_extendedFramePointerFlags") {
2634 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
2639 if (AArch64FI->getLOHRelated().count(
MI)) {
2641 MCSymbol *LOHLabel = createTempSymbol(
"loh");
2643 LOHInstToLabel[
MI] = LOHLabel;
2650 switch (
MI->getOpcode()) {
2653 "Unhandled tail call instruction");
2655 case AArch64::HINT: {
2660 if (CurrentPatchableFunctionEntrySym &&
2661 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
2662 MI == &MF->front().front()) {
2663 int64_t
Imm =
MI->getOperand(0).getImm();
2664 if ((Imm & 32) && (Imm & 6)) {
2666 MCInstLowering.Lower(
MI, Inst);
2667 EmitToStreamer(*OutStreamer, Inst);
2668 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
2669 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
2675 case AArch64::MOVMCSym: {
2676 Register DestReg =
MI->getOperand(0).getReg();
2684 MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
2685 MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
2692 EmitToStreamer(*OutStreamer, MovZ);
2700 EmitToStreamer(*OutStreamer, MovK);
2703 case AArch64::MOVIv2d_ns:
2711 if (STI->hasZeroCycleZeroingFPWorkaround() &&
2712 MI->getOperand(1).getImm() == 0) {
2714 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
2717 EmitToStreamer(*OutStreamer, TmpInst);
2722 case AArch64::DBG_VALUE:
2723 case AArch64::DBG_VALUE_LIST:
2727 PrintDebugValueComment(
MI,
OS);
2732 case AArch64::EMITBKEY: {
2734 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2735 ExceptionHandlingType != ExceptionHandling::ARM)
2738 if (getFunctionCFISectionType(*MF) == CFISection::None)
2745 case AArch64::EMITMTETAGGED: {
2747 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2748 ExceptionHandlingType != ExceptionHandling::ARM)
2751 if (getFunctionCFISectionType(*MF) != CFISection::None)
2757 case AArch64::AUTPAC:
2758 emitPtrauthAuthResign(
MI);
2761 case AArch64::LOADauthptrstatic:
2762 LowerLOADauthptrstatic(*
MI);
2765 case AArch64::LOADgotPAC:
2766 case AArch64::MOVaddrPAC:
2767 LowerMOVaddrPAC(*
MI);
2770 case AArch64::LOADgotAUTH:
2771 LowerLOADgotAUTH(*
MI);
2776 emitPtrauthBranch(
MI);
2782 case AArch64::AUTH_TCRETURN:
2783 case AArch64::AUTH_TCRETURN_BTI: {
2787 "Invalid auth key for tail-call return");
2789 const uint64_t Disc =
MI->getOperand(3).getImm();
2790 assert(isUInt<16>(Disc) &&
"Integer discriminator is too wide");
2792 Register AddrDisc =
MI->getOperand(4).getReg();
2794 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2796 emitPtrauthTailCallHardening(
MI);
2799 if (Callee == AddrDisc)
2801 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
2804 const bool IsZero = DiscReg == AArch64::XZR;
2805 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
2806 {AArch64::BRAB, AArch64::BRABZ}};
2809 TmpInst.
setOpcode(Opcodes[Key][IsZero]);
2813 EmitToStreamer(*OutStreamer, TmpInst);
2817 case AArch64::TCRETURNri:
2818 case AArch64::TCRETURNrix16x17:
2819 case AArch64::TCRETURNrix17:
2820 case AArch64::TCRETURNrinotx16:
2821 case AArch64::TCRETURNriALL: {
2822 emitPtrauthTailCallHardening(
MI);
2824 recordIfImportCall(
MI);
2828 EmitToStreamer(*OutStreamer, TmpInst);
2831 case AArch64::TCRETURNdi: {
2832 emitPtrauthTailCallHardening(
MI);
2835 MCInstLowering.lowerOperand(
MI->getOperand(0), Dest);
2836 recordIfImportCall(
MI);
2840 EmitToStreamer(*OutStreamer, TmpInst);
2843 case AArch64::SpeculationBarrierISBDSBEndBB: {
2848 EmitToStreamer(*OutStreamer, TmpInstDSB);
2852 EmitToStreamer(*OutStreamer, TmpInstISB);
2855 case AArch64::SpeculationBarrierSBEndBB: {
2859 EmitToStreamer(*OutStreamer, TmpInstSB);
2862 case AArch64::TLSDESC_AUTH_CALLSEQ: {
2874 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2875 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2881 EmitToStreamer(*OutStreamer, Adrp);
2889 EmitToStreamer(*OutStreamer, Ldr);
2892 Add.setOpcode(AArch64::ADDXri);
2895 Add.addOperand(SymTLSDescLo12);
2897 EmitToStreamer(*OutStreamer,
Add);
2906 EmitToStreamer(*OutStreamer, Blraa);
2910 case AArch64::TLSDESC_CALLSEQ: {
2923 MCInstLowering.lowerOperand(MO_Sym,
Sym);
2924 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2925 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2931 EmitToStreamer(*OutStreamer, Adrp);
2934 if (STI->isTargetILP32()) {
2944 EmitToStreamer(*OutStreamer, Ldr);
2947 if (STI->isTargetILP32()) {
2948 Add.setOpcode(AArch64::ADDWri);
2952 Add.setOpcode(AArch64::ADDXri);
2956 Add.addOperand(SymTLSDescLo12);
2958 EmitToStreamer(*OutStreamer,
Add);
2963 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
2965 EmitToStreamer(*OutStreamer, TLSDescCall);
2973 EmitToStreamer(*OutStreamer, Blr);
2978 case AArch64::JumpTableDest32:
2979 case AArch64::JumpTableDest16:
2980 case AArch64::JumpTableDest8:
2981 LowerJumpTableDest(*OutStreamer, *
MI);
2984 case AArch64::BR_JumpTable:
2985 LowerHardenedBRJumpTable(*
MI);
2988 case AArch64::FMOVH0:
2989 case AArch64::FMOVS0:
2990 case AArch64::FMOVD0:
2994 case AArch64::MOPSMemoryCopyPseudo:
2995 case AArch64::MOPSMemoryMovePseudo:
2996 case AArch64::MOPSMemorySetPseudo:
2997 case AArch64::MOPSMemorySetTaggingPseudo:
2998 LowerMOPS(*OutStreamer, *
MI);
3001 case TargetOpcode::STACKMAP:
3002 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
3004 case TargetOpcode::PATCHPOINT:
3005 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
3007 case TargetOpcode::STATEPOINT:
3008 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
3010 case TargetOpcode::FAULTING_OP:
3011 return LowerFAULTING_OP(*
MI);
3013 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
3014 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
3017 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
3018 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
3021 case TargetOpcode::PATCHABLE_TAIL_CALL:
3022 LowerPATCHABLE_TAIL_CALL(*
MI);
3024 case TargetOpcode::PATCHABLE_EVENT_CALL:
3025 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
3026 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3027 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
3029 case AArch64::KCFI_CHECK:
3030 LowerKCFI_CHECK(*
MI);
3033 case AArch64::HWASAN_CHECK_MEMACCESS:
3034 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
3035 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
3036 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
3037 LowerHWASAN_CHECK_MEMACCESS(*
MI);
3040 case AArch64::SEH_StackAlloc:
3044 case AArch64::SEH_SaveFPLR:
3048 case AArch64::SEH_SaveFPLR_X:
3049 assert(
MI->getOperand(0).getImm() < 0 &&
3050 "Pre increment SEH opcode must have a negative offset");
3054 case AArch64::SEH_SaveReg:
3056 MI->getOperand(1).getImm());
3059 case AArch64::SEH_SaveReg_X:
3060 assert(
MI->getOperand(1).getImm() < 0 &&
3061 "Pre increment SEH opcode must have a negative offset");
3063 -
MI->getOperand(1).getImm());
3066 case AArch64::SEH_SaveRegP:
3067 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
3068 MI->getOperand(0).getImm() <= 28) {
3069 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
3070 "Register paired with LR must be odd");
3072 MI->getOperand(2).getImm());
3075 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3076 "Non-consecutive registers not allowed for save_regp");
3078 MI->getOperand(2).getImm());
3081 case AArch64::SEH_SaveRegP_X:
3082 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3083 "Non-consecutive registers not allowed for save_regp_x");
3084 assert(
MI->getOperand(2).getImm() < 0 &&
3085 "Pre increment SEH opcode must have a negative offset");
3087 -
MI->getOperand(2).getImm());
3090 case AArch64::SEH_SaveFReg:
3092 MI->getOperand(1).getImm());
3095 case AArch64::SEH_SaveFReg_X:
3096 assert(
MI->getOperand(1).getImm() < 0 &&
3097 "Pre increment SEH opcode must have a negative offset");
3099 -
MI->getOperand(1).getImm());
3102 case AArch64::SEH_SaveFRegP:
3103 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3104 "Non-consecutive registers not allowed for save_regp");
3106 MI->getOperand(2).getImm());
3109 case AArch64::SEH_SaveFRegP_X:
3110 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3111 "Non-consecutive registers not allowed for save_regp_x");
3112 assert(
MI->getOperand(2).getImm() < 0 &&
3113 "Pre increment SEH opcode must have a negative offset");
3115 -
MI->getOperand(2).getImm());
3118 case AArch64::SEH_SetFP:
3122 case AArch64::SEH_AddFP:
3126 case AArch64::SEH_Nop:
3130 case AArch64::SEH_PrologEnd:
3134 case AArch64::SEH_EpilogStart:
3138 case AArch64::SEH_EpilogEnd:
3142 case AArch64::SEH_PACSignLR:
3146 case AArch64::SEH_SaveAnyRegQP:
3147 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3148 "Non-consecutive registers not allowed for save_any_reg");
3149 assert(
MI->getOperand(2).getImm() >= 0 &&
3150 "SaveAnyRegQP SEH opcode offset must be non-negative");
3151 assert(
MI->getOperand(2).getImm() <= 1008 &&
3152 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3154 MI->getOperand(2).getImm());
3157 case AArch64::SEH_SaveAnyRegQPX:
3158 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3159 "Non-consecutive registers not allowed for save_any_reg");
3160 assert(
MI->getOperand(2).getImm() < 0 &&
3161 "SaveAnyRegQPX SEH opcode offset must be negative");
3162 assert(
MI->getOperand(2).getImm() >= -1008 &&
3163 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3165 -
MI->getOperand(2).getImm());
3170 recordIfImportCall(
MI);
3172 MCInstLowering.Lower(
MI, TmpInst);
3173 EmitToStreamer(*OutStreamer, TmpInst);
3179 MCInstLowering.Lower(
MI, TmpInst);
3180 EmitToStreamer(*OutStreamer, TmpInst);
3183void AArch64AsmPrinter::recordIfImportCall(
3186 !
TM.getTargetTriple().isOSBinFormatCOFF())
3190 if (GV && GV->hasDLLImportStorageClass()) {
3191 auto *CallSiteSymbol = MMI->
getContext().createNamedTempSymbol(
"impcall");
3194 auto *CalledSymbol = MCInstLowering.GetGlobalValueSymbol(GV, OpFlags);
3196 .push_back({CallSiteSymbol, CalledSymbol});
3213 MCInstLowering.lowerOperand(
3218 EmitToStreamer(Adrp);
3227 MCInstLowering.lowerOperand(
3233 EmitToStreamer(Ldr);
3237 .addReg(AArch64::X16)
3238 .addReg(AArch64::X16)
3241 EmitToStreamer(
MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3246void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3281 .addReg(AArch64::SP)
3282 .addReg(AArch64::FP)
3283 .addReg(AArch64::LR)
3284 .addReg(AArch64::SP)
3288 .addReg(AArch64::FP)
3289 .addReg(AArch64::SP)
3293 for (
int I = 0;
I != 4; ++
I)
3295 .addReg(AArch64::SP)
3296 .addReg(AArch64::X1 + 2 *
I)
3297 .addReg(AArch64::X0 + 2 *
I)
3298 .addReg(AArch64::SP)
3301 for (
int I = 0;
I != 4; ++
I)
3303 .addReg(AArch64::SP)
3304 .addReg(AArch64::D1 + 2 *
I)
3305 .addReg(AArch64::D0 + 2 *
I)
3306 .addReg(AArch64::SP)
3318 MCInstLowering.lowerOperand(
3323 EmitToStreamer(Adrp);
3332 MCInstLowering.lowerOperand(
3338 EmitToStreamer(Ldr);
3342 .addReg(AArch64::X0)
3343 .addReg(AArch64::X16)
3347 .addReg(AArch64::X16)
3348 .addReg(AArch64::X0)
3352 for (
int I = 3;
I != -1; --
I)
3354 .addReg(AArch64::SP)
3355 .addReg(AArch64::D1 + 2 *
I)
3356 .addReg(AArch64::D0 + 2 *
I)
3357 .addReg(AArch64::SP)
3360 for (
int I = 3;
I != -1; --
I)
3362 .addReg(AArch64::SP)
3363 .addReg(AArch64::X1 + 2 *
I)
3364 .addReg(AArch64::X0 + 2 *
I)
3365 .addReg(AArch64::SP)
3369 .addReg(AArch64::SP)
3370 .addReg(AArch64::FP)
3371 .addReg(AArch64::LR)
3372 .addReg(AArch64::SP)
3375 EmitToStreamer(
MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3380const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV) {
3381 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
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 cl::opt< bool > EnableImportCallOptimization("aarch64-win-import-call-optimization", cl::Hidden, cl::desc("Enable import call optimization for AArch64 Windows"), cl::init(false))
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64AsmPrinter()
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.
unsigned const TargetRegisterInfo * TRI
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
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.
static const AArch64MCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
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 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 emitAttribute(StringRef VendorName, unsigned Tag, unsigned Value, std::string String, bool Override)
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 emitARM64WinCFIPrologEnd()
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFINop()
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
virtual void emitAtributesSubsection(StringRef VendorName, AArch64BuildAttributes::SubsectionOptional IsOptional, AArch64BuildAttributes::SubsectionType ParameterType)
Build attributes implementation.
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.
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 void emitJumpTableInfo()
Print assembly representations of the jump tables used by the current function to the current output ...
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 const MCExpr * lowerConstant(const Constant *CV)
Lower the specified LLVM Constant to an MCExpr.
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.
Constant * getPointer() const
The pointer that is signed in this ptrauth signed pointer.
ConstantInt * getKey() const
The Key ID, an i32 constant.
@ AddrDiscriminator_CtorsDtors
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
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)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static 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.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
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)
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.
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.
iterator_range< mop_iterator > operands()
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.
void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
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.
const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr) const
Accumulate the constant offset this value has compared to a base pointer.
LLVMContext & getContext() const
All values hold a context through their type.
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_NULL
No complex type; simple scalar variable.
@ 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.
@ 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.
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()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Target & getTheARM64_32Target()
@ MCAF_SubsectionsViaSymbols
.subsections_via_symbols (MachO)
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_Global
.type _foo, @gnu_unique_object
@ 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,...