77 cl::desc(
"Check pointer authentication auth/resign failures"),
80#define DEBUG_TYPE "asm-printer"
88 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
91 AArch64AsmPrinter(
TargetMachine &
TM, std::unique_ptr<MCStreamer> Streamer)
92 :
AsmPrinter(
TM, std::move(Streamer)), MCInstLowering(OutContext, *
this),
112 const MCSymbol *BranchLabel)
const override;
135 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
137 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
138 HwasanMemaccessTuple;
139 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
142 void emitHwasanMemaccessSymbols(
Module &M);
153 unsigned emitPtrauthDiscriminator(
uint16_t Disc,
unsigned AddrDisc,
154 unsigned &InstsEmitted);
169 void emitFunctionHeaderComment()
override;
182 if (STI->isTargetCOFF()) {
235 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
237 MInstToMCSymbol LOHInstToLabel;
240 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
255void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
258 if (
TT.isOSBinFormatCOFF()) {
261 OutStreamer->beginCOFFSymbolDef(S);
264 OutStreamer->endCOFFSymbolDef();
265 int64_t Feat00Value = 0;
267 if (
M.getModuleFlag(
"cfguard")) {
269 Feat00Value |= COFF::Feat00Flags::GuardCF;
272 if (
M.getModuleFlag(
"ehcontguard")) {
274 Feat00Value |= COFF::Feat00Flags::GuardEHCont;
277 if (
M.getModuleFlag(
"ms-kernel")) {
279 Feat00Value |= COFF::Feat00Flags::Kernel;
283 OutStreamer->emitAssignment(
287 if (!
TT.isOSBinFormatELF())
292 if (
const auto *BTE = mdconst::extract_or_null<ConstantInt>(
293 M.getModuleFlag(
"branch-target-enforcement")))
297 if (
const auto *GCS = mdconst::extract_or_null<ConstantInt>(
298 M.getModuleFlag(
"guarded-control-stack")))
302 if (
const auto *Sign = mdconst::extract_or_null<ConstantInt>(
303 M.getModuleFlag(
"sign-return-address")))
308 if (
const auto *PAP = mdconst::extract_or_null<ConstantInt>(
309 M.getModuleFlag(
"aarch64-elf-pauthabi-platform")))
310 PAuthABIPlatform = PAP->getZExtValue();
312 if (
const auto *PAV = mdconst::extract_or_null<ConstantInt>(
313 M.getModuleFlag(
"aarch64-elf-pauthabi-version")))
314 PAuthABIVersion = PAV->getZExtValue();
322void AArch64AsmPrinter::emitFunctionHeaderComment() {
325 if (OutlinerString != std::nullopt)
326 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
329void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
332 if (
F.hasFnAttribute(
"patchable-function-entry")) {
334 if (
F.getFnAttribute(
"patchable-function-entry")
336 .getAsInteger(10, Num))
342 emitSled(
MI, SledKind::FUNCTION_ENTER);
345void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
346 emitSled(
MI, SledKind::FUNCTION_EXIT);
349void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
350 emitSled(
MI, SledKind::TAIL_CALL);
353void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
354 static const int8_t NoopsInSledCount = 7;
375 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
376 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
377 OutStreamer->emitLabel(CurSled);
378 auto Target = OutContext.createTempSymbol();
383 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::B).addImm(8));
385 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
386 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
388 OutStreamer->emitLabel(
Target);
389 recordSled(CurSled,
MI, Kind, 2);
407void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
409 auto &
O = *OutStreamer;
410 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
411 O.emitLabel(CurSled);
422 bool MachO =
TM.getTargetTriple().isOSBinFormatMachO();
424 OutContext.getOrCreateSymbol(
425 Twine(MachO ?
"_" :
"") +
426 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
429 O.AddComment(
"Begin XRay typed event");
441 EmitToStreamer(O, MovX0Op0);
442 EmitToStreamer(O, MovX1Op1);
445 .addReg(AArch64::XZR)
446 .addReg(
MI.getOperand(2).getReg())
453 O.AddComment(
"End XRay typed event");
461 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
463 O.AddComment(
"Begin XRay custom event");
471 EmitToStreamer(O, MovX0Op0);
472 EmitToStreamer(O, MovX1Op1);
474 O.AddComment(
"End XRay custom event");
482 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
488 assert(std::next(
MI.getIterator())->isCall() &&
489 "KCFI_CHECK not followed by a call instruction");
490 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
491 "KCFI_CHECK call target doesn't match call operand");
495 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
496 if (AddrReg == AArch64::XZR) {
502 .addReg(AArch64::XZR)
503 .addReg(AArch64::XZR)
510 for (
auto &Reg : ScratchRegs) {
516 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
517 "Invalid scratch registers for KCFI_CHECK");
521 int64_t PrefixNops = 0;
524 .getFnAttribute(
"patchable-function-prefix")
526 .getAsInteger(10, PrefixNops);
530 .addReg(ScratchRegs[0])
532 .addImm(-(PrefixNops * 4 + 4)));
536 const int64_t
Type =
MI.getOperand(1).getImm();
538 .addReg(ScratchRegs[1])
539 .addReg(ScratchRegs[1])
540 .addImm(
Type & 0xFFFF)
543 .addReg(ScratchRegs[1])
544 .addReg(ScratchRegs[1])
545 .addImm((
Type >> 16) & 0xFFFF)
550 .addReg(AArch64::WZR)
551 .addReg(ScratchRegs[0])
552 .addReg(ScratchRegs[1])
556 EmitToStreamer(*OutStreamer,
566 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
570 AddrIndex = AddrReg - AArch64::X0;
580 assert(AddrIndex < 31 && TypeIndex < 31);
582 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
583 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BRK).addImm(ESR));
584 OutStreamer->emitLabel(
Pass);
587void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
590 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
592 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
593 uint32_t AccessInfo =
MI.getOperand(1).getImm();
595 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
597 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
598 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
600 MCSymbol *&
Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
601 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
604 if (!
TM.getTargetTriple().isOSBinFormatELF())
607 std::string SymName =
"__hwasan_check_x" + utostr(Reg - AArch64::X0) +
"_" +
610 SymName +=
"_fixed_" + utostr(FixedShadowOffset);
612 SymName +=
"_short_v2";
613 Sym = OutContext.getOrCreateSymbol(SymName);
616 EmitToStreamer(*OutStreamer,
621void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
622 if (HwasanMemaccessSymbols.empty())
627 std::unique_ptr<MCSubtargetInfo> STI(
628 TM.getTarget().createMCSubtargetInfo(
TT.str(),
"",
""));
629 assert(STI &&
"Unable to create subtarget info");
632 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
634 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
641 for (
auto &
P : HwasanMemaccessSymbols) {
642 unsigned Reg = std::get<0>(
P.first);
643 bool IsShort = std::get<1>(
P.first);
644 uint32_t AccessInfo = std::get<2>(
P.first);
645 bool IsFixedShadow = std::get<3>(
P.first);
646 uint64_t FixedShadowOffset = std::get<4>(
P.first);
648 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
651 bool HasMatchAllTag =
653 uint8_t MatchAllTag =
660 OutStreamer->switchSection(OutContext.getELFSection(
668 OutStreamer->emitLabel(
Sym);
684 .
addImm(FixedShadowOffset >> 32)
687 OutStreamer->emitInstruction(
MCInstBuilder(AArch64::LDRBBroX)
695 OutStreamer->emitInstruction(
698 .
addReg(IsShort ? AArch64::X20 : AArch64::X9)
705 OutStreamer->emitInstruction(
712 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
713 OutStreamer->emitInstruction(
719 MCSymbol *ReturnSym = OutContext.createTempSymbol();
720 OutStreamer->emitLabel(ReturnSym);
721 OutStreamer->emitInstruction(
723 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
725 if (HasMatchAllTag) {
738 OutStreamer->emitInstruction(
752 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
753 OutStreamer->emitInstruction(
759 OutStreamer->emitInstruction(
778 OutStreamer->emitInstruction(
784 OutStreamer->emitInstruction(
795 OutStreamer->emitInstruction(
802 OutStreamer->emitInstruction(
808 OutStreamer->emitLabel(HandleMismatchSym);
825 if (Reg != AArch64::X0)
832 OutStreamer->emitInstruction(
843 OutStreamer->emitInstruction(
849 OutStreamer->emitInstruction(
853 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
856 OutStreamer->emitInstruction(
861 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
864 OutStreamer->emitInstruction(
872 const MCExpr *StubAuthPtrRef) {
875 OutStreamer.
emitValue(StubAuthPtrRef, 8);
878void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
879 emitHwasanMemaccessSymbols(M);
882 if (
TT.isOSBinFormatMachO()) {
889 if (!Stubs.empty()) {
891 OutStreamer->switchSection(
894 emitAlignment(
Align(8));
896 for (
const auto &Stub : Stubs)
899 OutStreamer->addBlankLine();
910 if (
TT.isOSBinFormatELF()) {
916 if (!Stubs.empty()) {
919 emitAlignment(
Align(8));
921 for (
const auto &Stub : Stubs)
924 OutStreamer->addBlankLine();
929 FM.serializeToFaultMapSection();
933void AArch64AsmPrinter::emitLOHs() {
936 for (
const auto &
D : AArch64FI->getLOHContainer()) {
938 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
939 assert(LabelIt != LOHInstToLabel.end() &&
940 "Label hasn't been inserted for LOH related instruction");
943 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
948void AArch64AsmPrinter::emitFunctionBodyEnd() {
949 if (!AArch64FI->getLOHRelated().empty())
954MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
958 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
959 return OutContext.getOrCreateSymbol(
960 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
961 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
966void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
984 PrintSymbolOperand(MO, O);
995bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1019bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1022 assert(MO.
isReg() &&
"Should only get here with a register!");
1032bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1041 if (ExtraCode && ExtraCode[0]) {
1042 if (ExtraCode[1] != 0)
1045 switch (ExtraCode[0]) {
1053 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1067 switch (ExtraCode[0]) {
1069 RC = &AArch64::FPR8RegClass;
1072 RC = &AArch64::FPR16RegClass;
1075 RC = &AArch64::FPR32RegClass;
1078 RC = &AArch64::FPR64RegClass;
1081 RC = &AArch64::FPR128RegClass;
1084 RC = &AArch64::ZPRRegClass;
1089 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1102 if (AArch64::GPR32allRegClass.
contains(Reg) ||
1103 AArch64::GPR64allRegClass.
contains(Reg))
1107 if (AArch64::GPR64x8ClassRegClass.
contains(Reg))
1110 unsigned AltName = AArch64::NoRegAltName;
1112 if (AArch64::ZPRRegClass.
contains(Reg)) {
1113 RegClass = &AArch64::ZPRRegClass;
1114 }
else if (AArch64::PPRRegClass.
contains(Reg)) {
1115 RegClass = &AArch64::PPRRegClass;
1116 }
else if (AArch64::PNRRegClass.
contains(Reg)) {
1117 RegClass = &AArch64::PNRRegClass;
1119 RegClass = &AArch64::FPR128RegClass;
1120 AltName = AArch64::vreg;
1124 return printAsmRegInClass(MO, RegClass, AltName, O);
1131bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1133 const char *ExtraCode,
1135 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1139 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1144void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1146 unsigned NOps =
MI->getNumOperands();
1148 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1150 OS <<
MI->getDebugVariable()->getName();
1153 assert(
MI->isIndirectDebugValue());
1155 for (
unsigned I = 0, E = std::distance(
MI->debug_operands().begin(),
1156 MI->debug_operands().end());
1167void AArch64AsmPrinter::emitJumpTableInfo() {
1172 if (
JT.empty())
return;
1176 OutStreamer->switchSection(ReadOnlySec);
1179 for (
unsigned JTI = 0, e =
JT.size(); JTI !=
e; ++JTI) {
1180 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1183 if (JTBBs.empty())
continue;
1185 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1187 OutStreamer->emitLabel(GetJTISymbol(JTI));
1189 const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1192 for (
auto *JTBB : JTBBs) {
1212AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1214 const MCSymbol *BranchLabel)
const {
1216 const auto Base = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1218 switch (AFI->getJumpTableEntrySize(JTI)) {
1220 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1223 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1226 EntrySize = codeview::JumpTableEntrySize::Int32;
1231 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1234void AArch64AsmPrinter::emitFunctionEntryLabel() {
1236 MF->getFunction().getCallingConv() ==
1246 if (
TM.getTargetTriple().isWindowsArm64EC() &&
1247 !MF->getFunction().hasLocalLinkage()) {
1252 OutStreamer->emitAssignment(
1254 MMI->getContext()));
1260 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1261 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1267 getSymbolFromMetadata(
"arm64ec_unmangled_name")) {
1268 MCSymbol *ECMangledSym = getSymbolFromMetadata(
"arm64ec_ecmangled_name");
1274 emitFunctionAlias(UnmangledSym, ECMangledSym);
1275 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1279 emitFunctionAlias(UnmangledSym, CurrentFnSym);
1285void AArch64AsmPrinter::emitXXStructor(
const DataLayout &
DL,
1287 if (
const auto *CPA = dyn_cast<ConstantPtrAuth>(CV))
1288 if (CPA->hasAddressDiscriminator() &&
1289 !CPA->hasSpecialAddressDiscriminator(
1292 "unexpected address discrimination value for ctors/dtors entry, only "
1293 "'ptr inttoptr (i64 1 to ptr)' is allowed");
1302void AArch64AsmPrinter::emitGlobalAlias(
const Module &M,
1304 if (
auto F = dyn_cast_or_null<Function>(GA.
getAliasee())) {
1309 if (
MDNode *
Node =
F->getMetadata(
"arm64ec_exp_name")) {
1310 StringRef ExpStr = cast<MDString>(
Node->getOperand(0))->getString();
1311 MCSymbol *ExpSym = MMI->getContext().getOrCreateSymbol(ExpStr);
1314 OutStreamer->beginCOFFSymbolDef(ExpSym);
1318 OutStreamer->endCOFFSymbolDef();
1320 OutStreamer->beginCOFFSymbolDef(
Sym);
1324 OutStreamer->endCOFFSymbolDef();
1326 OutStreamer->emitAssignment(
1328 MMI->getContext()));
1346 Register DestReg =
MI.getOperand(0).getReg();
1347 Register ScratchReg =
MI.getOperand(1).getReg();
1349 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1350 Register TableReg =
MI.getOperand(2).getReg();
1351 Register EntryReg =
MI.getOperand(3).getReg();
1352 int JTIdx =
MI.getOperand(4).getIndex();
1353 int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
1363 Label = MF->getContext().createTempSymbol();
1364 AArch64FI->setJumpTableEntryInfo(JTIdx,
Size, Label);
1371 .addExpr(LabelExpr));
1376 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1377 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1378 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1384 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1388 .addImm(
Size == 1 ? 0 : 1));
1396 .addImm(
Size == 4 ? 0 : 2));
1399void AArch64AsmPrinter::LowerHardenedBRJumpTable(
const MachineInstr &
MI) {
1400 unsigned InstsEmitted = 0;
1403 assert(MJTI &&
"Can't lower jump-table dispatch without JTI");
1405 const std::vector<MachineJumpTableEntry> &JTs = MJTI->
getJumpTables();
1406 assert(!JTs.empty() &&
"Invalid JT index for jump-table dispatch");
1425 assert(!AArch64FI->getJumpTableEntryPCRelSymbol(JTI) &&
1426 "unsupported compressed jump table");
1428 const uint64_t NumTableEntries = JTs[JTI].MBBs.size();
1432 uint64_t MaxTableEntry = NumTableEntries - 1;
1433 if (isUInt<12>(MaxTableEntry)) {
1434 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXri)
1435 .addReg(AArch64::XZR)
1436 .addReg(AArch64::X16)
1437 .addImm(MaxTableEntry)
1441 EmitToStreamer(*OutStreamer,
1443 .addReg(AArch64::X17)
1444 .addImm(
static_cast<uint16_t>(MaxTableEntry))
1451 if ((MaxTableEntry >>
Offset) == 0)
1453 EmitToStreamer(*OutStreamer,
1455 .addReg(AArch64::X17)
1456 .addReg(AArch64::X17)
1461 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXrs)
1462 .addReg(AArch64::XZR)
1463 .addReg(AArch64::X16)
1464 .addReg(AArch64::X17)
1472 .addReg(AArch64::X16)
1473 .addReg(AArch64::X16)
1474 .addReg(AArch64::XZR)
1485 MCInstLowering.lowerOperand(JTMOHi, JTMCHi);
1486 MCInstLowering.lowerOperand(JTMOLo, JTMCLo);
1494 .addReg(AArch64::X17)
1495 .addReg(AArch64::X17)
1500 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::LDRSWroX)
1501 .addReg(AArch64::X16)
1502 .addReg(AArch64::X17)
1503 .addReg(AArch64::X16)
1508 MCSymbol *AdrLabel = MF->getContext().createTempSymbol();
1510 AArch64FI->setJumpTableEntryInfo(JTI, 4, AdrLabel);
1515 MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE));
1519 .addReg(AArch64::X16)
1520 .addReg(AArch64::X17)
1521 .addReg(AArch64::X16)
1525 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BR).addReg(AArch64::X16));
1529 assert(STI->getInstrInfo()->getInstSizeInBytes(
MI) >= InstsEmitted * 4);
1534 unsigned Opcode =
MI.getOpcode();
1536 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1538 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1539 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1540 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1541 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1542 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1543 if (Opcode == AArch64::MOPSMemorySetPseudo)
1544 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1545 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1546 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1549 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1550 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1552 for (
auto Op : Ops) {
1556 MCIB.addReg(
MI.getOperand(i++).getReg());
1557 MCIB.addReg(
MI.getOperand(i++).getReg());
1559 MCIB.addReg(
MI.getOperand(i++).getReg());
1561 MCIB.addReg(
MI.getOperand(i++).getReg());
1562 MCIB.addReg(
MI.getOperand(i++).getReg());
1563 MCIB.addReg(
MI.getOperand(i++).getReg());
1565 EmitToStreamer(OutStreamer, MCIB);
1574 MCSymbol *MILabel = Ctx.createTempSymbol();
1578 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1584 while (NumNOPBytes > 0) {
1585 if (MII ==
MBB.
end() || MII->isCall() ||
1586 MII->getOpcode() == AArch64::DBG_VALUE ||
1587 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1588 MII->getOpcode() == TargetOpcode::STACKMAP)
1595 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1596 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1604 MCSymbol *MILabel = Ctx.createTempSymbol();
1610 int64_t CallTarget = Opers.getCallTarget().getImm();
1611 unsigned EncodedBytes = 0;
1613 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1614 "High 16 bits of call target should be zero.");
1615 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1620 .addImm((CallTarget >> 32) & 0xFFFF)
1625 .addImm((CallTarget >> 16) & 0xFFFF)
1630 .addImm(CallTarget & 0xFFFF)
1632 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1635 unsigned NumBytes = Opers.getNumPatchBytes();
1636 assert(NumBytes >= EncodedBytes &&
1637 "Patchpoint can't request size less than the length of a call.");
1638 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1639 "Invalid number of NOP bytes requested!");
1640 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1641 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1647 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1648 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1649 for (
unsigned i = 0; i < PatchBytes; i += 4)
1650 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1655 unsigned CallOpcode;
1656 switch (CallTarget.
getType()) {
1659 MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
1660 CallOpcode = AArch64::BL;
1664 CallOpcode = AArch64::BL;
1668 CallOpcode = AArch64::BLR;
1675 EmitToStreamer(OutStreamer,
1680 MCSymbol *MILabel = Ctx.createTempSymbol();
1685void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1694 unsigned OperandsBeginIdx = 4;
1697 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1701 FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
1704 MI.setOpcode(Opcode);
1712 lowerOperand(MO, Dest);
1713 MI.addOperand(Dest);
1721 Register DestReg =
MI.getOperand(0).getReg();
1722 if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() &&
1723 STI->isNeonAvailable()) {
1725 if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
1726 DestReg = AArch64::D0 + (DestReg - AArch64::H0);
1727 else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
1728 DestReg = AArch64::D0 + (DestReg - AArch64::S0);
1730 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
1733 MOVI.setOpcode(AArch64::MOVID);
1736 EmitToStreamer(*OutStreamer, MOVI);
1739 switch (
MI.getOpcode()) {
1741 case AArch64::FMOVH0:
1742 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1743 if (!STI->hasFullFP16())
1744 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1748 case AArch64::FMOVS0:
1753 case AArch64::FMOVD0:
1759 EmitToStreamer(*OutStreamer, FMov);
1763unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(
uint16_t Disc,
1765 unsigned &InstsEmitted) {
1767 if (AddrDisc == AArch64::NoRegister)
1768 AddrDisc = AArch64::XZR;
1776 if (AddrDisc == AArch64::XZR) {
1778 .addReg(AArch64::X17)
1782 return AArch64::X17;
1787 .addReg(AArch64::X17)
1788 .addReg(AArch64::XZR)
1793 .addReg(AArch64::X17)
1794 .addReg(AArch64::X17)
1798 return AArch64::X17;
1801void AArch64AsmPrinter::emitPtrauthAuthResign(
const MachineInstr *
MI) {
1802 unsigned InstsEmitted = 0;
1803 const bool IsAUTPAC =
MI->getOpcode() == AArch64::AUTPAC;
1854 bool ShouldCheck =
true;
1856 bool ShouldTrap = MF->getFunction().hasFnAttribute(
"ptrauth-auth-traps");
1861 ShouldCheck = ShouldTrap =
false;
1868 ShouldCheck = ShouldTrap =
false;
1875 ShouldCheck = ShouldTrap =
true;
1880 uint64_t AUTDisc =
MI->getOperand(1).getImm();
1881 unsigned AUTAddrDisc =
MI->getOperand(2).getReg();
1886 assert(isUInt<16>(AUTDisc));
1887 unsigned AUTDiscReg =
1888 emitPtrauthDiscriminator(AUTDisc, AUTAddrDisc, InstsEmitted);
1889 bool AUTZero = AUTDiscReg == AArch64::XZR;
1900 EmitToStreamer(*OutStreamer, AUTInst);
1904 if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap)) {
1905 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
1913 MCSymbol *SuccessSym = createTempSymbol(
"auth_success_");
1918 .addReg(AArch64::X17)
1919 .addReg(AArch64::XZR)
1920 .addReg(AArch64::X16)
1927 MCInstBuilder(XPACOpc).addReg(AArch64::X17).addReg(AArch64::X17));
1931 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::SUBSXrs)
1932 .addReg(AArch64::XZR)
1933 .addReg(AArch64::X16)
1934 .addReg(AArch64::X17)
1942 SuccessSym, OutContext)));
1948 EmitToStreamer(*OutStreamer,
1959 .addReg(AArch64::X16)
1960 .addReg(AArch64::XZR)
1961 .addReg(AArch64::X17)
1966 EndSym = createTempSymbol(
"resign_end_");
1971 EndSym, OutContext)));
1985 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
1990 uint64_t PACDisc =
MI->getOperand(4).getImm();
1991 unsigned PACAddrDisc =
MI->getOperand(5).getReg();
1994 assert(isUInt<16>(PACDisc));
1995 unsigned PACDiscReg =
1996 emitPtrauthDiscriminator(PACDisc, PACAddrDisc, InstsEmitted);
1997 bool PACZero = PACDiscReg == AArch64::XZR;
2008 EmitToStreamer(*OutStreamer, PACInst);
2011 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
2017void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
2018 unsigned InstsEmitted = 0;
2019 bool IsCall =
MI->getOpcode() == AArch64::BLRA;
2020 unsigned BrTarget =
MI->getOperand(0).getReg();
2024 "Invalid auth call key");
2027 assert(isUInt<16>(Disc));
2029 unsigned AddrDisc =
MI->getOperand(3).getReg();
2032 unsigned DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, InstsEmitted);
2033 bool IsZeroDisc = DiscReg == AArch64::XZR;
2038 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
2040 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
2043 Opc = IsZeroDisc ? AArch64::BRAAZ : AArch64::BRAA;
2045 Opc = IsZeroDisc ? AArch64::BRABZ : AArch64::BRAB;
2053 EmitToStreamer(*OutStreamer, BRInst);
2056 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
2066 getDataLayout(),
Offset,
true);
2068 auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
2074 "cannot resolve target base/addend of ptrauth constant");
2092 "' out of range [0, " +
2096 if (!isUInt<16>(Disc))
2098 "' out of range [0, 0xFFFF]");
2105void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
2106 unsigned DstReg =
MI.getOperand(0).getReg();
2108 const uint64_t KeyC =
MI.getOperand(2).getImm();
2110 "key is out of range [0, AArch64PACKey::LAST]");
2112 const uint64_t Disc =
MI.getOperand(3).getImm();
2113 assert(isUInt<16>(Disc) &&
2114 "constant discriminator is out of range [0, 0xffff]");
2123 if (
TM.getTargetTriple().isOSBinFormatELF()) {
2128 "non-zero offset for $auth_ptr$ stub slots is not supported");
2130 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(
TM, MMI, GASym, Key, Disc);
2132 assert(
TM.getTargetTriple().isOSBinFormatMachO() &&
2133 "LOADauthptrstatic is implemented only for MachO/ELF");
2136 getObjFileLowering());
2139 "non-zero offset for $auth_ptr$ stub slots is not supported");
2141 AuthPtrStubSym = TLOF.getAuthPtrSlotSymbol(
TM, MMI, GASym, Key, Disc);
2150 MCInstLowering.lowerOperand(StubMOHi, StubMCHi);
2151 MCInstLowering.lowerOperand(StubMOLo, StubMCLo);
2164 unsigned InstsEmitted = 0;
2165 auto EmitAndIncrement = [
this, &InstsEmitted](
const MCInst &Inst) {
2166 EmitToStreamer(*OutStreamer, Inst);
2170 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
2172 const uint64_t KeyC =
MI.getOperand(1).getImm();
2174 "key is out of range [0, AArch64PACKey::LAST]");
2176 const unsigned AddrDisc =
MI.getOperand(2).getReg();
2177 const uint64_t Disc =
MI.getOperand(3).getImm();
2178 assert(isUInt<16>(Disc) &&
2179 "constant discriminator is out of range [0, 0xffff]");
2228 MCInstLowering.lowerOperand(GAMOHi, GAMCHi);
2229 MCInstLowering.lowerOperand(GAMOLo, GAMCLo);
2236 .addReg(AArch64::X16)
2237 .addReg(AArch64::X16)
2241 .addReg(AArch64::X16)
2242 .addReg(AArch64::X16)
2249 const bool IsNeg =
Offset < 0;
2250 if (isUInt<24>(AbsOffset)) {
2251 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
2255 .addReg(AArch64::X16)
2256 .addReg(AArch64::X16)
2257 .addImm((AbsOffset >> BitPos) & 0xfff)
2262 EmitAndIncrement(
MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
2263 .addReg(AArch64::X17)
2264 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
2266 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
2267 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
2268 uint64_t Shifted = UOffset >> BitPos;
2270 return Shifted != 0;
2271 for (
int I = 0;
I != 64 - BitPos;
I += 16)
2272 if (((Shifted >>
I) & 0xffff) != 0xffff)
2276 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16) {
2278 .addReg(AArch64::X17)
2279 .addReg(AArch64::X17)
2280 .addImm((UOffset >> BitPos) & 0xffff)
2284 .addReg(AArch64::X16)
2285 .addReg(AArch64::X16)
2286 .addReg(AArch64::X17)
2291 unsigned DiscReg = AddrDisc;
2293 if (AddrDisc != AArch64::XZR) {
2295 .addReg(AArch64::X17)
2296 .addReg(AArch64::XZR)
2300 .addReg(AArch64::X17)
2301 .addReg(AArch64::X17)
2306 .addReg(AArch64::X17)
2310 DiscReg = AArch64::X17;
2316 if (DiscReg != AArch64::XZR)
2318 EmitAndIncrement(MIB);
2320 assert(STI->getInstrInfo()->getInstSizeInBytes(
MI) >= InstsEmitted * 4);
2324AArch64AsmPrinter::lowerBlockAddressConstant(
const BlockAddress &BA) {
2328 if (std::optional<uint16_t> BADisc =
2329 STI->getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn))
2338#include "AArch64GenMCPseudoLowering.inc"
2341 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
2344 if (
MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
2345 EmitToStreamer(*OutStreamer, OutInst);
2349 if (
MI->getOpcode() == AArch64::ADRP) {
2350 for (
auto &Opd :
MI->operands()) {
2351 if (Opd.isSymbol() &&
StringRef(Opd.getSymbolName()) ==
2352 "swift_async_extendedFramePointerFlags") {
2353 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
2358 if (AArch64FI->getLOHRelated().count(
MI)) {
2360 MCSymbol *LOHLabel = createTempSymbol(
"loh");
2362 LOHInstToLabel[
MI] = LOHLabel;
2369 switch (
MI->getOpcode()) {
2372 case AArch64::HINT: {
2377 if (CurrentPatchableFunctionEntrySym &&
2378 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
2379 MI == &MF->front().front()) {
2380 int64_t
Imm =
MI->getOperand(0).getImm();
2381 if ((Imm & 32) && (
Imm & 6)) {
2383 MCInstLowering.Lower(
MI, Inst);
2384 EmitToStreamer(*OutStreamer, Inst);
2385 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
2386 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
2392 case AArch64::MOVMCSym: {
2393 Register DestReg =
MI->getOperand(0).getReg();
2401 MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
2402 MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
2409 EmitToStreamer(*OutStreamer, MovZ);
2417 EmitToStreamer(*OutStreamer, MovK);
2420 case AArch64::MOVIv2d_ns:
2428 if (STI->hasZeroCycleZeroingFPWorkaround() &&
2429 MI->getOperand(1).getImm() == 0) {
2431 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
2434 EmitToStreamer(*OutStreamer, TmpInst);
2439 case AArch64::DBG_VALUE:
2440 case AArch64::DBG_VALUE_LIST:
2444 PrintDebugValueComment(
MI,
OS);
2449 case AArch64::EMITBKEY: {
2451 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2452 ExceptionHandlingType != ExceptionHandling::ARM)
2455 if (getFunctionCFISectionType(*MF) == CFISection::None)
2462 case AArch64::EMITMTETAGGED: {
2464 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2465 ExceptionHandlingType != ExceptionHandling::ARM)
2468 if (getFunctionCFISectionType(*MF) != CFISection::None)
2474 case AArch64::AUTPAC:
2475 emitPtrauthAuthResign(
MI);
2478 case AArch64::LOADauthptrstatic:
2479 LowerLOADauthptrstatic(*
MI);
2482 case AArch64::LOADgotPAC:
2483 case AArch64::MOVaddrPAC:
2484 LowerMOVaddrPAC(*
MI);
2489 emitPtrauthBranch(
MI);
2495 case AArch64::AUTH_TCRETURN:
2496 case AArch64::AUTH_TCRETURN_BTI: {
2499 "Invalid auth key for tail-call return");
2501 const uint64_t Disc =
MI->getOperand(3).getImm();
2502 assert(isUInt<16>(Disc) &&
"Integer discriminator is too wide");
2504 Register AddrDisc =
MI->getOperand(4).getReg();
2506 Register ScratchReg =
MI->getOperand(0).getReg() == AArch64::X16
2510 unsigned DiscReg = AddrDisc;
2512 if (AddrDisc != AArch64::NoRegister) {
2515 .addReg(AArch64::XZR)
2529 DiscReg = ScratchReg;
2532 const bool IsZero = DiscReg == AArch64::NoRegister;
2533 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
2534 {AArch64::BRAB, AArch64::BRABZ}};
2537 TmpInst.
setOpcode(Opcodes[Key][IsZero]);
2541 EmitToStreamer(*OutStreamer, TmpInst);
2545 case AArch64::TCRETURNri:
2546 case AArch64::TCRETURNrix16x17:
2547 case AArch64::TCRETURNrix17:
2548 case AArch64::TCRETURNrinotx16:
2549 case AArch64::TCRETURNriALL: {
2553 EmitToStreamer(*OutStreamer, TmpInst);
2556 case AArch64::TCRETURNdi: {
2558 MCInstLowering.lowerOperand(
MI->getOperand(0), Dest);
2562 EmitToStreamer(*OutStreamer, TmpInst);
2565 case AArch64::SpeculationBarrierISBDSBEndBB: {
2570 EmitToStreamer(*OutStreamer, TmpInstDSB);
2574 EmitToStreamer(*OutStreamer, TmpInstISB);
2577 case AArch64::SpeculationBarrierSBEndBB: {
2581 EmitToStreamer(*OutStreamer, TmpInstSB);
2584 case AArch64::TLSDESC_CALLSEQ: {
2597 MCInstLowering.lowerOperand(MO_Sym,
Sym);
2598 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2599 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2605 EmitToStreamer(*OutStreamer, Adrp);
2608 if (STI->isTargetILP32()) {
2618 EmitToStreamer(*OutStreamer, Ldr);
2621 if (STI->isTargetILP32()) {
2622 Add.setOpcode(AArch64::ADDWri);
2626 Add.setOpcode(AArch64::ADDXri);
2630 Add.addOperand(SymTLSDescLo12);
2632 EmitToStreamer(*OutStreamer,
Add);
2637 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
2639 EmitToStreamer(*OutStreamer, TLSDescCall);
2644 EmitToStreamer(*OutStreamer, Blr);
2649 case AArch64::JumpTableDest32:
2650 case AArch64::JumpTableDest16:
2651 case AArch64::JumpTableDest8:
2652 LowerJumpTableDest(*OutStreamer, *
MI);
2655 case AArch64::BR_JumpTable:
2656 LowerHardenedBRJumpTable(*
MI);
2659 case AArch64::FMOVH0:
2660 case AArch64::FMOVS0:
2661 case AArch64::FMOVD0:
2665 case AArch64::MOPSMemoryCopyPseudo:
2666 case AArch64::MOPSMemoryMovePseudo:
2667 case AArch64::MOPSMemorySetPseudo:
2668 case AArch64::MOPSMemorySetTaggingPseudo:
2669 LowerMOPS(*OutStreamer, *
MI);
2672 case TargetOpcode::STACKMAP:
2673 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
2675 case TargetOpcode::PATCHPOINT:
2676 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
2678 case TargetOpcode::STATEPOINT:
2679 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
2681 case TargetOpcode::FAULTING_OP:
2682 return LowerFAULTING_OP(*
MI);
2684 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2685 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
2688 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2689 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
2692 case TargetOpcode::PATCHABLE_TAIL_CALL:
2693 LowerPATCHABLE_TAIL_CALL(*
MI);
2695 case TargetOpcode::PATCHABLE_EVENT_CALL:
2696 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
2697 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
2698 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
2700 case AArch64::KCFI_CHECK:
2701 LowerKCFI_CHECK(*
MI);
2704 case AArch64::HWASAN_CHECK_MEMACCESS:
2705 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
2706 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
2707 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
2708 LowerHWASAN_CHECK_MEMACCESS(*
MI);
2711 case AArch64::SEH_StackAlloc:
2715 case AArch64::SEH_SaveFPLR:
2719 case AArch64::SEH_SaveFPLR_X:
2720 assert(
MI->getOperand(0).getImm() < 0 &&
2721 "Pre increment SEH opcode must have a negative offset");
2725 case AArch64::SEH_SaveReg:
2727 MI->getOperand(1).getImm());
2730 case AArch64::SEH_SaveReg_X:
2731 assert(
MI->getOperand(1).getImm() < 0 &&
2732 "Pre increment SEH opcode must have a negative offset");
2734 -
MI->getOperand(1).getImm());
2737 case AArch64::SEH_SaveRegP:
2738 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
2739 MI->getOperand(0).getImm() <= 28) {
2740 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
2741 "Register paired with LR must be odd");
2743 MI->getOperand(2).getImm());
2746 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2747 "Non-consecutive registers not allowed for save_regp");
2749 MI->getOperand(2).getImm());
2752 case AArch64::SEH_SaveRegP_X:
2753 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2754 "Non-consecutive registers not allowed for save_regp_x");
2755 assert(
MI->getOperand(2).getImm() < 0 &&
2756 "Pre increment SEH opcode must have a negative offset");
2758 -
MI->getOperand(2).getImm());
2761 case AArch64::SEH_SaveFReg:
2763 MI->getOperand(1).getImm());
2766 case AArch64::SEH_SaveFReg_X:
2767 assert(
MI->getOperand(1).getImm() < 0 &&
2768 "Pre increment SEH opcode must have a negative offset");
2770 -
MI->getOperand(1).getImm());
2773 case AArch64::SEH_SaveFRegP:
2774 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2775 "Non-consecutive registers not allowed for save_regp");
2777 MI->getOperand(2).getImm());
2780 case AArch64::SEH_SaveFRegP_X:
2781 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2782 "Non-consecutive registers not allowed for save_regp_x");
2783 assert(
MI->getOperand(2).getImm() < 0 &&
2784 "Pre increment SEH opcode must have a negative offset");
2786 -
MI->getOperand(2).getImm());
2789 case AArch64::SEH_SetFP:
2793 case AArch64::SEH_AddFP:
2797 case AArch64::SEH_Nop:
2801 case AArch64::SEH_PrologEnd:
2805 case AArch64::SEH_EpilogStart:
2809 case AArch64::SEH_EpilogEnd:
2813 case AArch64::SEH_PACSignLR:
2817 case AArch64::SEH_SaveAnyRegQP:
2818 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2819 "Non-consecutive registers not allowed for save_any_reg");
2820 assert(
MI->getOperand(2).getImm() >= 0 &&
2821 "SaveAnyRegQP SEH opcode offset must be non-negative");
2822 assert(
MI->getOperand(2).getImm() <= 1008 &&
2823 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
2825 MI->getOperand(2).getImm());
2828 case AArch64::SEH_SaveAnyRegQPX:
2829 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2830 "Non-consecutive registers not allowed for save_any_reg");
2831 assert(
MI->getOperand(2).getImm() < 0 &&
2832 "SaveAnyRegQPX SEH opcode offset must be negative");
2833 assert(
MI->getOperand(2).getImm() >= -1008 &&
2834 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
2836 -
MI->getOperand(2).getImm());
2842 MCInstLowering.Lower(
MI, TmpInst);
2843 EmitToStreamer(*OutStreamer, TmpInst);
2859 MCInstLowering.lowerOperand(
2873 MCInstLowering.lowerOperand(
2883 .addReg(AArch64::X16)
2884 .addReg(AArch64::X16)
2895void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
2930 .addReg(AArch64::SP)
2931 .addReg(AArch64::FP)
2932 .addReg(AArch64::LR)
2933 .addReg(AArch64::SP)
2938 .addReg(AArch64::FP)
2939 .addReg(AArch64::SP)
2944 for (
int I = 0;
I != 4; ++
I)
2946 .addReg(AArch64::SP)
2947 .addReg(AArch64::X1 + 2 *
I)
2948 .addReg(AArch64::X0 + 2 *
I)
2949 .addReg(AArch64::SP)
2953 for (
int I = 0;
I != 4; ++
I)
2955 .addReg(AArch64::SP)
2956 .addReg(AArch64::D1 + 2 *
I)
2957 .addReg(AArch64::D0 + 2 *
I)
2958 .addReg(AArch64::SP)
2972 MCInstLowering.lowerOperand(
2986 MCInstLowering.lowerOperand(
2996 .addReg(AArch64::X0)
2997 .addReg(AArch64::X16)
3002 .addReg(AArch64::X16)
3003 .addReg(AArch64::X0)
3008 for (
int I = 3;
I != -1; --
I)
3010 .addReg(AArch64::SP)
3011 .addReg(AArch64::D1 + 2 *
I)
3012 .addReg(AArch64::D0 + 2 *
I)
3013 .addReg(AArch64::SP)
3017 for (
int I = 3;
I != -1; --
I)
3019 .addReg(AArch64::SP)
3020 .addReg(AArch64::X1 + 2 *
I)
3021 .addReg(AArch64::X0 + 2 *
I)
3022 .addReg(AArch64::SP)
3027 .addReg(AArch64::SP)
3028 .addReg(AArch64::FP)
3029 .addReg(AArch64::LR)
3030 .addReg(AArch64::SP)
3041const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV) {
3042 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 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
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const char LLVMTargetMachineRef TM
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
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 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.
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
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.
bool hasAddressDiscriminator() const
Whether there is any non-null address discriminator.
ConstantInt * getDiscriminator() const
The integer discriminator, an i64 constant, or 0.
@ AddrDiscriminator_CtorsDtors
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
void emitError(uint64_t LocCookie, 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(unsigned Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr 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 createReg(unsigned Reg)
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createImm(int64_t Val)
uint16_t getEncodingValue(MCRegister RegNo) const
Returns the encoding for RegNo.
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()
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.
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)
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.
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.
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.
static unsigned getXPACOpcodeForKey(AArch64PACKey::ID K)
Return XPAC opcode to be used for a ptrauth strip using the given key.
Target & getTheAArch64beTarget()
Target & getTheAArch64leTarget()
static unsigned getXRegFromWReg(unsigned Reg)
static unsigned getXRegFromXRegTuple(unsigned RegTuple)
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 unsigned getWRegFromXReg(unsigned Reg)
Target & getTheARM64Target()
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 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,...