71#define DEBUG_TYPE "asm-printer"
79 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
82 AArch64AsmPrinter(
TargetMachine &
TM, std::unique_ptr<MCStreamer> Streamer)
83 :
AsmPrinter(
TM, std::move(Streamer)), MCInstLowering(OutContext, *
this),
101 const MCSymbol *BranchLabel)
const override;
120 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
122 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
123 HwasanMemaccessTuple;
124 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
127 void emitHwasanMemaccessSymbols(
Module &M);
134 unsigned emitPtrauthDiscriminator(
uint16_t Disc,
unsigned AddrDisc,
135 unsigned &InstsEmitted);
146 bool emitPseudoExpansionLowering(
MCStreamer &OutStreamer,
151 void emitFunctionHeaderComment()
override;
164 if (STI->isTargetCOFF()) {
216 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
218 MInstToMCSymbol LOHInstToLabel;
221 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
236void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
239 if (
TT.isOSBinFormatCOFF()) {
242 OutStreamer->beginCOFFSymbolDef(S);
245 OutStreamer->endCOFFSymbolDef();
246 int64_t Feat00Value = 0;
248 if (
M.getModuleFlag(
"cfguard")) {
250 Feat00Value |= COFF::Feat00Flags::GuardCF;
253 if (
M.getModuleFlag(
"ehcontguard")) {
255 Feat00Value |= COFF::Feat00Flags::GuardEHCont;
258 if (
M.getModuleFlag(
"ms-kernel")) {
260 Feat00Value |= COFF::Feat00Flags::Kernel;
264 OutStreamer->emitAssignment(
268 if (!
TT.isOSBinFormatELF())
273 if (
const auto *BTE = mdconst::extract_or_null<ConstantInt>(
274 M.getModuleFlag(
"branch-target-enforcement")))
275 if (BTE->getZExtValue())
278 if (
const auto *GCS = mdconst::extract_or_null<ConstantInt>(
279 M.getModuleFlag(
"guarded-control-stack")))
280 if (GCS->getZExtValue())
283 if (
const auto *Sign = mdconst::extract_or_null<ConstantInt>(
284 M.getModuleFlag(
"sign-return-address")))
285 if (Sign->getZExtValue())
289 if (
const auto *PAP = mdconst::extract_or_null<ConstantInt>(
290 M.getModuleFlag(
"aarch64-elf-pauthabi-platform")))
291 PAuthABIPlatform = PAP->getZExtValue();
293 if (
const auto *PAV = mdconst::extract_or_null<ConstantInt>(
294 M.getModuleFlag(
"aarch64-elf-pauthabi-version")))
295 PAuthABIVersion = PAV->getZExtValue();
303void AArch64AsmPrinter::emitFunctionHeaderComment() {
306 if (OutlinerString != std::nullopt)
307 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
310void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
313 if (
F.hasFnAttribute(
"patchable-function-entry")) {
315 if (
F.getFnAttribute(
"patchable-function-entry")
317 .getAsInteger(10, Num))
323 emitSled(
MI, SledKind::FUNCTION_ENTER);
326void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
327 emitSled(
MI, SledKind::FUNCTION_EXIT);
330void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
331 emitSled(
MI, SledKind::TAIL_CALL);
334void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
335 static const int8_t NoopsInSledCount = 7;
356 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
357 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
358 OutStreamer->emitLabel(CurSled);
359 auto Target = OutContext.createTempSymbol();
364 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::B).addImm(8));
366 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
367 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
369 OutStreamer->emitLabel(
Target);
370 recordSled(CurSled,
MI, Kind, 2);
388void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
390 auto &
O = *OutStreamer;
391 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
392 O.emitLabel(CurSled);
403 bool MachO =
TM.getTargetTriple().isOSBinFormatMachO();
405 OutContext.getOrCreateSymbol(
406 Twine(MachO ?
"_" :
"") +
407 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
410 O.AddComment(
"Begin XRay typed event");
422 EmitToStreamer(O, MovX0Op0);
423 EmitToStreamer(O, MovX1Op1);
426 .addReg(AArch64::XZR)
427 .addReg(
MI.getOperand(2).getReg())
434 O.AddComment(
"End XRay typed event");
442 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
444 O.AddComment(
"Begin XRay custom event");
452 EmitToStreamer(O, MovX0Op0);
453 EmitToStreamer(O, MovX1Op1);
455 O.AddComment(
"End XRay custom event");
463 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
469 assert(std::next(
MI.getIterator())->isCall() &&
470 "KCFI_CHECK not followed by a call instruction");
471 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
472 "KCFI_CHECK call target doesn't match call operand");
476 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
477 if (AddrReg == AArch64::XZR) {
483 .addReg(AArch64::XZR)
484 .addReg(AArch64::XZR)
491 for (
auto &Reg : ScratchRegs) {
497 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
498 "Invalid scratch registers for KCFI_CHECK");
502 int64_t PrefixNops = 0;
505 .getFnAttribute(
"patchable-function-prefix")
507 .getAsInteger(10, PrefixNops);
511 .addReg(ScratchRegs[0])
513 .addImm(-(PrefixNops * 4 + 4)));
517 const int64_t
Type =
MI.getOperand(1).getImm();
519 .addReg(ScratchRegs[1])
520 .addReg(ScratchRegs[1])
521 .addImm(
Type & 0xFFFF)
524 .addReg(ScratchRegs[1])
525 .addReg(ScratchRegs[1])
526 .addImm((
Type >> 16) & 0xFFFF)
531 .addReg(AArch64::WZR)
532 .addReg(ScratchRegs[0])
533 .addReg(ScratchRegs[1])
537 EmitToStreamer(*OutStreamer,
547 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
551 AddrIndex = AddrReg - AArch64::X0;
561 assert(AddrIndex < 31 && TypeIndex < 31);
563 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
564 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BRK).addImm(ESR));
565 OutStreamer->emitLabel(
Pass);
568void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
571 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
573 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
574 uint32_t AccessInfo =
MI.getOperand(1).getImm();
576 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
578 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
579 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
581 MCSymbol *&
Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
582 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
585 if (!
TM.getTargetTriple().isOSBinFormatELF())
588 std::string SymName =
"__hwasan_check_x" + utostr(Reg - AArch64::X0) +
"_" +
591 SymName +=
"_fixed_" + utostr(FixedShadowOffset);
593 SymName +=
"_short_v2";
594 Sym = OutContext.getOrCreateSymbol(SymName);
597 EmitToStreamer(*OutStreamer,
602void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
603 if (HwasanMemaccessSymbols.empty())
608 std::unique_ptr<MCSubtargetInfo> STI(
609 TM.getTarget().createMCSubtargetInfo(
TT.str(),
"",
""));
610 assert(STI &&
"Unable to create subtarget info");
613 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
615 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
622 for (
auto &
P : HwasanMemaccessSymbols) {
623 unsigned Reg = std::get<0>(
P.first);
624 bool IsShort = std::get<1>(
P.first);
625 uint32_t AccessInfo = std::get<2>(
P.first);
626 bool IsFixedShadow = std::get<3>(
P.first);
627 uint64_t FixedShadowOffset = std::get<4>(
P.first);
629 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
632 bool HasMatchAllTag =
634 uint8_t MatchAllTag =
641 OutStreamer->switchSection(OutContext.getELFSection(
649 OutStreamer->emitLabel(
Sym);
665 .
addImm(FixedShadowOffset >> 32)
668 OutStreamer->emitInstruction(
MCInstBuilder(AArch64::LDRBBroX)
676 OutStreamer->emitInstruction(
679 .
addReg(IsShort ? AArch64::X20 : AArch64::X9)
686 OutStreamer->emitInstruction(
693 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
694 OutStreamer->emitInstruction(
700 MCSymbol *ReturnSym = OutContext.createTempSymbol();
701 OutStreamer->emitLabel(ReturnSym);
702 OutStreamer->emitInstruction(
704 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
706 if (HasMatchAllTag) {
719 OutStreamer->emitInstruction(
733 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
734 OutStreamer->emitInstruction(
740 OutStreamer->emitInstruction(
759 OutStreamer->emitInstruction(
765 OutStreamer->emitInstruction(
776 OutStreamer->emitInstruction(
783 OutStreamer->emitInstruction(
789 OutStreamer->emitLabel(HandleMismatchSym);
806 if (Reg != AArch64::X0)
813 OutStreamer->emitInstruction(
824 OutStreamer->emitInstruction(
830 OutStreamer->emitInstruction(
834 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
837 OutStreamer->emitInstruction(
842 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
845 OutStreamer->emitInstruction(
851template <
typename MachineModuleInfoTarget>
854 const typename MachineModuleInfoTarget::AuthStubInfo &StubInfo) {
857 OutStreamer.
emitValue(StubInfo.AuthPtrRef, 8);
860void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
861 emitHwasanMemaccessSymbols(M);
864 if (
TT.isOSBinFormatMachO()) {
873 if (
TT.isOSBinFormatELF()) {
879 if (!Stubs.empty()) {
882 emitAlignment(
Align(8));
884 for (
const auto &Stub : Stubs)
885 emitAuthenticatedPointer<MachineModuleInfoELF>(*OutStreamer, Stub.first,
888 OutStreamer->addBlankLine();
893 FM.serializeToFaultMapSection();
897void AArch64AsmPrinter::emitLOHs() {
900 for (
const auto &
D : AArch64FI->getLOHContainer()) {
902 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
903 assert(LabelIt != LOHInstToLabel.end() &&
904 "Label hasn't been inserted for LOH related instruction");
907 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
912void AArch64AsmPrinter::emitFunctionBodyEnd() {
913 if (!AArch64FI->getLOHRelated().empty())
918MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
922 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
923 return OutContext.getOrCreateSymbol(
924 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
925 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
930void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
948 PrintSymbolOperand(MO, O);
959bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
983bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
986 assert(MO.
isReg() &&
"Should only get here with a register!");
996bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1005 if (ExtraCode && ExtraCode[0]) {
1006 if (ExtraCode[1] != 0)
1009 switch (ExtraCode[0]) {
1017 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1031 switch (ExtraCode[0]) {
1033 RC = &AArch64::FPR8RegClass;
1036 RC = &AArch64::FPR16RegClass;
1039 RC = &AArch64::FPR32RegClass;
1042 RC = &AArch64::FPR64RegClass;
1045 RC = &AArch64::FPR128RegClass;
1048 RC = &AArch64::ZPRRegClass;
1053 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1066 if (AArch64::GPR32allRegClass.
contains(Reg) ||
1067 AArch64::GPR64allRegClass.
contains(Reg))
1071 if (AArch64::GPR64x8ClassRegClass.
contains(Reg))
1074 unsigned AltName = AArch64::NoRegAltName;
1076 if (AArch64::ZPRRegClass.
contains(Reg)) {
1077 RegClass = &AArch64::ZPRRegClass;
1078 }
else if (AArch64::PPRRegClass.
contains(Reg)) {
1079 RegClass = &AArch64::PPRRegClass;
1080 }
else if (AArch64::PNRRegClass.
contains(Reg)) {
1081 RegClass = &AArch64::PNRRegClass;
1083 RegClass = &AArch64::FPR128RegClass;
1084 AltName = AArch64::vreg;
1088 return printAsmRegInClass(MO, RegClass, AltName, O);
1095bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1097 const char *ExtraCode,
1099 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1103 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1108void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1110 unsigned NOps =
MI->getNumOperands();
1112 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1114 OS <<
MI->getDebugVariable()->getName();
1117 assert(
MI->isIndirectDebugValue());
1119 for (
unsigned I = 0, E = std::distance(
MI->debug_operands().begin(),
1120 MI->debug_operands().end());
1131void AArch64AsmPrinter::emitJumpTableInfo() {
1136 if (
JT.empty())
return;
1140 OutStreamer->switchSection(ReadOnlySec);
1143 for (
unsigned JTI = 0, e =
JT.size(); JTI !=
e; ++JTI) {
1144 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1147 if (JTBBs.empty())
continue;
1149 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1151 OutStreamer->emitLabel(GetJTISymbol(JTI));
1153 const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1156 for (
auto *JTBB : JTBBs) {
1176AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1178 const MCSymbol *BranchLabel)
const {
1180 const auto Base = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1182 switch (AFI->getJumpTableEntrySize(JTI)) {
1184 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1187 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1190 EntrySize = codeview::JumpTableEntrySize::Int32;
1195 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1198void AArch64AsmPrinter::emitFunctionEntryLabel() {
1200 MF->getFunction().getCallingConv() ==
1210 if (
TM.getTargetTriple().isWindowsArm64EC() &&
1211 !MF->getFunction().hasLocalLinkage()) {
1216 OutStreamer->emitAssignment(
1218 MMI->getContext()));
1224 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1225 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1231 getSymbolFromMetadata(
"arm64ec_unmangled_name")) {
1232 MCSymbol *ECMangledSym = getSymbolFromMetadata(
"arm64ec_ecmangled_name");
1238 emitFunctionAlias(UnmangledSym, ECMangledSym);
1239 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1243 emitFunctionAlias(UnmangledSym, CurrentFnSym);
1260 Register DestReg =
MI.getOperand(0).getReg();
1261 Register ScratchReg =
MI.getOperand(1).getReg();
1263 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1264 Register TableReg =
MI.getOperand(2).getReg();
1265 Register EntryReg =
MI.getOperand(3).getReg();
1266 int JTIdx =
MI.getOperand(4).getIndex();
1267 int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
1277 Label = MF->getContext().createTempSymbol();
1278 AArch64FI->setJumpTableEntryInfo(JTIdx,
Size, Label);
1285 .addExpr(LabelExpr));
1290 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1291 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1292 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1298 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1302 .addImm(
Size == 1 ? 0 : 1));
1310 .addImm(
Size == 4 ? 0 : 2));
1315 unsigned Opcode =
MI.getOpcode();
1317 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1319 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1320 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1321 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1322 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1323 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1324 if (Opcode == AArch64::MOPSMemorySetPseudo)
1325 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1326 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1327 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1330 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1331 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1333 for (
auto Op : Ops) {
1337 MCIB.addReg(
MI.getOperand(i++).getReg());
1338 MCIB.addReg(
MI.getOperand(i++).getReg());
1340 MCIB.addReg(
MI.getOperand(i++).getReg());
1342 MCIB.addReg(
MI.getOperand(i++).getReg());
1343 MCIB.addReg(
MI.getOperand(i++).getReg());
1344 MCIB.addReg(
MI.getOperand(i++).getReg());
1346 EmitToStreamer(OutStreamer, MCIB);
1355 MCSymbol *MILabel = Ctx.createTempSymbol();
1359 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1365 while (NumNOPBytes > 0) {
1366 if (MII ==
MBB.
end() || MII->isCall() ||
1367 MII->getOpcode() == AArch64::DBG_VALUE ||
1368 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1369 MII->getOpcode() == TargetOpcode::STACKMAP)
1376 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1377 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1385 MCSymbol *MILabel = Ctx.createTempSymbol();
1391 int64_t CallTarget = Opers.getCallTarget().getImm();
1392 unsigned EncodedBytes = 0;
1394 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1395 "High 16 bits of call target should be zero.");
1396 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1401 .addImm((CallTarget >> 32) & 0xFFFF)
1406 .addImm((CallTarget >> 16) & 0xFFFF)
1411 .addImm(CallTarget & 0xFFFF)
1413 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1416 unsigned NumBytes = Opers.getNumPatchBytes();
1417 assert(NumBytes >= EncodedBytes &&
1418 "Patchpoint can't request size less than the length of a call.");
1419 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1420 "Invalid number of NOP bytes requested!");
1421 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1422 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1428 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1429 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1430 for (
unsigned i = 0; i < PatchBytes; i += 4)
1431 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1436 unsigned CallOpcode;
1437 switch (CallTarget.
getType()) {
1440 MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
1441 CallOpcode = AArch64::BL;
1445 CallOpcode = AArch64::BL;
1449 CallOpcode = AArch64::BLR;
1456 EmitToStreamer(OutStreamer,
1461 MCSymbol *MILabel = Ctx.createTempSymbol();
1466void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1475 unsigned OperandsBeginIdx = 4;
1478 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1482 FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
1485 MI.setOpcode(Opcode);
1493 lowerOperand(MO, Dest);
1494 MI.addOperand(Dest);
1502 Register DestReg =
MI.getOperand(0).getReg();
1503 if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() &&
1504 STI->isNeonAvailable()) {
1506 if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
1507 DestReg = AArch64::D0 + (DestReg - AArch64::H0);
1508 else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
1509 DestReg = AArch64::D0 + (DestReg - AArch64::S0);
1511 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
1514 MOVI.setOpcode(AArch64::MOVID);
1517 EmitToStreamer(*OutStreamer, MOVI);
1520 switch (
MI.getOpcode()) {
1522 case AArch64::FMOVH0:
1523 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1524 if (!STI->hasFullFP16())
1525 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1529 case AArch64::FMOVS0:
1534 case AArch64::FMOVD0:
1540 EmitToStreamer(*OutStreamer, FMov);
1544unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(
uint16_t Disc,
1546 unsigned &InstsEmitted) {
1548 if (AddrDisc == AArch64::NoRegister)
1549 AddrDisc = AArch64::XZR;
1557 if (AddrDisc == AArch64::XZR) {
1559 .addReg(AArch64::X17)
1563 return AArch64::X17;
1568 .addReg(AArch64::X17)
1569 .addReg(AArch64::XZR)
1574 .addReg(AArch64::X17)
1575 .addReg(AArch64::X17)
1579 return AArch64::X17;
1582void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
1583 unsigned InstsEmitted = 0;
1584 unsigned BrTarget =
MI->getOperand(0).getReg();
1588 "Invalid auth call key");
1591 assert(isUInt<16>(Disc));
1593 unsigned AddrDisc =
MI->getOperand(3).getReg();
1596 unsigned DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, InstsEmitted);
1597 bool IsZeroDisc = DiscReg == AArch64::XZR;
1601 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
1603 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
1610 EmitToStreamer(*OutStreamer, BRInst);
1613 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
1623 getDataLayout(),
Offset,
true);
1625 auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
1631 "cannot resolve target base/addend of ptrauth constant");
1649 "' out of range [0, " +
1653 if (!isUInt<16>(Disc))
1655 "' out of range [0, 0xFFFF]");
1662void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
1663 unsigned DstReg =
MI.getOperand(0).getReg();
1665 const uint64_t KeyC =
MI.getOperand(2).getImm();
1667 "key is out of range [0, AArch64PACKey::LAST]");
1669 const uint64_t Disc =
MI.getOperand(3).getImm();
1670 assert(isUInt<16>(Disc) &&
1671 "constant discriminator is out of range [0, 0xffff]");
1679 assert(
TM.getTargetTriple().isOSBinFormatELF() &&
1680 "LOADauthptrstatic is implemented only for ELF");
1685 "non-zero offset for $auth_ptr$ stub slots is not supported");
1688 TLOF.getAuthPtrSlotSymbol(
TM, &MF->getMMI(), GASym, Key, Disc);
1696 MCInstLowering.lowerOperand(StubMOHi, StubMCHi);
1697 MCInstLowering.lowerOperand(StubMOLo, StubMCLo);
1710 unsigned InstsEmitted = 0;
1711 auto EmitAndIncrement = [
this, &InstsEmitted](
const MCInst &Inst) {
1712 EmitToStreamer(*OutStreamer, Inst);
1716 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
1718 const uint64_t KeyC =
MI.getOperand(1).getImm();
1720 "key is out of range [0, AArch64PACKey::LAST]");
1722 const unsigned AddrDisc =
MI.getOperand(2).getReg();
1723 const uint64_t Disc =
MI.getOperand(3).getImm();
1724 assert(isUInt<16>(Disc) &&
1725 "constant discriminator is out of range [0, 0xffff]");
1774 MCInstLowering.lowerOperand(GAMOHi, GAMCHi);
1775 MCInstLowering.lowerOperand(GAMOLo, GAMCLo);
1782 .addReg(AArch64::X16)
1783 .addReg(AArch64::X16)
1787 .addReg(AArch64::X16)
1788 .addReg(AArch64::X16)
1795 const bool IsNeg =
Offset < 0;
1796 if (isUInt<24>(AbsOffset)) {
1797 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
1801 .addReg(AArch64::X16)
1802 .addReg(AArch64::X16)
1803 .addImm((AbsOffset >> BitPos) & 0xfff)
1808 EmitAndIncrement(
MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
1809 .addReg(AArch64::X17)
1810 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
1812 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
1813 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
1814 uint64_t Shifted = UOffset >> BitPos;
1816 return Shifted != 0;
1817 for (
int I = 0;
I != 64 - BitPos;
I += 16)
1818 if (((Shifted >>
I) & 0xffff) != 0xffff)
1822 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16) {
1824 .addReg(AArch64::X17)
1825 .addReg(AArch64::X17)
1826 .addImm((UOffset >> BitPos) & 0xffff)
1830 .addReg(AArch64::X16)
1831 .addReg(AArch64::X16)
1832 .addReg(AArch64::X17)
1837 unsigned DiscReg = AddrDisc;
1839 if (AddrDisc != AArch64::XZR) {
1841 .addReg(AArch64::X17)
1842 .addReg(AArch64::XZR)
1846 .addReg(AArch64::X17)
1847 .addReg(AArch64::X17)
1852 .addReg(AArch64::X17)
1856 DiscReg = AArch64::X17;
1862 if (DiscReg != AArch64::XZR)
1864 EmitAndIncrement(MIB);
1866 assert(STI->getInstrInfo()->getInstSizeInBytes(
MI) >= InstsEmitted * 4);
1871#include "AArch64GenMCPseudoLowering.inc"
1874 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
1877 if (emitPseudoExpansionLowering(*OutStreamer,
MI))
1880 if (
MI->getOpcode() == AArch64::ADRP) {
1881 for (
auto &Opd :
MI->operands()) {
1882 if (Opd.isSymbol() &&
StringRef(Opd.getSymbolName()) ==
1883 "swift_async_extendedFramePointerFlags") {
1884 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
1889 if (AArch64FI->getLOHRelated().count(
MI)) {
1891 MCSymbol *LOHLabel = createTempSymbol(
"loh");
1893 LOHInstToLabel[
MI] = LOHLabel;
1900 switch (
MI->getOpcode()) {
1903 case AArch64::HINT: {
1908 if (CurrentPatchableFunctionEntrySym &&
1909 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
1910 MI == &MF->front().front()) {
1911 int64_t
Imm =
MI->getOperand(0).getImm();
1912 if ((Imm & 32) && (
Imm & 6)) {
1914 MCInstLowering.Lower(
MI, Inst);
1915 EmitToStreamer(*OutStreamer, Inst);
1916 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
1917 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
1923 case AArch64::MOVMCSym: {
1924 Register DestReg =
MI->getOperand(0).getReg();
1932 MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
1933 MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
1940 EmitToStreamer(*OutStreamer, MovZ);
1948 EmitToStreamer(*OutStreamer, MovK);
1951 case AArch64::MOVIv2d_ns:
1959 if (STI->hasZeroCycleZeroingFPWorkaround() &&
1960 MI->getOperand(1).getImm() == 0) {
1962 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
1965 EmitToStreamer(*OutStreamer, TmpInst);
1970 case AArch64::DBG_VALUE:
1971 case AArch64::DBG_VALUE_LIST:
1975 PrintDebugValueComment(
MI,
OS);
1980 case AArch64::EMITBKEY: {
1982 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
1983 ExceptionHandlingType != ExceptionHandling::ARM)
1986 if (getFunctionCFISectionType(*MF) == CFISection::None)
1993 case AArch64::EMITMTETAGGED: {
1995 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
1996 ExceptionHandlingType != ExceptionHandling::ARM)
1999 if (getFunctionCFISectionType(*MF) != CFISection::None)
2004 case AArch64::LOADauthptrstatic:
2005 LowerLOADauthptrstatic(*
MI);
2008 case AArch64::LOADgotPAC:
2009 case AArch64::MOVaddrPAC:
2010 LowerMOVaddrPAC(*
MI);
2014 emitPtrauthBranch(
MI);
2020 case AArch64::AUTH_TCRETURN:
2021 case AArch64::AUTH_TCRETURN_BTI: {
2024 "Invalid auth key for tail-call return");
2026 const uint64_t Disc =
MI->getOperand(3).getImm();
2027 assert(isUInt<16>(Disc) &&
"Integer discriminator is too wide");
2029 Register AddrDisc =
MI->getOperand(4).getReg();
2031 Register ScratchReg =
MI->getOperand(0).getReg() == AArch64::X16
2035 unsigned DiscReg = AddrDisc;
2037 if (AddrDisc != AArch64::NoRegister) {
2040 .addReg(AArch64::XZR)
2054 DiscReg = ScratchReg;
2057 const bool IsZero = DiscReg == AArch64::NoRegister;
2058 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
2059 {AArch64::BRAB, AArch64::BRABZ}};
2062 TmpInst.
setOpcode(Opcodes[Key][IsZero]);
2066 EmitToStreamer(*OutStreamer, TmpInst);
2070 case AArch64::TCRETURNri:
2071 case AArch64::TCRETURNrix16x17:
2072 case AArch64::TCRETURNrix17:
2073 case AArch64::TCRETURNrinotx16:
2074 case AArch64::TCRETURNriALL: {
2078 EmitToStreamer(*OutStreamer, TmpInst);
2081 case AArch64::TCRETURNdi: {
2083 MCInstLowering.lowerOperand(
MI->getOperand(0), Dest);
2087 EmitToStreamer(*OutStreamer, TmpInst);
2090 case AArch64::SpeculationBarrierISBDSBEndBB: {
2095 EmitToStreamer(*OutStreamer, TmpInstDSB);
2099 EmitToStreamer(*OutStreamer, TmpInstISB);
2102 case AArch64::SpeculationBarrierSBEndBB: {
2106 EmitToStreamer(*OutStreamer, TmpInstSB);
2109 case AArch64::TLSDESC_CALLSEQ: {
2122 MCInstLowering.lowerOperand(MO_Sym,
Sym);
2123 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2124 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2130 EmitToStreamer(*OutStreamer, Adrp);
2133 if (STI->isTargetILP32()) {
2143 EmitToStreamer(*OutStreamer, Ldr);
2146 if (STI->isTargetILP32()) {
2147 Add.setOpcode(AArch64::ADDWri);
2151 Add.setOpcode(AArch64::ADDXri);
2155 Add.addOperand(SymTLSDescLo12);
2157 EmitToStreamer(*OutStreamer,
Add);
2162 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
2164 EmitToStreamer(*OutStreamer, TLSDescCall);
2169 EmitToStreamer(*OutStreamer, Blr);
2174 case AArch64::JumpTableDest32:
2175 case AArch64::JumpTableDest16:
2176 case AArch64::JumpTableDest8:
2177 LowerJumpTableDest(*OutStreamer, *
MI);
2180 case AArch64::FMOVH0:
2181 case AArch64::FMOVS0:
2182 case AArch64::FMOVD0:
2186 case AArch64::MOPSMemoryCopyPseudo:
2187 case AArch64::MOPSMemoryMovePseudo:
2188 case AArch64::MOPSMemorySetPseudo:
2189 case AArch64::MOPSMemorySetTaggingPseudo:
2190 LowerMOPS(*OutStreamer, *
MI);
2193 case TargetOpcode::STACKMAP:
2194 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
2196 case TargetOpcode::PATCHPOINT:
2197 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
2199 case TargetOpcode::STATEPOINT:
2200 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
2202 case TargetOpcode::FAULTING_OP:
2203 return LowerFAULTING_OP(*
MI);
2205 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2206 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
2209 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2210 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
2213 case TargetOpcode::PATCHABLE_TAIL_CALL:
2214 LowerPATCHABLE_TAIL_CALL(*
MI);
2216 case TargetOpcode::PATCHABLE_EVENT_CALL:
2217 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
2218 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
2219 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
2221 case AArch64::KCFI_CHECK:
2222 LowerKCFI_CHECK(*
MI);
2225 case AArch64::HWASAN_CHECK_MEMACCESS:
2226 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
2227 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
2228 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
2229 LowerHWASAN_CHECK_MEMACCESS(*
MI);
2232 case AArch64::SEH_StackAlloc:
2236 case AArch64::SEH_SaveFPLR:
2240 case AArch64::SEH_SaveFPLR_X:
2241 assert(
MI->getOperand(0).getImm() < 0 &&
2242 "Pre increment SEH opcode must have a negative offset");
2246 case AArch64::SEH_SaveReg:
2248 MI->getOperand(1).getImm());
2251 case AArch64::SEH_SaveReg_X:
2252 assert(
MI->getOperand(1).getImm() < 0 &&
2253 "Pre increment SEH opcode must have a negative offset");
2255 -
MI->getOperand(1).getImm());
2258 case AArch64::SEH_SaveRegP:
2259 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
2260 MI->getOperand(0).getImm() <= 28) {
2261 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
2262 "Register paired with LR must be odd");
2264 MI->getOperand(2).getImm());
2267 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2268 "Non-consecutive registers not allowed for save_regp");
2270 MI->getOperand(2).getImm());
2273 case AArch64::SEH_SaveRegP_X:
2274 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2275 "Non-consecutive registers not allowed for save_regp_x");
2276 assert(
MI->getOperand(2).getImm() < 0 &&
2277 "Pre increment SEH opcode must have a negative offset");
2279 -
MI->getOperand(2).getImm());
2282 case AArch64::SEH_SaveFReg:
2284 MI->getOperand(1).getImm());
2287 case AArch64::SEH_SaveFReg_X:
2288 assert(
MI->getOperand(1).getImm() < 0 &&
2289 "Pre increment SEH opcode must have a negative offset");
2291 -
MI->getOperand(1).getImm());
2294 case AArch64::SEH_SaveFRegP:
2295 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2296 "Non-consecutive registers not allowed for save_regp");
2298 MI->getOperand(2).getImm());
2301 case AArch64::SEH_SaveFRegP_X:
2302 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2303 "Non-consecutive registers not allowed for save_regp_x");
2304 assert(
MI->getOperand(2).getImm() < 0 &&
2305 "Pre increment SEH opcode must have a negative offset");
2307 -
MI->getOperand(2).getImm());
2310 case AArch64::SEH_SetFP:
2314 case AArch64::SEH_AddFP:
2318 case AArch64::SEH_Nop:
2322 case AArch64::SEH_PrologEnd:
2326 case AArch64::SEH_EpilogStart:
2330 case AArch64::SEH_EpilogEnd:
2334 case AArch64::SEH_PACSignLR:
2338 case AArch64::SEH_SaveAnyRegQP:
2339 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2340 "Non-consecutive registers not allowed for save_any_reg");
2341 assert(
MI->getOperand(2).getImm() >= 0 &&
2342 "SaveAnyRegQP SEH opcode offset must be non-negative");
2343 assert(
MI->getOperand(2).getImm() <= 1008 &&
2344 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
2346 MI->getOperand(2).getImm());
2349 case AArch64::SEH_SaveAnyRegQPX:
2350 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2351 "Non-consecutive registers not allowed for save_any_reg");
2352 assert(
MI->getOperand(2).getImm() < 0 &&
2353 "SaveAnyRegQPX SEH opcode offset must be negative");
2354 assert(
MI->getOperand(2).getImm() >= -1008 &&
2355 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
2357 -
MI->getOperand(2).getImm());
2363 MCInstLowering.Lower(
MI, TmpInst);
2364 EmitToStreamer(*OutStreamer, TmpInst);
2380 MCInstLowering.lowerOperand(
2394 MCInstLowering.lowerOperand(
2404 .addReg(AArch64::X16)
2405 .addReg(AArch64::X16)
2416void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
2451 .addReg(AArch64::SP)
2452 .addReg(AArch64::FP)
2453 .addReg(AArch64::LR)
2454 .addReg(AArch64::SP)
2459 .addReg(AArch64::FP)
2460 .addReg(AArch64::SP)
2465 for (
int I = 0;
I != 4; ++
I)
2467 .addReg(AArch64::SP)
2468 .addReg(AArch64::X1 + 2 *
I)
2469 .addReg(AArch64::X0 + 2 *
I)
2470 .addReg(AArch64::SP)
2474 for (
int I = 0;
I != 4; ++
I)
2476 .addReg(AArch64::SP)
2477 .addReg(AArch64::D1 + 2 *
I)
2478 .addReg(AArch64::D0 + 2 *
I)
2479 .addReg(AArch64::SP)
2493 MCInstLowering.lowerOperand(
2507 MCInstLowering.lowerOperand(
2517 .addReg(AArch64::X0)
2518 .addReg(AArch64::X16)
2523 .addReg(AArch64::X16)
2524 .addReg(AArch64::X0)
2529 for (
int I = 3;
I != -1; --
I)
2531 .addReg(AArch64::SP)
2532 .addReg(AArch64::D1 + 2 *
I)
2533 .addReg(AArch64::D0 + 2 *
I)
2534 .addReg(AArch64::SP)
2538 for (
int I = 3;
I != -1; --
I)
2540 .addReg(AArch64::SP)
2541 .addReg(AArch64::X1 + 2 *
I)
2542 .addReg(AArch64::X0 + 2 *
I)
2543 .addReg(AArch64::SP)
2548 .addReg(AArch64::SP)
2549 .addReg(AArch64::FP)
2550 .addReg(AArch64::LR)
2551 .addReg(AArch64::SP)
2562const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV) {
2563 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64AsmPrinter()
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const typename MachineModuleInfoTarget::AuthStubInfo &StubInfo)
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#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).
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 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 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.
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.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
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.
AuthStubListTy 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.
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.
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
Reg
All possible values of the reg field in the ModR/M byte.
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.
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'...
@ 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,...