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);
218 void emitFunctionHeaderComment()
override;
231 if (STI->isTargetCOFF()) {
288 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
290 MInstToMCSymbol LOHInstToLabel;
293 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
313void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
316 if (
TT.isOSBinFormatCOFF()) {
319 OutStreamer->beginCOFFSymbolDef(S);
322 OutStreamer->endCOFFSymbolDef();
323 int64_t Feat00Value = 0;
325 if (
M.getModuleFlag(
"cfguard")) {
327 Feat00Value |= COFF::Feat00Flags::GuardCF;
330 if (
M.getModuleFlag(
"ehcontguard")) {
332 Feat00Value |= COFF::Feat00Flags::GuardEHCont;
335 if (
M.getModuleFlag(
"ms-kernel")) {
337 Feat00Value |= COFF::Feat00Flags::Kernel;
341 OutStreamer->emitAssignment(
345 if (!
TT.isOSBinFormatELF())
350 if (
const auto *BTE = mdconst::extract_or_null<ConstantInt>(
351 M.getModuleFlag(
"branch-target-enforcement")))
355 if (
const auto *GCS = mdconst::extract_or_null<ConstantInt>(
356 M.getModuleFlag(
"guarded-control-stack")))
360 if (
const auto *Sign = mdconst::extract_or_null<ConstantInt>(
361 M.getModuleFlag(
"sign-return-address")))
366 if (
const auto *PAP = mdconst::extract_or_null<ConstantInt>(
367 M.getModuleFlag(
"aarch64-elf-pauthabi-platform")))
368 PAuthABIPlatform = PAP->getZExtValue();
370 if (
const auto *PAV = mdconst::extract_or_null<ConstantInt>(
371 M.getModuleFlag(
"aarch64-elf-pauthabi-version")))
372 PAuthABIVersion = PAV->getZExtValue();
380void AArch64AsmPrinter::emitFunctionHeaderComment() {
383 if (OutlinerString != std::nullopt)
384 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
387void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
390 if (
F.hasFnAttribute(
"patchable-function-entry")) {
392 if (
F.getFnAttribute(
"patchable-function-entry")
394 .getAsInteger(10, Num))
400 emitSled(
MI, SledKind::FUNCTION_ENTER);
403void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
404 emitSled(
MI, SledKind::FUNCTION_EXIT);
407void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
408 emitSled(
MI, SledKind::TAIL_CALL);
411void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
412 static const int8_t NoopsInSledCount = 7;
433 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
434 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
435 OutStreamer->emitLabel(CurSled);
436 auto Target = OutContext.createTempSymbol();
441 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::B).addImm(8));
443 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
444 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
446 OutStreamer->emitLabel(
Target);
447 recordSled(CurSled,
MI, Kind, 2);
465void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
467 auto &
O = *OutStreamer;
468 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
469 O.emitLabel(CurSled);
470 bool MachO =
TM.getTargetTriple().isOSBinFormatMachO();
472 OutContext.getOrCreateSymbol(
473 Twine(MachO ?
"_" :
"") +
474 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
477 O.AddComment(
"Begin XRay typed event");
489 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
490 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
491 emitMovXReg(AArch64::X2,
MI.getOperand(2).getReg());
497 O.AddComment(
"End XRay typed event");
505 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
507 O.AddComment(
"Begin XRay custom event");
515 emitMovXReg(AArch64::X0,
MI.getOperand(0).getReg());
516 emitMovXReg(AArch64::X1,
MI.getOperand(1).getReg());
518 O.AddComment(
"End XRay custom event");
526 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
532 assert(std::next(
MI.getIterator())->isCall() &&
533 "KCFI_CHECK not followed by a call instruction");
534 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
535 "KCFI_CHECK call target doesn't match call operand");
539 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
540 if (AddrReg == AArch64::XZR) {
544 emitMovXReg(AddrReg, AArch64::XZR);
550 for (
auto &Reg : ScratchRegs) {
556 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
557 "Invalid scratch registers for KCFI_CHECK");
561 int64_t PrefixNops = 0;
564 .getFnAttribute(
"patchable-function-prefix")
566 .getAsInteger(10, PrefixNops);
570 .addReg(ScratchRegs[0])
572 .addImm(-(PrefixNops * 4 + 4)));
576 const int64_t
Type =
MI.getOperand(1).getImm();
577 emitMOVK(ScratchRegs[1],
Type & 0xFFFF, 0);
578 emitMOVK(ScratchRegs[1], (
Type >> 16) & 0xFFFF, 16);
582 .addReg(AArch64::WZR)
583 .addReg(ScratchRegs[0])
584 .addReg(ScratchRegs[1])
588 EmitToStreamer(*OutStreamer,
598 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
602 AddrIndex = AddrReg - AArch64::X0;
612 assert(AddrIndex < 31 && TypeIndex < 31);
614 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
615 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BRK).addImm(ESR));
616 OutStreamer->emitLabel(
Pass);
619void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
627 if (Reg == AArch64::XZR)
631 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
633 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
634 uint32_t AccessInfo =
MI.getOperand(1).getImm();
636 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
638 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
639 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
641 MCSymbol *&
Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
642 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
645 if (!
TM.getTargetTriple().isOSBinFormatELF())
648 std::string SymName =
"__hwasan_check_x" + utostr(Reg - AArch64::X0) +
"_" +
651 SymName +=
"_fixed_" + utostr(FixedShadowOffset);
653 SymName +=
"_short_v2";
654 Sym = OutContext.getOrCreateSymbol(SymName);
657 EmitToStreamer(*OutStreamer,
662void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
663 if (HwasanMemaccessSymbols.empty())
668 std::unique_ptr<MCSubtargetInfo> STI(
669 TM.getTarget().createMCSubtargetInfo(
TT.str(),
"",
""));
670 assert(STI &&
"Unable to create subtarget info");
674 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
676 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
683 for (
auto &
P : HwasanMemaccessSymbols) {
684 unsigned Reg = std::get<0>(
P.first);
685 bool IsShort = std::get<1>(
P.first);
686 uint32_t AccessInfo = std::get<2>(
P.first);
687 bool IsFixedShadow = std::get<3>(
P.first);
688 uint64_t FixedShadowOffset = std::get<4>(
P.first);
690 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
693 bool HasMatchAllTag =
702 OutStreamer->switchSection(OutContext.getELFSection(
710 OutStreamer->emitLabel(
Sym);
713 .addReg(AArch64::X16)
723 emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
725 .addReg(AArch64::W16)
726 .addReg(AArch64::X17)
727 .addReg(AArch64::X16)
732 .addReg(AArch64::W16)
733 .addReg(IsShort ? AArch64::X20 : AArch64::X9)
734 .addReg(AArch64::X16)
740 .addReg(AArch64::XZR)
741 .addReg(AArch64::X16)
744 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
748 HandleMismatchOrPartialSym, OutContext)));
749 MCSymbol *ReturnSym = OutContext.createTempSymbol();
750 OutStreamer->emitLabel(ReturnSym);
751 EmitToStreamer(
MCInstBuilder(AArch64::RET).addReg(AArch64::LR));
752 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
754 if (HasMatchAllTag) {
756 .addReg(AArch64::X17)
761 .addReg(AArch64::XZR)
762 .addReg(AArch64::X17)
773 .addReg(AArch64::WZR)
774 .addReg(AArch64::W16)
777 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
784 .addReg(AArch64::X17)
789 .addReg(AArch64::X17)
790 .addReg(AArch64::X17)
794 .addReg(AArch64::WZR)
795 .addReg(AArch64::W16)
796 .addReg(AArch64::W17)
804 .addReg(AArch64::X16)
808 .addReg(AArch64::W16)
809 .addReg(AArch64::X16)
813 .addReg(AArch64::XZR)
814 .addReg(AArch64::X16)
822 OutStreamer->emitLabel(HandleMismatchSym);
837 if (Reg != AArch64::X0)
838 emitMovXReg(AArch64::X0, Reg);
845 EmitToStreamer(
MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef));
852 .addReg(AArch64::X16)
854 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
858 .addReg(AArch64::X16)
859 .addReg(AArch64::X16)
861 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
863 EmitToStreamer(
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
871 const MCExpr *StubAuthPtrRef) {
874 OutStreamer.
emitValue(StubAuthPtrRef, 8);
877void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
878 emitHwasanMemaccessSymbols(M);
881 if (
TT.isOSBinFormatMachO()) {
888 if (!Stubs.empty()) {
890 OutStreamer->switchSection(
893 emitAlignment(
Align(8));
895 for (
const auto &Stub : Stubs)
898 OutStreamer->addBlankLine();
909 if (
TT.isOSBinFormatELF()) {
915 if (!Stubs.empty()) {
918 emitAlignment(
Align(8));
920 for (
const auto &Stub : Stubs)
923 OutStreamer->addBlankLine();
933 const auto *PtrAuthELFGOTFlag = mdconst::extract_or_null<ConstantInt>(
934 M.getModuleFlag(
"ptrauth-elf-got"));
935 if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue() == 1)
937 if (!GV.use_empty() && isa<Function>(GV) &&
938 !GV.getName().starts_with(
"llvm."))
939 OutStreamer->emitSymbolAttribute(getSymbol(&GV),
944 FM.serializeToFaultMapSection();
949 OutStreamer->switchSection(getObjFileLowering().getImportCallSection());
952 constexpr char ImpCallMagic[12] =
"Imp_Call_V1";
953 OutStreamer->emitBytes(
StringRef{ImpCallMagic,
sizeof(ImpCallMagic)});
964 for (
auto &[Section, CallsToImportedFuncs] :
965 SectionToImportedFunctionCalls) {
967 sizeof(
uint32_t) * (2 + 3 * CallsToImportedFuncs.size());
968 OutStreamer->emitInt32(SectionSize);
969 OutStreamer->emitCOFFSecNumber(
Section->getBeginSymbol());
970 for (
auto &[CallsiteSymbol, CalledSymbol] : CallsToImportedFuncs) {
972 OutStreamer->emitInt32(0x13);
973 OutStreamer->emitCOFFSecOffset(CallsiteSymbol);
974 OutStreamer->emitCOFFSymbolIndex(CalledSymbol);
980void AArch64AsmPrinter::emitLOHs() {
983 for (
const auto &
D : AArch64FI->getLOHContainer()) {
985 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
986 assert(LabelIt != LOHInstToLabel.end() &&
987 "Label hasn't been inserted for LOH related instruction");
990 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
995void AArch64AsmPrinter::emitFunctionBodyEnd() {
996 if (!AArch64FI->getLOHRelated().empty())
1001MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
1005 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
1006 return OutContext.getOrCreateSymbol(
1007 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
1008 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
1013void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
1031 PrintSymbolOperand(MO, O);
1042bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1066bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1069 assert(MO.
isReg() &&
"Should only get here with a register!");
1079bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1088 if (ExtraCode && ExtraCode[0]) {
1089 if (ExtraCode[1] != 0)
1092 switch (ExtraCode[0]) {
1100 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1114 switch (ExtraCode[0]) {
1116 RC = &AArch64::FPR8RegClass;
1119 RC = &AArch64::FPR16RegClass;
1122 RC = &AArch64::FPR32RegClass;
1125 RC = &AArch64::FPR64RegClass;
1128 RC = &AArch64::FPR128RegClass;
1131 RC = &AArch64::ZPRRegClass;
1136 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1149 if (AArch64::GPR32allRegClass.
contains(Reg) ||
1150 AArch64::GPR64allRegClass.
contains(Reg))
1154 if (AArch64::GPR64x8ClassRegClass.
contains(Reg))
1157 unsigned AltName = AArch64::NoRegAltName;
1159 if (AArch64::ZPRRegClass.
contains(Reg)) {
1160 RegClass = &AArch64::ZPRRegClass;
1161 }
else if (AArch64::PPRRegClass.
contains(Reg)) {
1162 RegClass = &AArch64::PPRRegClass;
1163 }
else if (AArch64::PNRRegClass.
contains(Reg)) {
1164 RegClass = &AArch64::PNRRegClass;
1166 RegClass = &AArch64::FPR128RegClass;
1167 AltName = AArch64::vreg;
1171 return printAsmRegInClass(MO, RegClass, AltName, O);
1178bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1180 const char *ExtraCode,
1182 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1186 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1191void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1193 unsigned NOps =
MI->getNumOperands();
1195 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1197 OS <<
MI->getDebugVariable()->getName();
1200 assert(
MI->isIndirectDebugValue());
1202 for (
unsigned I = 0, E = std::distance(
MI->debug_operands().begin(),
1203 MI->debug_operands().end());
1214void AArch64AsmPrinter::emitJumpTableInfo() {
1219 if (
JT.empty())
return;
1223 OutStreamer->switchSection(ReadOnlySec);
1226 for (
unsigned JTI = 0, e =
JT.size(); JTI !=
e; ++JTI) {
1227 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1230 if (JTBBs.empty())
continue;
1232 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1234 OutStreamer->emitLabel(GetJTISymbol(JTI));
1236 const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1239 for (
auto *JTBB : JTBBs) {
1259AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1261 const MCSymbol *BranchLabel)
const {
1263 const auto Base = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1265 switch (AFI->getJumpTableEntrySize(JTI)) {
1267 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1270 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1273 EntrySize = codeview::JumpTableEntrySize::Int32;
1278 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1281void AArch64AsmPrinter::emitFunctionEntryLabel() {
1283 MF->getFunction().getCallingConv() ==
1293 if (
TM.getTargetTriple().isWindowsArm64EC() &&
1294 !MF->getFunction().hasLocalLinkage()) {
1299 OutStreamer->emitAssignment(
1301 MMI->getContext()));
1307 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1308 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1314 getSymbolFromMetadata(
"arm64ec_unmangled_name")) {
1315 MCSymbol *ECMangledSym = getSymbolFromMetadata(
"arm64ec_ecmangled_name");
1321 emitFunctionAlias(UnmangledSym, ECMangledSym);
1322 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1326 emitFunctionAlias(UnmangledSym, CurrentFnSym);
1332void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1334 if (
const auto *CPA = dyn_cast<ConstantPtrAuth>(CV))
1335 if (CPA->hasAddressDiscriminator() &&
1336 !CPA->hasSpecialAddressDiscriminator(
1339 "unexpected address discrimination value for ctors/dtors entry, only "
1340 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1349void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1351 if (
auto F = dyn_cast_or_null<Function>(GA.
getAliasee())) {
1356 if (
MDNode *
Node =
F->getMetadata(
"arm64ec_exp_name")) {
1357 StringRef ExpStr = cast<MDString>(
Node->getOperand(0))->getString();
1358 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1361 OutStreamer->beginCOFFSymbolDef(ExpSym);
1365 OutStreamer->endCOFFSymbolDef();
1367 OutStreamer->beginCOFFSymbolDef(
Sym);
1371 OutStreamer->endCOFFSymbolDef();
1373 OutStreamer->emitAssignment(
1375 MMI->getContext()));
1393 Register DestReg =
MI.getOperand(0).getReg();
1394 Register ScratchReg =
MI.getOperand(1).getReg();
1396 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1397 Register TableReg =
MI.getOperand(2).getReg();
1398 Register EntryReg =
MI.getOperand(3).getReg();
1399 int JTIdx =
MI.getOperand(4).getIndex();
1400 int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
1410 Label = MF->getContext().createTempSymbol();
1411 AArch64FI->setJumpTableEntryInfo(JTIdx,
Size, Label);
1418 .addExpr(LabelExpr));
1423 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1424 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1425 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1431 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1435 .addImm(
Size == 1 ? 0 : 1));
1443 .addImm(
Size == 4 ? 0 : 2));
1446void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1448 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1450 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1451 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1470 assert(!AArch64FI->getJumpTableEntryPCRelSymbol(JTI) &&
1471 "unsupported compressed jump table");
1473 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1477 uint64_t MaxTableEntry = NumTableEntries - 1;
1478 if (isUInt<12>(MaxTableEntry)) {
1479 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXri)
1480 .addReg(AArch64::XZR)
1481 .addReg(AArch64::X16)
1482 .addImm(MaxTableEntry)
1485 emitMOVZ(AArch64::X17,
static_cast<uint16_t>(MaxTableEntry), 0);
1490 if ((MaxTableEntry >>
Offset) == 0)
1492 emitMOVK(AArch64::X17,
static_cast<uint16_t>(MaxTableEntry >>
Offset),
1495 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXrs)
1496 .addReg(AArch64::XZR)
1497 .addReg(AArch64::X16)
1498 .addReg(AArch64::X17)
1505 .addReg(AArch64::X16)
1506 .addReg(AArch64::X16)
1507 .addReg(AArch64::XZR)
1517 MCInstLowering.lowerOperand(JTMOHi, JTMCHi);
1518 MCInstLowering.lowerOperand(JTMOLo, JTMCLo);
1525 .addReg(AArch64::X17)
1526 .addReg(AArch64::X17)
1530 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::LDRSWroX)
1531 .addReg(AArch64::X16)
1532 .addReg(AArch64::X17)
1533 .addReg(AArch64::X16)
1537 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1539 AArch64FI->setJumpTableEntryInfo(JTI, 4, AdrLabel);
1544 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1547 .addReg(AArch64::X16)
1548 .addReg(AArch64::X17)
1549 .addReg(AArch64::X16)
1552 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1557 unsigned Opcode =
MI.getOpcode();
1559 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1561 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1562 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1563 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1564 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1565 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1566 if (Opcode == AArch64::MOPSMemorySetPseudo)
1567 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1568 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1569 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1572 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1573 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1575 for (
auto Op : Ops) {
1579 MCIB.addReg(
MI.getOperand(i++).getReg());
1580 MCIB.addReg(
MI.getOperand(i++).getReg());
1582 MCIB.addReg(
MI.getOperand(i++).getReg());
1584 MCIB.addReg(
MI.getOperand(i++).getReg());
1585 MCIB.addReg(
MI.getOperand(i++).getReg());
1586 MCIB.addReg(
MI.getOperand(i++).getReg());
1588 EmitToStreamer(OutStreamer, MCIB);
1597 MCSymbol *MILabel = Ctx.createTempSymbol();
1601 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1607 while (NumNOPBytes > 0) {
1608 if (MII ==
MBB.
end() || MII->isCall() ||
1609 MII->getOpcode() == AArch64::DBG_VALUE ||
1610 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1611 MII->getOpcode() == TargetOpcode::STACKMAP)
1618 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1619 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1627 MCSymbol *MILabel = Ctx.createTempSymbol();
1633 int64_t CallTarget = Opers.getCallTarget().getImm();
1634 unsigned EncodedBytes = 0;
1636 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1637 "High 16 bits of call target should be zero.");
1638 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1641 emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1642 emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1643 emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
1644 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1647 unsigned NumBytes = Opers.getNumPatchBytes();
1648 assert(NumBytes >= EncodedBytes &&
1649 "Patchpoint can't request size less than the length of a call.");
1650 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1651 "Invalid number of NOP bytes requested!");
1652 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1653 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1659 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1660 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1661 for (
unsigned i = 0; i < PatchBytes; i += 4)
1662 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1667 unsigned CallOpcode;
1668 switch (CallTarget.
getType()) {
1671 MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
1672 CallOpcode = AArch64::BL;
1676 CallOpcode = AArch64::BL;
1680 CallOpcode = AArch64::BLR;
1687 EmitToStreamer(OutStreamer,
1692 MCSymbol *MILabel = Ctx.createTempSymbol();
1697void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1706 unsigned OperandsBeginIdx = 4;
1709 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1713 FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
1716 MI.setOpcode(Opcode);
1724 lowerOperand(MO, Dest);
1725 MI.addOperand(Dest);
1735 .addReg(AArch64::XZR)
1740void AArch64AsmPrinter::emitMOVZ(
Register Dest,
uint64_t Imm,
unsigned Shift) {
1741 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1742 EmitToStreamer(*OutStreamer,
1749void AArch64AsmPrinter::emitMOVK(
Register Dest,
uint64_t Imm,
unsigned Shift) {
1750 bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1751 EmitToStreamer(*OutStreamer,
1760 Register DestReg =
MI.getOperand(0).getReg();
1761 if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() &&
1762 STI->isNeonAvailable()) {
1764 if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
1765 DestReg = AArch64::D0 + (DestReg - AArch64::H0);
1766 else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
1767 DestReg = AArch64::D0 + (DestReg - AArch64::S0);
1769 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
1772 MOVI.setOpcode(AArch64::MOVID);
1775 EmitToStreamer(*OutStreamer, MOVI);
1778 switch (
MI.getOpcode()) {
1780 case AArch64::FMOVH0:
1781 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1782 if (!STI->hasFullFP16())
1783 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1787 case AArch64::FMOVS0:
1792 case AArch64::FMOVD0:
1798 EmitToStreamer(*OutStreamer, FMov);
1805 bool MayUseAddrAsScratch) {
1806 assert(ScratchReg == AArch64::X16 || ScratchReg == AArch64::X17);
1808 if (AddrDisc == AArch64::NoRegister)
1809 AddrDisc = AArch64::XZR;
1817 if (AddrDisc == AArch64::XZR) {
1818 emitMOVZ(ScratchReg, Disc, 0);
1825 assert(MayUseAddrAsScratch || ScratchReg != AddrDisc);
1826 bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17;
1827 if (MayUseAddrAsScratch && AddrDiscIsSafe)
1828 ScratchReg = AddrDisc;
1830 emitMovXReg(ScratchReg, AddrDisc);
1832 emitMOVK(ScratchReg, Disc, 48);
1840void AArch64AsmPrinter::emitPtrauthCheckAuthenticatedValue(
1873 if (Method == AuthCheckMethod::None)
1875 if (Method == AuthCheckMethod::DummyLoad) {
1880 assert(ShouldTrap && !OnFailure &&
"DummyLoad always traps on error");
1884 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
1885 if (Method == AuthCheckMethod::XPAC || Method == AuthCheckMethod::XPACHint) {
1887 emitMovXReg(ScratchReg, TestedReg);
1889 if (Method == AuthCheckMethod::XPAC) {
1893 MCInstBuilder(XPACOpc).addReg(ScratchReg).addReg(ScratchReg));
1898 assert(TestedReg == AArch64::LR &&
1899 "XPACHint mode is only compatible with checking the LR register");
1901 "XPACHint mode is only compatible with I-keys");
1907 .addReg(AArch64::XZR)
1917 }
else if (Method == AuthCheckMethod::HighBitsNoTBI) {
1935 assert(!OnFailure &&
"Cannot specify OnFailure with ShouldTrap");
1938 EmitToStreamer(
MCInstBuilder(AArch64::BRK).addImm(0xc470 | Key));
1952 case AuthCheckMethod::XPACHint:
1955 case AuthCheckMethod::XPAC:
1957 emitMovXReg(TestedReg, ScratchReg);
1964 MCInstBuilder(XPACOpc).addReg(TestedReg).addReg(TestedReg));
1984void AArch64AsmPrinter::emitPtrauthTailCallHardening(
const MachineInstr *TC) {
1985 if (!AArch64FI->shouldSignReturnAddress(*MF))
1988 auto LRCheckMethod = STI->getAuthenticatedLRCheckMethod(*MF);
1989 if (LRCheckMethod == AArch64PAuth::AuthCheckMethod::None)
1996 "Neither x16 nor x17 is available as a scratch register");
1999 emitPtrauthCheckAuthenticatedValue(
2000 AArch64::LR, ScratchReg, Key, LRCheckMethod,
2004void AArch64AsmPrinter::emitPtrauthAuthResign(
const MachineInstr *
MI) {
2005 const bool IsAUTPAC =
MI->getOpcode() == AArch64::AUTPAC;
2019 bool ShouldCheck =
true;
2021 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
2026 ShouldCheck = ShouldTrap =
false;
2033 ShouldCheck = ShouldTrap =
false;
2040 ShouldCheck = ShouldTrap =
true;
2045 uint64_t AUTDisc =
MI->getOperand(1).getImm();
2046 unsigned AUTAddrDisc =
MI->getOperand(2).getReg();
2049 assert(isUInt<16>(AUTDisc));
2051 emitPtrauthDiscriminator(AUTDisc, AUTAddrDisc, AArch64::X17);
2052 bool AUTZero = AUTDiscReg == AArch64::XZR;
2063 EmitToStreamer(*OutStreamer, AUTInst);
2066 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap))
2072 if (IsAUTPAC && !ShouldTrap)
2073 EndSym = createTempSymbol(
"resign_end_");
2075 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AUTKey,
2076 AArch64PAuth::AuthCheckMethod::XPAC,
2077 ShouldTrap, EndSym);
2087 uint64_t PACDisc =
MI->getOperand(4).getImm();
2088 unsigned PACAddrDisc =
MI->getOperand(5).getReg();
2091 assert(isUInt<16>(PACDisc));
2093 emitPtrauthDiscriminator(PACDisc, PACAddrDisc, AArch64::X17);
2094 bool PACZero = PACDiscReg == AArch64::XZR;
2105 EmitToStreamer(*OutStreamer, PACInst);
2112void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2113 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2114 unsigned BrTarget =
MI->getOperand(0).getReg();
2118 "Invalid auth call key");
2121 assert(isUInt<16>(Disc));
2123 unsigned AddrDisc =
MI->getOperand(3).getReg();
2129 if (BrTarget == AddrDisc)
2137 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17,
2139 bool IsZeroDisc = DiscReg == AArch64::XZR;
2144 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
2146 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
2149 Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
2151 Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
2159 EmitToStreamer(*OutStreamer, BRInst);
2169 getDataLayout(),
Offset,
true);
2171 auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
2177 "cannot resolve target base/addend of ptrauth constant");
2195 "' out of range [0, " +
2199 if (!isUInt<16>(Disc))
2201 "' out of range [0, 0xFFFF]");
2208void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2209 unsigned DstReg =
MI.getOperand(0).getReg();
2211 const uint64_t KeyC =
MI.getOperand(2).getImm();
2213 "key is out of range [0, AArch64PACKey::LAST]");
2215 const uint64_t Disc =
MI.getOperand(3).getImm();
2216 assert(isUInt<16>(Disc) &&
2217 "constant discriminator is out of range [0, 0xffff]");
2226 if (
TM.getTargetTriple().isOSBinFormatELF()) {
2231 "non-zero offset for $auth_ptr$ stub slots is not supported");
2233 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym, Key, Disc);
2235 assert(
TM.getTargetTriple().isOSBinFormatMachO() &&
2236 "LOADauthptrstatic is implemented only for MachO/ELF");
2239 getObjFileLowering());
2242 "non-zero offset for $auth_ptr$ stub slots is not supported");
2244 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(TM, MMI, GASym, Key, Disc);
2253 MCInstLowering.lowerOperand(StubMOHi, StubMCHi);
2254 MCInstLowering.lowerOperand(StubMOLo, StubMCLo);
2267 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2268 const bool IsELFSignedGOT =
MI.getParent()
2271 ->hasELFSignedGOT();
2273 const uint64_t KeyC =
MI.getOperand(1).getImm();
2275 "key is out of range [0, AArch64PACKey::LAST]");
2277 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2278 const uint64_t Disc =
MI.getOperand(3).getImm();
2279 assert(isUInt<16>(Disc) &&
2280 "constant discriminator is out of range [0, 0xffff]");
2337 MCInstLowering.lowerOperand(GAMOHi, GAMCHi);
2338 MCInstLowering.lowerOperand(GAMOLo, GAMCLo);
2342 .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2346 if (IsELFSignedGOT) {
2348 .addReg(AArch64::X17)
2349 .addReg(AArch64::X17)
2354 .addReg(AArch64::X16)
2355 .addReg(AArch64::X17)
2365 .addReg(AArch64::X16)
2366 .addReg(AArch64::X16)
2367 .addReg(AArch64::X17));
2369 if (!STI->hasFPAC()) {
2373 emitPtrauthCheckAuthenticatedValue(AArch64::X16, AArch64::X17, AuthKey,
2374 AArch64PAuth::AuthCheckMethod::XPAC,
2380 .addReg(AArch64::X16)
2381 .addReg(AArch64::X16)
2386 .addReg(AArch64::X16)
2387 .addReg(AArch64::X16)
2394 const bool IsNeg =
Offset < 0;
2395 if (isUInt<24>(AbsOffset)) {
2396 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2400 .addReg(AArch64::X16)
2401 .addReg(AArch64::X16)
2402 .addImm((AbsOffset >> BitPos) & 0xfff)
2407 EmitToStreamer(
MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2408 .addReg(AArch64::X17)
2409 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
2411 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
2412 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2413 uint64_t Shifted = UOffset >> BitPos;
2415 return Shifted != 0;
2416 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2417 if (((Shifted >>
I) & 0xffff) != 0xffff)
2421 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2422 emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
2425 .addReg(AArch64::X16)
2426 .addReg(AArch64::X16)
2427 .addReg(AArch64::X17)
2432 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17);
2437 if (DiscReg != AArch64::XZR)
2439 EmitToStreamer(MIB);
2442void AArch64AsmPrinter::LowerLOADgotAUTH(
const MachineInstr &
MI) {
2444 Register AuthResultReg = STI->hasFPAC() ? DstReg : AArch64::X16;
2450 MCInstLowering.lowerOperand(GAMO, GAMC);
2454 .addReg(AuthResultReg)
2455 .addReg(AArch64::X17)
2464 MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
2465 MCInstLowering.lowerOperand(GALoOp, GAMCLo);
2471 .addReg(AArch64::X17)
2472 .addReg(AArch64::X17)
2477 .addReg(AuthResultReg)
2478 .addReg(AArch64::X17)
2485 UndefWeakSym = createTempSymbol(
"undef_weak");
2488 .addReg(AuthResultReg)
2497 .addReg(AuthResultReg)
2498 .addReg(AuthResultReg)
2499 .addReg(AArch64::X17));
2504 if (!STI->hasFPAC()) {
2508 emitPtrauthCheckAuthenticatedValue(AuthResultReg, AArch64::X17, AuthKey,
2509 AArch64PAuth::AuthCheckMethod::XPAC,
2513 emitMovXReg(DstReg, AuthResultReg);
2518AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2522 if (std::optional<uint16_t> BADisc =
2523 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2532#include "AArch64GenMCPseudoLowering.inc"
2542 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
2547 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
2552 if (
MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
2553 EmitToStreamer(*OutStreamer, OutInst);
2557 if (
MI->getOpcode() == AArch64::ADRP) {
2558 for (
auto &Opd :
MI->operands()) {
2559 if (Opd.isSymbol() &&
StringRef(Opd.getSymbolName()) ==
2560 "swift_async_extendedFramePointerFlags") {
2561 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
2566 if (AArch64FI->getLOHRelated().count(
MI)) {
2568 MCSymbol *LOHLabel = createTempSymbol(
"loh");
2570 LOHInstToLabel[
MI] = LOHLabel;
2577 switch (
MI->getOpcode()) {
2580 "Unhandled tail call instruction");
2582 case AArch64::HINT: {
2587 if (CurrentPatchableFunctionEntrySym &&
2588 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
2589 MI == &MF->front().front()) {
2590 int64_t
Imm =
MI->getOperand(0).getImm();
2591 if ((Imm & 32) && (Imm & 6)) {
2593 MCInstLowering.Lower(
MI, Inst);
2594 EmitToStreamer(*OutStreamer, Inst);
2595 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
2596 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
2602 case AArch64::MOVMCSym: {
2603 Register DestReg =
MI->getOperand(0).getReg();
2611 MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
2612 MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
2619 EmitToStreamer(*OutStreamer, MovZ);
2627 EmitToStreamer(*OutStreamer, MovK);
2630 case AArch64::MOVIv2d_ns:
2638 if (STI->hasZeroCycleZeroingFPWorkaround() &&
2639 MI->getOperand(1).getImm() == 0) {
2641 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
2644 EmitToStreamer(*OutStreamer, TmpInst);
2649 case AArch64::DBG_VALUE:
2650 case AArch64::DBG_VALUE_LIST:
2654 PrintDebugValueComment(
MI,
OS);
2659 case AArch64::EMITBKEY: {
2661 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2662 ExceptionHandlingType != ExceptionHandling::ARM)
2665 if (getFunctionCFISectionType(*MF) == CFISection::None)
2672 case AArch64::EMITMTETAGGED: {
2674 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2675 ExceptionHandlingType != ExceptionHandling::ARM)
2678 if (getFunctionCFISectionType(*MF) != CFISection::None)
2684 case AArch64::AUTPAC:
2685 emitPtrauthAuthResign(
MI);
2688 case AArch64::LOADauthptrstatic:
2689 LowerLOADauthptrstatic(*
MI);
2692 case AArch64::LOADgotPAC:
2693 case AArch64::MOVaddrPAC:
2694 LowerMOVaddrPAC(*
MI);
2697 case AArch64::LOADgotAUTH:
2698 LowerLOADgotAUTH(*
MI);
2703 emitPtrauthBranch(
MI);
2709 case AArch64::AUTH_TCRETURN:
2710 case AArch64::AUTH_TCRETURN_BTI: {
2714 "Invalid auth key for tail-call return");
2716 const uint64_t Disc =
MI->getOperand(3).getImm();
2717 assert(isUInt<16>(Disc) &&
"Integer discriminator is too wide");
2719 Register AddrDisc =
MI->getOperand(4).getReg();
2721 Register ScratchReg =
Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16;
2723 emitPtrauthTailCallHardening(
MI);
2726 if (Callee == AddrDisc)
2728 Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg,
2731 const bool IsZero = DiscReg == AArch64::XZR;
2732 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
2733 {AArch64::BRAB, AArch64::BRABZ}};
2736 TmpInst.
setOpcode(Opcodes[Key][IsZero]);
2740 EmitToStreamer(*OutStreamer, TmpInst);
2744 case AArch64::TCRETURNri:
2745 case AArch64::TCRETURNrix16x17:
2746 case AArch64::TCRETURNrix17:
2747 case AArch64::TCRETURNrinotx16:
2748 case AArch64::TCRETURNriALL: {
2749 emitPtrauthTailCallHardening(
MI);
2751 recordIfImportCall(
MI);
2755 EmitToStreamer(*OutStreamer, TmpInst);
2758 case AArch64::TCRETURNdi: {
2759 emitPtrauthTailCallHardening(
MI);
2762 MCInstLowering.lowerOperand(
MI->getOperand(0), Dest);
2763 recordIfImportCall(
MI);
2767 EmitToStreamer(*OutStreamer, TmpInst);
2770 case AArch64::SpeculationBarrierISBDSBEndBB: {
2775 EmitToStreamer(*OutStreamer, TmpInstDSB);
2779 EmitToStreamer(*OutStreamer, TmpInstISB);
2782 case AArch64::SpeculationBarrierSBEndBB: {
2786 EmitToStreamer(*OutStreamer, TmpInstSB);
2789 case AArch64::TLSDESC_AUTH_CALLSEQ: {
2801 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2802 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2808 EmitToStreamer(*OutStreamer, Adrp);
2816 EmitToStreamer(*OutStreamer, Ldr);
2819 Add.setOpcode(AArch64::ADDXri);
2822 Add.addOperand(SymTLSDescLo12);
2824 EmitToStreamer(*OutStreamer,
Add);
2833 EmitToStreamer(*OutStreamer, Blraa);
2837 case AArch64::TLSDESC_CALLSEQ: {
2850 MCInstLowering.lowerOperand(MO_Sym,
Sym);
2851 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2852 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2858 EmitToStreamer(*OutStreamer, Adrp);
2861 if (STI->isTargetILP32()) {
2871 EmitToStreamer(*OutStreamer, Ldr);
2874 if (STI->isTargetILP32()) {
2875 Add.setOpcode(AArch64::ADDWri);
2879 Add.setOpcode(AArch64::ADDXri);
2883 Add.addOperand(SymTLSDescLo12);
2885 EmitToStreamer(*OutStreamer,
Add);
2890 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
2892 EmitToStreamer(*OutStreamer, TLSDescCall);
2900 EmitToStreamer(*OutStreamer, Blr);
2905 case AArch64::JumpTableDest32:
2906 case AArch64::JumpTableDest16:
2907 case AArch64::JumpTableDest8:
2908 LowerJumpTableDest(*OutStreamer, *
MI);
2911 case AArch64::BR_JumpTable:
2912 LowerHardenedBRJumpTable(*
MI);
2915 case AArch64::FMOVH0:
2916 case AArch64::FMOVS0:
2917 case AArch64::FMOVD0:
2921 case AArch64::MOPSMemoryCopyPseudo:
2922 case AArch64::MOPSMemoryMovePseudo:
2923 case AArch64::MOPSMemorySetPseudo:
2924 case AArch64::MOPSMemorySetTaggingPseudo:
2925 LowerMOPS(*OutStreamer, *
MI);
2928 case TargetOpcode::STACKMAP:
2929 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
2931 case TargetOpcode::PATCHPOINT:
2932 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
2934 case TargetOpcode::STATEPOINT:
2935 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
2937 case TargetOpcode::FAULTING_OP:
2938 return LowerFAULTING_OP(*
MI);
2940 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2941 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
2944 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2945 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
2948 case TargetOpcode::PATCHABLE_TAIL_CALL:
2949 LowerPATCHABLE_TAIL_CALL(*
MI);
2951 case TargetOpcode::PATCHABLE_EVENT_CALL:
2952 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
2953 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
2954 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
2956 case AArch64::KCFI_CHECK:
2957 LowerKCFI_CHECK(*
MI);
2960 case AArch64::HWASAN_CHECK_MEMACCESS:
2961 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
2962 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
2963 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
2964 LowerHWASAN_CHECK_MEMACCESS(*
MI);
2967 case AArch64::SEH_StackAlloc:
2971 case AArch64::SEH_SaveFPLR:
2975 case AArch64::SEH_SaveFPLR_X:
2976 assert(
MI->getOperand(0).getImm() < 0 &&
2977 "Pre increment SEH opcode must have a negative offset");
2981 case AArch64::SEH_SaveReg:
2983 MI->getOperand(1).getImm());
2986 case AArch64::SEH_SaveReg_X:
2987 assert(
MI->getOperand(1).getImm() < 0 &&
2988 "Pre increment SEH opcode must have a negative offset");
2990 -
MI->getOperand(1).getImm());
2993 case AArch64::SEH_SaveRegP:
2994 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
2995 MI->getOperand(0).getImm() <= 28) {
2996 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
2997 "Register paired with LR must be odd");
2999 MI->getOperand(2).getImm());
3002 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3003 "Non-consecutive registers not allowed for save_regp");
3005 MI->getOperand(2).getImm());
3008 case AArch64::SEH_SaveRegP_X:
3009 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3010 "Non-consecutive registers not allowed for save_regp_x");
3011 assert(
MI->getOperand(2).getImm() < 0 &&
3012 "Pre increment SEH opcode must have a negative offset");
3014 -
MI->getOperand(2).getImm());
3017 case AArch64::SEH_SaveFReg:
3019 MI->getOperand(1).getImm());
3022 case AArch64::SEH_SaveFReg_X:
3023 assert(
MI->getOperand(1).getImm() < 0 &&
3024 "Pre increment SEH opcode must have a negative offset");
3026 -
MI->getOperand(1).getImm());
3029 case AArch64::SEH_SaveFRegP:
3030 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3031 "Non-consecutive registers not allowed for save_regp");
3033 MI->getOperand(2).getImm());
3036 case AArch64::SEH_SaveFRegP_X:
3037 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
3038 "Non-consecutive registers not allowed for save_regp_x");
3039 assert(
MI->getOperand(2).getImm() < 0 &&
3040 "Pre increment SEH opcode must have a negative offset");
3042 -
MI->getOperand(2).getImm());
3045 case AArch64::SEH_SetFP:
3049 case AArch64::SEH_AddFP:
3053 case AArch64::SEH_Nop:
3057 case AArch64::SEH_PrologEnd:
3061 case AArch64::SEH_EpilogStart:
3065 case AArch64::SEH_EpilogEnd:
3069 case AArch64::SEH_PACSignLR:
3073 case AArch64::SEH_SaveAnyRegQP:
3074 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3075 "Non-consecutive registers not allowed for save_any_reg");
3076 assert(
MI->getOperand(2).getImm() >= 0 &&
3077 "SaveAnyRegQP SEH opcode offset must be non-negative");
3078 assert(
MI->getOperand(2).getImm() <= 1008 &&
3079 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
3081 MI->getOperand(2).getImm());
3084 case AArch64::SEH_SaveAnyRegQPX:
3085 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
3086 "Non-consecutive registers not allowed for save_any_reg");
3087 assert(
MI->getOperand(2).getImm() < 0 &&
3088 "SaveAnyRegQPX SEH opcode offset must be negative");
3089 assert(
MI->getOperand(2).getImm() >= -1008 &&
3090 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
3092 -
MI->getOperand(2).getImm());
3097 recordIfImportCall(
MI);
3099 MCInstLowering.Lower(
MI, TmpInst);
3100 EmitToStreamer(*OutStreamer, TmpInst);
3106 MCInstLowering.Lower(
MI, TmpInst);
3107 EmitToStreamer(*OutStreamer, TmpInst);
3110void AArch64AsmPrinter::recordIfImportCall(
3113 !
TM.getTargetTriple().isOSBinFormatCOFF())
3117 if (GV && GV->hasDLLImportStorageClass()) {
3118 auto *CallSiteSymbol = MMI->
getContext().createNamedTempSymbol(
"impcall");
3121 auto *CalledSymbol = MCInstLowering.GetGlobalValueSymbol(GV, OpFlags);
3123 .push_back({CallSiteSymbol, CalledSymbol});
3140 MCInstLowering.lowerOperand(
3145 EmitToStreamer(Adrp);
3154 MCInstLowering.lowerOperand(
3160 EmitToStreamer(Ldr);
3164 .addReg(AArch64::X16)
3165 .addReg(AArch64::X16)
3168 EmitToStreamer(
MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3173void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
3208 .addReg(AArch64::SP)
3209 .addReg(AArch64::FP)
3210 .addReg(AArch64::LR)
3211 .addReg(AArch64::SP)
3215 .addReg(AArch64::FP)
3216 .addReg(AArch64::SP)
3220 for (
int I = 0;
I != 4; ++
I)
3222 .addReg(AArch64::SP)
3223 .addReg(AArch64::X1 + 2 *
I)
3224 .addReg(AArch64::X0 + 2 *
I)
3225 .addReg(AArch64::SP)
3228 for (
int I = 0;
I != 4; ++
I)
3230 .addReg(AArch64::SP)
3231 .addReg(AArch64::D1 + 2 *
I)
3232 .addReg(AArch64::D0 + 2 *
I)
3233 .addReg(AArch64::SP)
3245 MCInstLowering.lowerOperand(
3250 EmitToStreamer(Adrp);
3259 MCInstLowering.lowerOperand(
3265 EmitToStreamer(Ldr);
3269 .addReg(AArch64::X0)
3270 .addReg(AArch64::X16)
3274 .addReg(AArch64::X16)
3275 .addReg(AArch64::X0)
3279 for (
int I = 3;
I != -1; --
I)
3281 .addReg(AArch64::SP)
3282 .addReg(AArch64::D1 + 2 *
I)
3283 .addReg(AArch64::D0 + 2 *
I)
3284 .addReg(AArch64::SP)
3287 for (
int I = 3;
I != -1; --
I)
3289 .addReg(AArch64::SP)
3290 .addReg(AArch64::X1 + 2 *
I)
3291 .addReg(AArch64::X0 + 2 *
I)
3292 .addReg(AArch64::SP)
3296 .addReg(AArch64::SP)
3297 .addReg(AArch64::FP)
3298 .addReg(AArch64::LR)
3299 .addReg(AArch64::SP)
3302 EmitToStreamer(
MCInstBuilder(
TM.getTargetTriple().isArm64e() ? AArch64::BRAAZ
3307const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV) {
3308 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 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()
void emitNoteSection(unsigned Flags, uint64_t PAuthABIPlatform=-1, uint64_t PAuthABIVersion=-1)
Callback used to implement the .note.gnu.property section.
virtual void emitARM64WinCFISaveReg(unsigned Reg, int Offset)
virtual void emitARM64WinCFINop()
virtual void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset)
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.
@ 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,...