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")))
278 if (
const auto *GCS = mdconst::extract_or_null<ConstantInt>(
279 M.getModuleFlag(
"guarded-control-stack")))
283 if (
const auto *Sign = mdconst::extract_or_null<ConstantInt>(
284 M.getModuleFlag(
"sign-return-address")))
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(
853 const MCExpr *StubAuthPtrRef) {
856 OutStreamer.
emitValue(StubAuthPtrRef, 8);
859void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
860 emitHwasanMemaccessSymbols(M);
863 if (
TT.isOSBinFormatMachO()) {
870 if (!Stubs.empty()) {
872 OutStreamer->switchSection(
875 emitAlignment(
Align(8));
877 for (
const auto &Stub : Stubs)
880 OutStreamer->addBlankLine();
891 if (
TT.isOSBinFormatELF()) {
897 if (!Stubs.empty()) {
900 emitAlignment(
Align(8));
902 for (
const auto &Stub : Stubs)
905 OutStreamer->addBlankLine();
910 FM.serializeToFaultMapSection();
914void AArch64AsmPrinter::emitLOHs() {
917 for (
const auto &
D : AArch64FI->getLOHContainer()) {
919 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
920 assert(LabelIt != LOHInstToLabel.end() &&
921 "Label hasn't been inserted for LOH related instruction");
924 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
929void AArch64AsmPrinter::emitFunctionBodyEnd() {
930 if (!AArch64FI->getLOHRelated().empty())
935MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
939 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
940 return OutContext.getOrCreateSymbol(
941 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
942 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
947void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
965 PrintSymbolOperand(MO, O);
976bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
1000bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
1003 assert(MO.
isReg() &&
"Should only get here with a register!");
1013bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
1022 if (ExtraCode && ExtraCode[0]) {
1023 if (ExtraCode[1] != 0)
1026 switch (ExtraCode[0]) {
1034 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
1048 switch (ExtraCode[0]) {
1050 RC = &AArch64::FPR8RegClass;
1053 RC = &AArch64::FPR16RegClass;
1056 RC = &AArch64::FPR32RegClass;
1059 RC = &AArch64::FPR64RegClass;
1062 RC = &AArch64::FPR128RegClass;
1065 RC = &AArch64::ZPRRegClass;
1070 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1083 if (AArch64::GPR32allRegClass.
contains(Reg) ||
1084 AArch64::GPR64allRegClass.
contains(Reg))
1088 if (AArch64::GPR64x8ClassRegClass.
contains(Reg))
1091 unsigned AltName = AArch64::NoRegAltName;
1093 if (AArch64::ZPRRegClass.
contains(Reg)) {
1094 RegClass = &AArch64::ZPRRegClass;
1095 }
else if (AArch64::PPRRegClass.
contains(Reg)) {
1096 RegClass = &AArch64::PPRRegClass;
1097 }
else if (AArch64::PNRRegClass.
contains(Reg)) {
1098 RegClass = &AArch64::PNRRegClass;
1100 RegClass = &AArch64::FPR128RegClass;
1101 AltName = AArch64::vreg;
1105 return printAsmRegInClass(MO, RegClass, AltName, O);
1112bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1114 const char *ExtraCode,
1116 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1120 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1125void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1127 unsigned NOps =
MI->getNumOperands();
1129 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1131 OS <<
MI->getDebugVariable()->getName();
1134 assert(
MI->isIndirectDebugValue());
1136 for (
unsigned I = 0, E = std::distance(
MI->debug_operands().begin(),
1137 MI->debug_operands().end());
1148void AArch64AsmPrinter::emitJumpTableInfo() {
1153 if (
JT.empty())
return;
1157 OutStreamer->switchSection(ReadOnlySec);
1160 for (
unsigned JTI = 0, e =
JT.size(); JTI !=
e; ++JTI) {
1161 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1164 if (JTBBs.empty())
continue;
1166 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1168 OutStreamer->emitLabel(GetJTISymbol(JTI));
1170 const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1173 for (
auto *JTBB : JTBBs) {
1193AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1195 const MCSymbol *BranchLabel)
const {
1197 const auto Base = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1199 switch (AFI->getJumpTableEntrySize(JTI)) {
1201 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1204 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1207 EntrySize = codeview::JumpTableEntrySize::Int32;
1212 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1215void AArch64AsmPrinter::emitFunctionEntryLabel() {
1217 MF->getFunction().getCallingConv() ==
1227 if (
TM.getTargetTriple().isWindowsArm64EC() &&
1228 !MF->getFunction().hasLocalLinkage()) {
1233 OutStreamer->emitAssignment(
1235 MMI->getContext()));
1241 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1242 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1248 getSymbolFromMetadata(
"arm64ec_unmangled_name")) {
1249 MCSymbol *ECMangledSym = getSymbolFromMetadata(
"arm64ec_ecmangled_name");
1255 emitFunctionAlias(UnmangledSym, ECMangledSym);
1256 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1260 emitFunctionAlias(UnmangledSym, CurrentFnSym);
1277 Register DestReg =
MI.getOperand(0).getReg();
1278 Register ScratchReg =
MI.getOperand(1).getReg();
1280 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1281 Register TableReg =
MI.getOperand(2).getReg();
1282 Register EntryReg =
MI.getOperand(3).getReg();
1283 int JTIdx =
MI.getOperand(4).getIndex();
1284 int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
1294 Label = MF->getContext().createTempSymbol();
1295 AArch64FI->setJumpTableEntryInfo(JTIdx,
Size, Label);
1302 .addExpr(LabelExpr));
1307 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1308 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1309 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1315 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1319 .addImm(
Size == 1 ? 0 : 1));
1327 .addImm(
Size == 4 ? 0 : 2));
1332 unsigned Opcode =
MI.getOpcode();
1334 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1336 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1337 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1338 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1339 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1340 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1341 if (Opcode == AArch64::MOPSMemorySetPseudo)
1342 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1343 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1344 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1347 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1348 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1350 for (
auto Op : Ops) {
1354 MCIB.addReg(
MI.getOperand(i++).getReg());
1355 MCIB.addReg(
MI.getOperand(i++).getReg());
1357 MCIB.addReg(
MI.getOperand(i++).getReg());
1359 MCIB.addReg(
MI.getOperand(i++).getReg());
1360 MCIB.addReg(
MI.getOperand(i++).getReg());
1361 MCIB.addReg(
MI.getOperand(i++).getReg());
1363 EmitToStreamer(OutStreamer, MCIB);
1372 MCSymbol *MILabel = Ctx.createTempSymbol();
1376 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1382 while (NumNOPBytes > 0) {
1383 if (MII ==
MBB.
end() || MII->isCall() ||
1384 MII->getOpcode() == AArch64::DBG_VALUE ||
1385 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1386 MII->getOpcode() == TargetOpcode::STACKMAP)
1393 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1394 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1402 MCSymbol *MILabel = Ctx.createTempSymbol();
1408 int64_t CallTarget = Opers.getCallTarget().getImm();
1409 unsigned EncodedBytes = 0;
1411 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1412 "High 16 bits of call target should be zero.");
1413 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1418 .addImm((CallTarget >> 32) & 0xFFFF)
1423 .addImm((CallTarget >> 16) & 0xFFFF)
1428 .addImm(CallTarget & 0xFFFF)
1430 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1433 unsigned NumBytes = Opers.getNumPatchBytes();
1434 assert(NumBytes >= EncodedBytes &&
1435 "Patchpoint can't request size less than the length of a call.");
1436 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1437 "Invalid number of NOP bytes requested!");
1438 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1439 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1445 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1446 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1447 for (
unsigned i = 0; i < PatchBytes; i += 4)
1448 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1453 unsigned CallOpcode;
1454 switch (CallTarget.
getType()) {
1457 MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
1458 CallOpcode = AArch64::BL;
1462 CallOpcode = AArch64::BL;
1466 CallOpcode = AArch64::BLR;
1473 EmitToStreamer(OutStreamer,
1478 MCSymbol *MILabel = Ctx.createTempSymbol();
1483void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1492 unsigned OperandsBeginIdx = 4;
1495 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1499 FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
1502 MI.setOpcode(Opcode);
1510 lowerOperand(MO, Dest);
1511 MI.addOperand(Dest);
1519 Register DestReg =
MI.getOperand(0).getReg();
1520 if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() &&
1521 STI->isNeonAvailable()) {
1523 if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
1524 DestReg = AArch64::D0 + (DestReg - AArch64::H0);
1525 else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
1526 DestReg = AArch64::D0 + (DestReg - AArch64::S0);
1528 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
1531 MOVI.setOpcode(AArch64::MOVID);
1534 EmitToStreamer(*OutStreamer, MOVI);
1537 switch (
MI.getOpcode()) {
1539 case AArch64::FMOVH0:
1540 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1541 if (!STI->hasFullFP16())
1542 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1546 case AArch64::FMOVS0:
1551 case AArch64::FMOVD0:
1557 EmitToStreamer(*OutStreamer, FMov);
1561unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(
uint16_t Disc,
1563 unsigned &InstsEmitted) {
1565 if (AddrDisc == AArch64::NoRegister)
1566 AddrDisc = AArch64::XZR;
1574 if (AddrDisc == AArch64::XZR) {
1576 .addReg(AArch64::X17)
1580 return AArch64::X17;
1585 .addReg(AArch64::X17)
1586 .addReg(AArch64::XZR)
1591 .addReg(AArch64::X17)
1592 .addReg(AArch64::X17)
1596 return AArch64::X17;
1599void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
1600 unsigned InstsEmitted = 0;
1601 unsigned BrTarget =
MI->getOperand(0).getReg();
1605 "Invalid auth call key");
1608 assert(isUInt<16>(Disc));
1610 unsigned AddrDisc =
MI->getOperand(3).getReg();
1613 unsigned DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, InstsEmitted);
1614 bool IsZeroDisc = DiscReg == AArch64::XZR;
1618 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
1620 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
1627 EmitToStreamer(*OutStreamer, BRInst);
1630 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
1640 getDataLayout(),
Offset,
true);
1642 auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
1648 "cannot resolve target base/addend of ptrauth constant");
1666 "' out of range [0, " +
1670 if (!isUInt<16>(Disc))
1672 "' out of range [0, 0xFFFF]");
1679void AArch64AsmPrinter::LowerLOADauthptrstatic(
const MachineInstr &
MI) {
1680 unsigned DstReg =
MI.getOperand(0).getReg();
1682 const uint64_t KeyC =
MI.getOperand(2).getImm();
1684 "key is out of range [0, AArch64PACKey::LAST]");
1686 const uint64_t Disc =
MI.getOperand(3).getImm();
1687 assert(isUInt<16>(Disc) &&
1688 "constant discriminator is out of range [0, 0xffff]");
1697 if (
TM.getTargetTriple().isOSBinFormatELF()) {
1702 "non-zero offset for $auth_ptr$ stub slots is not supported");
1705 TLOF.getAuthPtrSlotSymbol(
TM, &MF->getMMI(), GASym, Key, Disc);
1707 assert(
TM.getTargetTriple().isOSBinFormatMachO() &&
1708 "LOADauthptrstatic is implemented only for MachO/ELF");
1711 getObjFileLowering());
1714 "non-zero offset for $auth_ptr$ stub slots is not supported");
1717 TLOF.getAuthPtrSlotSymbol(
TM, &MF->getMMI(), GASym, Key, Disc);
1726 MCInstLowering.lowerOperand(StubMOHi, StubMCHi);
1727 MCInstLowering.lowerOperand(StubMOLo, StubMCLo);
1740 unsigned InstsEmitted = 0;
1741 auto EmitAndIncrement = [
this, &InstsEmitted](
const MCInst &Inst) {
1742 EmitToStreamer(*OutStreamer, Inst);
1746 const bool IsGOTLoad =
MI.getOpcode() == AArch64::LOADgotPAC;
1748 const uint64_t KeyC =
MI.getOperand(1).getImm();
1750 "key is out of range [0, AArch64PACKey::LAST]");
1752 const unsigned AddrDisc =
MI.getOperand(2).getReg();
1753 const uint64_t Disc =
MI.getOperand(3).getImm();
1754 assert(isUInt<16>(Disc) &&
1755 "constant discriminator is out of range [0, 0xffff]");
1804 MCInstLowering.lowerOperand(GAMOHi, GAMCHi);
1805 MCInstLowering.lowerOperand(GAMOLo, GAMCLo);
1812 .addReg(AArch64::X16)
1813 .addReg(AArch64::X16)
1817 .addReg(AArch64::X16)
1818 .addReg(AArch64::X16)
1825 const bool IsNeg =
Offset < 0;
1826 if (isUInt<24>(AbsOffset)) {
1827 for (
int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos);
1831 .addReg(AArch64::X16)
1832 .addReg(AArch64::X16)
1833 .addImm((AbsOffset >> BitPos) & 0xfff)
1838 EmitAndIncrement(
MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi)
1839 .addReg(AArch64::X17)
1840 .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff)
1842 auto NeedMovk = [IsNeg, UOffset](
int BitPos) ->
bool {
1843 assert(BitPos == 16 || BitPos == 32 || BitPos == 48);
1844 uint64_t Shifted = UOffset >> BitPos;
1846 return Shifted != 0;
1847 for (
int I = 0;
I != 64 - BitPos;
I += 16)
1848 if (((Shifted >>
I) & 0xffff) != 0xffff)
1852 for (
int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16) {
1854 .addReg(AArch64::X17)
1855 .addReg(AArch64::X17)
1856 .addImm((UOffset >> BitPos) & 0xffff)
1860 .addReg(AArch64::X16)
1861 .addReg(AArch64::X16)
1862 .addReg(AArch64::X17)
1867 unsigned DiscReg = AddrDisc;
1869 if (AddrDisc != AArch64::XZR) {
1871 .addReg(AArch64::X17)
1872 .addReg(AArch64::XZR)
1876 .addReg(AArch64::X17)
1877 .addReg(AArch64::X17)
1882 .addReg(AArch64::X17)
1886 DiscReg = AArch64::X17;
1892 if (DiscReg != AArch64::XZR)
1894 EmitAndIncrement(MIB);
1896 assert(STI->getInstrInfo()->getInstSizeInBytes(
MI) >= InstsEmitted * 4);
1901#include "AArch64GenMCPseudoLowering.inc"
1904 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
1907 if (emitPseudoExpansionLowering(*OutStreamer,
MI))
1910 if (
MI->getOpcode() == AArch64::ADRP) {
1911 for (
auto &Opd :
MI->operands()) {
1912 if (Opd.isSymbol() &&
StringRef(Opd.getSymbolName()) ==
1913 "swift_async_extendedFramePointerFlags") {
1914 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
1919 if (AArch64FI->getLOHRelated().count(
MI)) {
1921 MCSymbol *LOHLabel = createTempSymbol(
"loh");
1923 LOHInstToLabel[
MI] = LOHLabel;
1930 switch (
MI->getOpcode()) {
1933 case AArch64::HINT: {
1938 if (CurrentPatchableFunctionEntrySym &&
1939 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
1940 MI == &MF->front().front()) {
1941 int64_t
Imm =
MI->getOperand(0).getImm();
1942 if ((Imm & 32) && (
Imm & 6)) {
1944 MCInstLowering.Lower(
MI, Inst);
1945 EmitToStreamer(*OutStreamer, Inst);
1946 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
1947 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
1953 case AArch64::MOVMCSym: {
1954 Register DestReg =
MI->getOperand(0).getReg();
1962 MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
1963 MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
1970 EmitToStreamer(*OutStreamer, MovZ);
1978 EmitToStreamer(*OutStreamer, MovK);
1981 case AArch64::MOVIv2d_ns:
1989 if (STI->hasZeroCycleZeroingFPWorkaround() &&
1990 MI->getOperand(1).getImm() == 0) {
1992 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
1995 EmitToStreamer(*OutStreamer, TmpInst);
2000 case AArch64::DBG_VALUE:
2001 case AArch64::DBG_VALUE_LIST:
2005 PrintDebugValueComment(
MI,
OS);
2010 case AArch64::EMITBKEY: {
2012 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2013 ExceptionHandlingType != ExceptionHandling::ARM)
2016 if (getFunctionCFISectionType(*MF) == CFISection::None)
2023 case AArch64::EMITMTETAGGED: {
2025 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
2026 ExceptionHandlingType != ExceptionHandling::ARM)
2029 if (getFunctionCFISectionType(*MF) != CFISection::None)
2034 case AArch64::LOADauthptrstatic:
2035 LowerLOADauthptrstatic(*
MI);
2038 case AArch64::LOADgotPAC:
2039 case AArch64::MOVaddrPAC:
2040 LowerMOVaddrPAC(*
MI);
2044 emitPtrauthBranch(
MI);
2050 case AArch64::AUTH_TCRETURN:
2051 case AArch64::AUTH_TCRETURN_BTI: {
2054 "Invalid auth key for tail-call return");
2056 const uint64_t Disc =
MI->getOperand(3).getImm();
2057 assert(isUInt<16>(Disc) &&
"Integer discriminator is too wide");
2059 Register AddrDisc =
MI->getOperand(4).getReg();
2061 Register ScratchReg =
MI->getOperand(0).getReg() == AArch64::X16
2065 unsigned DiscReg = AddrDisc;
2067 if (AddrDisc != AArch64::NoRegister) {
2070 .addReg(AArch64::XZR)
2084 DiscReg = ScratchReg;
2087 const bool IsZero = DiscReg == AArch64::NoRegister;
2088 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
2089 {AArch64::BRAB, AArch64::BRABZ}};
2092 TmpInst.
setOpcode(Opcodes[Key][IsZero]);
2096 EmitToStreamer(*OutStreamer, TmpInst);
2100 case AArch64::TCRETURNri:
2101 case AArch64::TCRETURNrix16x17:
2102 case AArch64::TCRETURNrix17:
2103 case AArch64::TCRETURNrinotx16:
2104 case AArch64::TCRETURNriALL: {
2108 EmitToStreamer(*OutStreamer, TmpInst);
2111 case AArch64::TCRETURNdi: {
2113 MCInstLowering.lowerOperand(
MI->getOperand(0), Dest);
2117 EmitToStreamer(*OutStreamer, TmpInst);
2120 case AArch64::SpeculationBarrierISBDSBEndBB: {
2125 EmitToStreamer(*OutStreamer, TmpInstDSB);
2129 EmitToStreamer(*OutStreamer, TmpInstISB);
2132 case AArch64::SpeculationBarrierSBEndBB: {
2136 EmitToStreamer(*OutStreamer, TmpInstSB);
2139 case AArch64::TLSDESC_CALLSEQ: {
2152 MCInstLowering.lowerOperand(MO_Sym,
Sym);
2153 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
2154 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
2160 EmitToStreamer(*OutStreamer, Adrp);
2163 if (STI->isTargetILP32()) {
2173 EmitToStreamer(*OutStreamer, Ldr);
2176 if (STI->isTargetILP32()) {
2177 Add.setOpcode(AArch64::ADDWri);
2181 Add.setOpcode(AArch64::ADDXri);
2185 Add.addOperand(SymTLSDescLo12);
2187 EmitToStreamer(*OutStreamer,
Add);
2192 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
2194 EmitToStreamer(*OutStreamer, TLSDescCall);
2199 EmitToStreamer(*OutStreamer, Blr);
2204 case AArch64::JumpTableDest32:
2205 case AArch64::JumpTableDest16:
2206 case AArch64::JumpTableDest8:
2207 LowerJumpTableDest(*OutStreamer, *
MI);
2210 case AArch64::FMOVH0:
2211 case AArch64::FMOVS0:
2212 case AArch64::FMOVD0:
2216 case AArch64::MOPSMemoryCopyPseudo:
2217 case AArch64::MOPSMemoryMovePseudo:
2218 case AArch64::MOPSMemorySetPseudo:
2219 case AArch64::MOPSMemorySetTaggingPseudo:
2220 LowerMOPS(*OutStreamer, *
MI);
2223 case TargetOpcode::STACKMAP:
2224 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
2226 case TargetOpcode::PATCHPOINT:
2227 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
2229 case TargetOpcode::STATEPOINT:
2230 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
2232 case TargetOpcode::FAULTING_OP:
2233 return LowerFAULTING_OP(*
MI);
2235 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2236 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
2239 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2240 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
2243 case TargetOpcode::PATCHABLE_TAIL_CALL:
2244 LowerPATCHABLE_TAIL_CALL(*
MI);
2246 case TargetOpcode::PATCHABLE_EVENT_CALL:
2247 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
2248 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
2249 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
2251 case AArch64::KCFI_CHECK:
2252 LowerKCFI_CHECK(*
MI);
2255 case AArch64::HWASAN_CHECK_MEMACCESS:
2256 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
2257 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
2258 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
2259 LowerHWASAN_CHECK_MEMACCESS(*
MI);
2262 case AArch64::SEH_StackAlloc:
2266 case AArch64::SEH_SaveFPLR:
2270 case AArch64::SEH_SaveFPLR_X:
2271 assert(
MI->getOperand(0).getImm() < 0 &&
2272 "Pre increment SEH opcode must have a negative offset");
2276 case AArch64::SEH_SaveReg:
2278 MI->getOperand(1).getImm());
2281 case AArch64::SEH_SaveReg_X:
2282 assert(
MI->getOperand(1).getImm() < 0 &&
2283 "Pre increment SEH opcode must have a negative offset");
2285 -
MI->getOperand(1).getImm());
2288 case AArch64::SEH_SaveRegP:
2289 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
2290 MI->getOperand(0).getImm() <= 28) {
2291 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
2292 "Register paired with LR must be odd");
2294 MI->getOperand(2).getImm());
2297 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2298 "Non-consecutive registers not allowed for save_regp");
2300 MI->getOperand(2).getImm());
2303 case AArch64::SEH_SaveRegP_X:
2304 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2305 "Non-consecutive registers not allowed for save_regp_x");
2306 assert(
MI->getOperand(2).getImm() < 0 &&
2307 "Pre increment SEH opcode must have a negative offset");
2309 -
MI->getOperand(2).getImm());
2312 case AArch64::SEH_SaveFReg:
2314 MI->getOperand(1).getImm());
2317 case AArch64::SEH_SaveFReg_X:
2318 assert(
MI->getOperand(1).getImm() < 0 &&
2319 "Pre increment SEH opcode must have a negative offset");
2321 -
MI->getOperand(1).getImm());
2324 case AArch64::SEH_SaveFRegP:
2325 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2326 "Non-consecutive registers not allowed for save_regp");
2328 MI->getOperand(2).getImm());
2331 case AArch64::SEH_SaveFRegP_X:
2332 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2333 "Non-consecutive registers not allowed for save_regp_x");
2334 assert(
MI->getOperand(2).getImm() < 0 &&
2335 "Pre increment SEH opcode must have a negative offset");
2337 -
MI->getOperand(2).getImm());
2340 case AArch64::SEH_SetFP:
2344 case AArch64::SEH_AddFP:
2348 case AArch64::SEH_Nop:
2352 case AArch64::SEH_PrologEnd:
2356 case AArch64::SEH_EpilogStart:
2360 case AArch64::SEH_EpilogEnd:
2364 case AArch64::SEH_PACSignLR:
2368 case AArch64::SEH_SaveAnyRegQP:
2369 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2370 "Non-consecutive registers not allowed for save_any_reg");
2371 assert(
MI->getOperand(2).getImm() >= 0 &&
2372 "SaveAnyRegQP SEH opcode offset must be non-negative");
2373 assert(
MI->getOperand(2).getImm() <= 1008 &&
2374 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
2376 MI->getOperand(2).getImm());
2379 case AArch64::SEH_SaveAnyRegQPX:
2380 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2381 "Non-consecutive registers not allowed for save_any_reg");
2382 assert(
MI->getOperand(2).getImm() < 0 &&
2383 "SaveAnyRegQPX SEH opcode offset must be negative");
2384 assert(
MI->getOperand(2).getImm() >= -1008 &&
2385 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
2387 -
MI->getOperand(2).getImm());
2393 MCInstLowering.Lower(
MI, TmpInst);
2394 EmitToStreamer(*OutStreamer, TmpInst);
2410 MCInstLowering.lowerOperand(
2424 MCInstLowering.lowerOperand(
2434 .addReg(AArch64::X16)
2435 .addReg(AArch64::X16)
2446void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
2481 .addReg(AArch64::SP)
2482 .addReg(AArch64::FP)
2483 .addReg(AArch64::LR)
2484 .addReg(AArch64::SP)
2489 .addReg(AArch64::FP)
2490 .addReg(AArch64::SP)
2495 for (
int I = 0;
I != 4; ++
I)
2497 .addReg(AArch64::SP)
2498 .addReg(AArch64::X1 + 2 *
I)
2499 .addReg(AArch64::X0 + 2 *
I)
2500 .addReg(AArch64::SP)
2504 for (
int I = 0;
I != 4; ++
I)
2506 .addReg(AArch64::SP)
2507 .addReg(AArch64::D1 + 2 *
I)
2508 .addReg(AArch64::D0 + 2 *
I)
2509 .addReg(AArch64::SP)
2523 MCInstLowering.lowerOperand(
2537 MCInstLowering.lowerOperand(
2547 .addReg(AArch64::X0)
2548 .addReg(AArch64::X16)
2553 .addReg(AArch64::X16)
2554 .addReg(AArch64::X0)
2559 for (
int I = 3;
I != -1; --
I)
2561 .addReg(AArch64::SP)
2562 .addReg(AArch64::D1 + 2 *
I)
2563 .addReg(AArch64::D0 + 2 *
I)
2564 .addReg(AArch64::SP)
2568 for (
int I = 3;
I != -1; --
I)
2570 .addReg(AArch64::SP)
2571 .addReg(AArch64::X1 + 2 *
I)
2572 .addReg(AArch64::X0 + 2 *
I)
2573 .addReg(AArch64::SP)
2578 .addReg(AArch64::SP)
2579 .addReg(AArch64::FP)
2580 .addReg(AArch64::LR)
2581 .addReg(AArch64::SP)
2592const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV) {
2593 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
static void emitAuthenticatedPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, const MCExpr *StubAuthPtrRef)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64AsmPrinter()
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).
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 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.
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.
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.
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,...