70#define DEBUG_TYPE "asm-printer"
78 bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
false;
81 AArch64AsmPrinter(
TargetMachine &
TM, std::unique_ptr<MCStreamer> Streamer)
82 :
AsmPrinter(
TM, std::move(Streamer)), MCInstLowering(OutContext, *
this),
98 const MCSymbol *BranchLabel)
const override;
117 void LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
bool Typed);
119 typedef std::tuple<unsigned, bool, uint32_t, bool, uint64_t>
120 HwasanMemaccessTuple;
121 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
124 void emitHwasanMemaccessSymbols(
Module &M);
131 unsigned emitPtrauthDiscriminator(
uint16_t Disc,
unsigned AddrDisc,
132 unsigned &InstsEmitted);
136 bool emitPseudoExpansionLowering(
MCStreamer &OutStreamer,
141 void emitFunctionHeaderComment()
override;
154 if (STI->isTargetCOFF()) {
206 using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
208 MInstToMCSymbol LOHInstToLabel;
211 return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
226void AArch64AsmPrinter::emitStartOfAsmFile(
Module &M) {
229 if (
TT.isOSBinFormatCOFF()) {
232 OutStreamer->beginCOFFSymbolDef(S);
235 OutStreamer->endCOFFSymbolDef();
236 int64_t Feat00Value = 0;
238 if (
M.getModuleFlag(
"cfguard")) {
240 Feat00Value |= COFF::Feat00Flags::GuardCF;
243 if (
M.getModuleFlag(
"ehcontguard")) {
245 Feat00Value |= COFF::Feat00Flags::GuardEHCont;
248 if (
M.getModuleFlag(
"ms-kernel")) {
250 Feat00Value |= COFF::Feat00Flags::Kernel;
254 OutStreamer->emitAssignment(
258 if (!
TT.isOSBinFormatELF())
263 if (
const auto *BTE = mdconst::extract_or_null<ConstantInt>(
264 M.getModuleFlag(
"branch-target-enforcement")))
265 if (BTE->getZExtValue())
268 if (
const auto *GCS = mdconst::extract_or_null<ConstantInt>(
269 M.getModuleFlag(
"guarded-control-stack")))
270 if (GCS->getZExtValue())
273 if (
const auto *Sign = mdconst::extract_or_null<ConstantInt>(
274 M.getModuleFlag(
"sign-return-address")))
275 if (Sign->getZExtValue())
279 if (
const auto *PAP = mdconst::extract_or_null<ConstantInt>(
280 M.getModuleFlag(
"aarch64-elf-pauthabi-platform")))
281 PAuthABIPlatform = PAP->getZExtValue();
283 if (
const auto *PAV = mdconst::extract_or_null<ConstantInt>(
284 M.getModuleFlag(
"aarch64-elf-pauthabi-version")))
285 PAuthABIVersion = PAV->getZExtValue();
293void AArch64AsmPrinter::emitFunctionHeaderComment() {
296 if (OutlinerString != std::nullopt)
297 OutStreamer->getCommentOS() <<
' ' << OutlinerString;
300void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
303 if (
F.hasFnAttribute(
"patchable-function-entry")) {
305 if (
F.getFnAttribute(
"patchable-function-entry")
307 .getAsInteger(10, Num))
313 emitSled(
MI, SledKind::FUNCTION_ENTER);
316void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI) {
317 emitSled(
MI, SledKind::FUNCTION_EXIT);
320void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI) {
321 emitSled(
MI, SledKind::TAIL_CALL);
324void AArch64AsmPrinter::emitSled(
const MachineInstr &
MI, SledKind Kind) {
325 static const int8_t NoopsInSledCount = 7;
346 OutStreamer->emitCodeAlignment(
Align(4), &getSubtargetInfo());
347 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
348 OutStreamer->emitLabel(CurSled);
349 auto Target = OutContext.createTempSymbol();
354 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::B).addImm(8));
356 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
357 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
359 OutStreamer->emitLabel(
Target);
360 recordSled(CurSled,
MI, Kind, 2);
378void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(
const MachineInstr &
MI,
380 auto &
O = *OutStreamer;
381 MCSymbol *CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
382 O.emitLabel(CurSled);
393 bool MachO =
TM.getTargetTriple().isOSBinFormatMachO();
395 OutContext.getOrCreateSymbol(
396 Twine(MachO ?
"_" :
"") +
397 (Typed ?
"__xray_TypedEvent" :
"__xray_CustomEvent")),
400 O.AddComment(
"Begin XRay typed event");
412 EmitToStreamer(O, MovX0Op0);
413 EmitToStreamer(O, MovX1Op1);
416 .addReg(AArch64::XZR)
417 .addReg(
MI.getOperand(2).getReg())
424 O.AddComment(
"End XRay typed event");
432 recordSled(CurSled,
MI, SledKind::TYPED_EVENT, 2);
434 O.AddComment(
"Begin XRay custom event");
442 EmitToStreamer(O, MovX0Op0);
443 EmitToStreamer(O, MovX1Op1);
445 O.AddComment(
"End XRay custom event");
453 recordSled(CurSled,
MI, SledKind::CUSTOM_EVENT, 2);
459 assert(std::next(
MI.getIterator())->isCall() &&
460 "KCFI_CHECK not followed by a call instruction");
461 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
462 "KCFI_CHECK call target doesn't match call operand");
466 unsigned ScratchRegs[] = {AArch64::W16, AArch64::W17};
467 if (AddrReg == AArch64::XZR) {
473 .addReg(AArch64::XZR)
474 .addReg(AArch64::XZR)
481 for (
auto &Reg : ScratchRegs) {
487 assert(ScratchRegs[0] != AddrReg && ScratchRegs[1] != AddrReg &&
488 "Invalid scratch registers for KCFI_CHECK");
492 int64_t PrefixNops = 0;
495 .getFnAttribute(
"patchable-function-prefix")
497 .getAsInteger(10, PrefixNops);
501 .addReg(ScratchRegs[0])
503 .addImm(-(PrefixNops * 4 + 4)));
507 const int64_t
Type =
MI.getOperand(1).getImm();
509 .addReg(ScratchRegs[1])
510 .addReg(ScratchRegs[1])
511 .addImm(
Type & 0xFFFF)
514 .addReg(ScratchRegs[1])
515 .addReg(ScratchRegs[1])
516 .addImm((
Type >> 16) & 0xFFFF)
521 .addReg(AArch64::WZR)
522 .addReg(ScratchRegs[0])
523 .addReg(ScratchRegs[1])
527 EmitToStreamer(*OutStreamer,
537 unsigned TypeIndex = ScratchRegs[1] - AArch64::W0;
541 AddrIndex = AddrReg - AArch64::X0;
551 assert(AddrIndex < 31 && TypeIndex < 31);
553 unsigned ESR = 0x8000 | ((TypeIndex & 31) << 5) | (AddrIndex & 31);
554 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::BRK).addImm(ESR));
555 OutStreamer->emitLabel(
Pass);
558void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
561 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES) ||
563 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
564 uint32_t AccessInfo =
MI.getOperand(1).getImm();
566 ((
MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW) ||
568 AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW));
569 uint64_t FixedShadowOffset = IsFixedShadow ?
MI.getOperand(2).getImm() : 0;
571 MCSymbol *&
Sym = HwasanMemaccessSymbols[HwasanMemaccessTuple(
572 Reg, IsShort, AccessInfo, IsFixedShadow, FixedShadowOffset)];
575 if (!
TM.getTargetTriple().isOSBinFormatELF())
578 std::string SymName =
"__hwasan_check_x" + utostr(Reg - AArch64::X0) +
"_" +
581 SymName +=
"_fixed_" + utostr(FixedShadowOffset);
583 SymName +=
"_short_v2";
584 Sym = OutContext.getOrCreateSymbol(SymName);
587 EmitToStreamer(*OutStreamer,
592void AArch64AsmPrinter::emitHwasanMemaccessSymbols(
Module &M) {
593 if (HwasanMemaccessSymbols.empty())
598 std::unique_ptr<MCSubtargetInfo> STI(
599 TM.getTarget().createMCSubtargetInfo(
TT.str(),
"",
""));
600 assert(STI &&
"Unable to create subtarget info");
603 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch");
605 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
612 for (
auto &
P : HwasanMemaccessSymbols) {
613 unsigned Reg = std::get<0>(
P.first);
614 bool IsShort = std::get<1>(
P.first);
615 uint32_t AccessInfo = std::get<2>(
P.first);
616 bool IsFixedShadow = std::get<3>(
P.first);
617 uint64_t FixedShadowOffset = std::get<4>(
P.first);
619 IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
622 bool HasMatchAllTag =
624 uint8_t MatchAllTag =
631 OutStreamer->switchSection(OutContext.getELFSection(
639 OutStreamer->emitLabel(
Sym);
655 .
addImm(FixedShadowOffset >> 32)
658 OutStreamer->emitInstruction(
MCInstBuilder(AArch64::LDRBBroX)
666 OutStreamer->emitInstruction(
669 .
addReg(IsShort ? AArch64::X20 : AArch64::X9)
676 OutStreamer->emitInstruction(
683 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
684 OutStreamer->emitInstruction(
690 MCSymbol *ReturnSym = OutContext.createTempSymbol();
691 OutStreamer->emitLabel(ReturnSym);
692 OutStreamer->emitInstruction(
694 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
696 if (HasMatchAllTag) {
709 OutStreamer->emitInstruction(
723 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
724 OutStreamer->emitInstruction(
730 OutStreamer->emitInstruction(
749 OutStreamer->emitInstruction(
755 OutStreamer->emitInstruction(
766 OutStreamer->emitInstruction(
773 OutStreamer->emitInstruction(
779 OutStreamer->emitLabel(HandleMismatchSym);
796 if (Reg != AArch64::X0)
803 OutStreamer->emitInstruction(
814 OutStreamer->emitInstruction(
820 OutStreamer->emitInstruction(
824 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
827 OutStreamer->emitInstruction(
832 HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
835 OutStreamer->emitInstruction(
841void AArch64AsmPrinter::emitEndOfAsmFile(
Module &M) {
842 emitHwasanMemaccessSymbols(M);
845 if (
TT.isOSBinFormatMachO()) {
855 FM.serializeToFaultMapSection();
859void AArch64AsmPrinter::emitLOHs() {
862 for (
const auto &
D : AArch64FI->getLOHContainer()) {
864 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(
MI);
865 assert(LabelIt != LOHInstToLabel.end() &&
866 "Label hasn't been inserted for LOH related instruction");
869 OutStreamer->emitLOHDirective(
D.getKind(), MCArgs);
874void AArch64AsmPrinter::emitFunctionBodyEnd() {
875 if (!AArch64FI->getLOHRelated().empty())
880MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
884 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
885 return OutContext.getOrCreateSymbol(
886 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
887 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
892void AArch64AsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
910 PrintSymbolOperand(MO, O);
921bool AArch64AsmPrinter::printAsmMRegister(
const MachineOperand &MO,
char Mode,
945bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
948 assert(MO.
isReg() &&
"Should only get here with a register!");
958bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNum,
967 if (ExtraCode && ExtraCode[0]) {
968 if (ExtraCode[1] != 0)
971 switch (ExtraCode[0]) {
979 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
993 switch (ExtraCode[0]) {
995 RC = &AArch64::FPR8RegClass;
998 RC = &AArch64::FPR16RegClass;
1001 RC = &AArch64::FPR32RegClass;
1004 RC = &AArch64::FPR64RegClass;
1007 RC = &AArch64::FPR128RegClass;
1010 RC = &AArch64::ZPRRegClass;
1015 return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
1028 if (AArch64::GPR32allRegClass.
contains(Reg) ||
1029 AArch64::GPR64allRegClass.
contains(Reg))
1033 if (AArch64::GPR64x8ClassRegClass.
contains(Reg))
1036 unsigned AltName = AArch64::NoRegAltName;
1038 if (AArch64::ZPRRegClass.
contains(Reg)) {
1039 RegClass = &AArch64::ZPRRegClass;
1040 }
else if (AArch64::PPRRegClass.
contains(Reg)) {
1041 RegClass = &AArch64::PPRRegClass;
1042 }
else if (AArch64::PNRRegClass.
contains(Reg)) {
1043 RegClass = &AArch64::PNRRegClass;
1045 RegClass = &AArch64::FPR128RegClass;
1046 AltName = AArch64::vreg;
1050 return printAsmRegInClass(MO, RegClass, AltName, O);
1057bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
1059 const char *ExtraCode,
1061 if (ExtraCode && ExtraCode[0] && ExtraCode[0] !=
'a')
1065 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
1070void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *
MI,
1072 unsigned NOps =
MI->getNumOperands();
1074 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
1076 OS <<
MI->getDebugVariable()->getName();
1079 assert(
MI->isIndirectDebugValue());
1081 for (
unsigned I = 0, E = std::distance(
MI->debug_operands().begin(),
1082 MI->debug_operands().end());
1093void AArch64AsmPrinter::emitJumpTableInfo() {
1098 if (
JT.empty())
return;
1102 OutStreamer->switchSection(ReadOnlySec);
1105 for (
unsigned JTI = 0, e =
JT.size(); JTI !=
e; ++JTI) {
1106 const std::vector<MachineBasicBlock*> &JTBBs =
JT[JTI].MBBs;
1109 if (JTBBs.empty())
continue;
1111 unsigned Size = AFI->getJumpTableEntrySize(JTI);
1113 OutStreamer->emitLabel(GetJTISymbol(JTI));
1115 const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1118 for (
auto *JTBB : JTBBs) {
1138AArch64AsmPrinter::getCodeViewJumpTableInfo(
int JTI,
1140 const MCSymbol *BranchLabel)
const {
1142 const auto Base = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
1144 switch (AFI->getJumpTableEntrySize(JTI)) {
1146 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1149 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1152 EntrySize = codeview::JumpTableEntrySize::Int32;
1157 return std::make_tuple(
Base, 0, BranchLabel, EntrySize);
1160void AArch64AsmPrinter::emitFunctionEntryLabel() {
1162 MF->getFunction().getCallingConv() ==
1172 if (
TM.getTargetTriple().isWindowsArm64EC() &&
1173 !MF->getFunction().hasLocalLinkage()) {
1178 OutStreamer->emitAssignment(
1180 MMI->getContext()));
1186 StringRef NameStr = cast<MDString>(
Node->getOperand(0))->getString();
1187 Sym = MMI->getContext().getOrCreateSymbol(NameStr);
1193 getSymbolFromMetadata(
"arm64ec_unmangled_name")) {
1194 MCSymbol *ECMangledSym = getSymbolFromMetadata(
"arm64ec_ecmangled_name");
1200 emitFunctionAlias(UnmangledSym, ECMangledSym);
1201 emitFunctionAlias(ECMangledSym, CurrentFnSym);
1205 emitFunctionAlias(UnmangledSym, CurrentFnSym);
1222 Register DestReg =
MI.getOperand(0).getReg();
1223 Register ScratchReg =
MI.getOperand(1).getReg();
1225 STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
1226 Register TableReg =
MI.getOperand(2).getReg();
1227 Register EntryReg =
MI.getOperand(3).getReg();
1228 int JTIdx =
MI.getOperand(4).getIndex();
1229 int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
1239 Label = MF->getContext().createTempSymbol();
1240 AArch64FI->setJumpTableEntryInfo(JTIdx,
Size, Label);
1247 .addExpr(LabelExpr));
1252 case 1: LdrOpcode = AArch64::LDRBBroX;
break;
1253 case 2: LdrOpcode = AArch64::LDRHHroX;
break;
1254 case 4: LdrOpcode = AArch64::LDRSWroX;
break;
1260 .addReg(
Size == 4 ? ScratchReg : ScratchRegW)
1264 .addImm(
Size == 1 ? 0 : 1));
1272 .addImm(
Size == 4 ? 0 : 2));
1277 unsigned Opcode =
MI.getOpcode();
1279 assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
1281 const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
1282 if (Opcode == AArch64::MOPSMemoryCopyPseudo)
1283 return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
1284 if (Opcode == AArch64::MOPSMemoryMovePseudo)
1285 return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
1286 if (Opcode == AArch64::MOPSMemorySetPseudo)
1287 return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
1288 if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
1289 return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
1292 const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
1293 Opcode == AArch64::MOPSMemorySetTaggingPseudo;
1295 for (
auto Op : Ops) {
1299 MCIB.addReg(
MI.getOperand(i++).getReg());
1300 MCIB.addReg(
MI.getOperand(i++).getReg());
1302 MCIB.addReg(
MI.getOperand(i++).getReg());
1304 MCIB.addReg(
MI.getOperand(i++).getReg());
1305 MCIB.addReg(
MI.getOperand(i++).getReg());
1306 MCIB.addReg(
MI.getOperand(i++).getReg());
1308 EmitToStreamer(OutStreamer, MCIB);
1317 MCSymbol *MILabel = Ctx.createTempSymbol();
1321 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1327 while (NumNOPBytes > 0) {
1328 if (MII ==
MBB.
end() || MII->isCall() ||
1329 MII->getOpcode() == AArch64::DBG_VALUE ||
1330 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
1331 MII->getOpcode() == TargetOpcode::STACKMAP)
1338 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
1339 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1347 MCSymbol *MILabel = Ctx.createTempSymbol();
1353 int64_t CallTarget = Opers.getCallTarget().getImm();
1354 unsigned EncodedBytes = 0;
1356 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
1357 "High 16 bits of call target should be zero.");
1358 Register ScratchReg =
MI.getOperand(Opers.getNextScratchIdx()).getReg();
1363 .addImm((CallTarget >> 32) & 0xFFFF)
1368 .addImm((CallTarget >> 16) & 0xFFFF)
1373 .addImm(CallTarget & 0xFFFF)
1375 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
1378 unsigned NumBytes = Opers.getNumPatchBytes();
1379 assert(NumBytes >= EncodedBytes &&
1380 "Patchpoint can't request size less than the length of a call.");
1381 assert((NumBytes - EncodedBytes) % 4 == 0 &&
1382 "Invalid number of NOP bytes requested!");
1383 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
1384 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1390 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
1391 assert(PatchBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
1392 for (
unsigned i = 0; i < PatchBytes; i += 4)
1393 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
1398 unsigned CallOpcode;
1399 switch (CallTarget.
getType()) {
1402 MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
1403 CallOpcode = AArch64::BL;
1407 CallOpcode = AArch64::BL;
1411 CallOpcode = AArch64::BLR;
1418 EmitToStreamer(OutStreamer,
1423 MCSymbol *MILabel = Ctx.createTempSymbol();
1428void AArch64AsmPrinter::LowerFAULTING_OP(
const MachineInstr &FaultingMI) {
1437 unsigned OperandsBeginIdx = 4;
1440 MCSymbol *FaultingLabel = Ctx.createTempSymbol();
1444 FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
1447 MI.setOpcode(Opcode);
1455 lowerOperand(MO, Dest);
1456 MI.addOperand(Dest);
1464 Register DestReg =
MI.getOperand(0).getReg();
1465 if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() &&
1466 STI->isNeonAvailable()) {
1468 if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
1469 DestReg = AArch64::D0 + (DestReg - AArch64::H0);
1470 else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
1471 DestReg = AArch64::D0 + (DestReg - AArch64::S0);
1473 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
1476 MOVI.setOpcode(AArch64::MOVID);
1479 EmitToStreamer(*OutStreamer, MOVI);
1482 switch (
MI.getOpcode()) {
1484 case AArch64::FMOVH0:
1485 FMov.
setOpcode(STI->hasFullFP16() ? AArch64::FMOVWHr : AArch64::FMOVWSr);
1486 if (!STI->hasFullFP16())
1487 DestReg = (AArch64::S0 + (DestReg - AArch64::H0));
1491 case AArch64::FMOVS0:
1496 case AArch64::FMOVD0:
1502 EmitToStreamer(*OutStreamer, FMov);
1506unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(
uint16_t Disc,
1508 unsigned &InstsEmitted) {
1510 if (AddrDisc == AArch64::NoRegister)
1511 AddrDisc = AArch64::XZR;
1519 if (AddrDisc == AArch64::XZR) {
1521 .addReg(AArch64::X17)
1525 return AArch64::X17;
1530 .addReg(AArch64::X17)
1531 .addReg(AArch64::XZR)
1536 .addReg(AArch64::X17)
1537 .addReg(AArch64::X17)
1541 return AArch64::X17;
1544void AArch64AsmPrinter::emitPtrauthBranch(
const MachineInstr *
MI) {
1545 unsigned InstsEmitted = 0;
1546 unsigned BrTarget =
MI->getOperand(0).getReg();
1550 "Invalid auth call key");
1553 assert(isUInt<16>(Disc));
1555 unsigned AddrDisc =
MI->getOperand(3).getReg();
1558 unsigned DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, InstsEmitted);
1559 bool IsZeroDisc = DiscReg == AArch64::XZR;
1563 Opc = IsZeroDisc ? AArch64::BLRAAZ : AArch64::BLRAA;
1565 Opc = IsZeroDisc ? AArch64::BLRABZ : AArch64::BLRAB;
1572 EmitToStreamer(*OutStreamer, BRInst);
1575 assert(STI->getInstrInfo()->getInstSizeInBytes(*
MI) >= InstsEmitted * 4);
1580#include "AArch64GenMCPseudoLowering.inc"
1583 AArch64_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
1586 if (emitPseudoExpansionLowering(*OutStreamer,
MI))
1589 if (
MI->getOpcode() == AArch64::ADRP) {
1590 for (
auto &Opd :
MI->operands()) {
1591 if (Opd.isSymbol() &&
StringRef(Opd.getSymbolName()) ==
1592 "swift_async_extendedFramePointerFlags") {
1593 ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags =
true;
1598 if (AArch64FI->getLOHRelated().count(
MI)) {
1600 MCSymbol *LOHLabel = createTempSymbol(
"loh");
1602 LOHInstToLabel[
MI] = LOHLabel;
1609 switch (
MI->getOpcode()) {
1612 case AArch64::HINT: {
1617 if (CurrentPatchableFunctionEntrySym &&
1618 CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
1619 MI == &MF->front().front()) {
1620 int64_t
Imm =
MI->getOperand(0).getImm();
1621 if ((Imm & 32) && (
Imm & 6)) {
1623 MCInstLowering.Lower(
MI, Inst);
1624 EmitToStreamer(*OutStreamer, Inst);
1625 CurrentPatchableFunctionEntrySym = createTempSymbol(
"patch");
1626 OutStreamer->
emitLabel(CurrentPatchableFunctionEntrySym);
1632 case AArch64::MOVMCSym: {
1633 Register DestReg =
MI->getOperand(0).getReg();
1641 MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
1642 MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
1649 EmitToStreamer(*OutStreamer, MovZ);
1657 EmitToStreamer(*OutStreamer, MovK);
1660 case AArch64::MOVIv2d_ns:
1668 if (STI->hasZeroCycleZeroingFPWorkaround() &&
1669 MI->getOperand(1).getImm() == 0) {
1671 TmpInst.
setOpcode(AArch64::MOVIv16b_ns);
1674 EmitToStreamer(*OutStreamer, TmpInst);
1679 case AArch64::DBG_VALUE:
1680 case AArch64::DBG_VALUE_LIST:
1684 PrintDebugValueComment(
MI,
OS);
1689 case AArch64::EMITBKEY: {
1691 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
1692 ExceptionHandlingType != ExceptionHandling::ARM)
1695 if (getFunctionCFISectionType(*MF) == CFISection::None)
1702 case AArch64::EMITMTETAGGED: {
1704 if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
1705 ExceptionHandlingType != ExceptionHandling::ARM)
1708 if (getFunctionCFISectionType(*MF) != CFISection::None)
1714 emitPtrauthBranch(
MI);
1720 case AArch64::AUTH_TCRETURN:
1721 case AArch64::AUTH_TCRETURN_BTI: {
1724 "Invalid auth key for tail-call return");
1726 const uint64_t Disc =
MI->getOperand(3).getImm();
1727 assert(isUInt<16>(Disc) &&
"Integer discriminator is too wide");
1729 Register AddrDisc =
MI->getOperand(4).getReg();
1731 Register ScratchReg =
MI->getOperand(0).getReg() == AArch64::X16
1735 unsigned DiscReg = AddrDisc;
1737 if (AddrDisc != AArch64::NoRegister) {
1740 .addReg(AArch64::XZR)
1754 DiscReg = ScratchReg;
1757 const bool IsZero = DiscReg == AArch64::NoRegister;
1758 const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ},
1759 {AArch64::BRAB, AArch64::BRABZ}};
1762 TmpInst.
setOpcode(Opcodes[Key][IsZero]);
1766 EmitToStreamer(*OutStreamer, TmpInst);
1770 case AArch64::TCRETURNri:
1771 case AArch64::TCRETURNrix16x17:
1772 case AArch64::TCRETURNrix17:
1773 case AArch64::TCRETURNrinotx16:
1774 case AArch64::TCRETURNriALL: {
1778 EmitToStreamer(*OutStreamer, TmpInst);
1781 case AArch64::TCRETURNdi: {
1783 MCInstLowering.lowerOperand(
MI->getOperand(0), Dest);
1787 EmitToStreamer(*OutStreamer, TmpInst);
1790 case AArch64::SpeculationBarrierISBDSBEndBB: {
1795 EmitToStreamer(*OutStreamer, TmpInstDSB);
1799 EmitToStreamer(*OutStreamer, TmpInstISB);
1802 case AArch64::SpeculationBarrierSBEndBB: {
1806 EmitToStreamer(*OutStreamer, TmpInstSB);
1809 case AArch64::TLSDESC_CALLSEQ: {
1822 MCInstLowering.lowerOperand(MO_Sym,
Sym);
1823 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
1824 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
1830 EmitToStreamer(*OutStreamer, Adrp);
1833 if (STI->isTargetILP32()) {
1843 EmitToStreamer(*OutStreamer, Ldr);
1846 if (STI->isTargetILP32()) {
1847 Add.setOpcode(AArch64::ADDWri);
1851 Add.setOpcode(AArch64::ADDXri);
1855 Add.addOperand(SymTLSDescLo12);
1857 EmitToStreamer(*OutStreamer,
Add);
1862 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
1864 EmitToStreamer(*OutStreamer, TLSDescCall);
1869 EmitToStreamer(*OutStreamer, Blr);
1874 case AArch64::JumpTableDest32:
1875 case AArch64::JumpTableDest16:
1876 case AArch64::JumpTableDest8:
1877 LowerJumpTableDest(*OutStreamer, *
MI);
1880 case AArch64::FMOVH0:
1881 case AArch64::FMOVS0:
1882 case AArch64::FMOVD0:
1886 case AArch64::MOPSMemoryCopyPseudo:
1887 case AArch64::MOPSMemoryMovePseudo:
1888 case AArch64::MOPSMemorySetPseudo:
1889 case AArch64::MOPSMemorySetTaggingPseudo:
1890 LowerMOPS(*OutStreamer, *
MI);
1893 case TargetOpcode::STACKMAP:
1894 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
1896 case TargetOpcode::PATCHPOINT:
1897 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
1899 case TargetOpcode::STATEPOINT:
1900 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
1902 case TargetOpcode::FAULTING_OP:
1903 return LowerFAULTING_OP(*
MI);
1905 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
1906 LowerPATCHABLE_FUNCTION_ENTER(*
MI);
1909 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1910 LowerPATCHABLE_FUNCTION_EXIT(*
MI);
1913 case TargetOpcode::PATCHABLE_TAIL_CALL:
1914 LowerPATCHABLE_TAIL_CALL(*
MI);
1916 case TargetOpcode::PATCHABLE_EVENT_CALL:
1917 return LowerPATCHABLE_EVENT_CALL(*
MI,
false);
1918 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
1919 return LowerPATCHABLE_EVENT_CALL(*
MI,
true);
1921 case AArch64::KCFI_CHECK:
1922 LowerKCFI_CHECK(*
MI);
1925 case AArch64::HWASAN_CHECK_MEMACCESS:
1926 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
1927 case AArch64::HWASAN_CHECK_MEMACCESS_FIXEDSHADOW:
1928 case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES_FIXEDSHADOW:
1929 LowerHWASAN_CHECK_MEMACCESS(*
MI);
1932 case AArch64::SEH_StackAlloc:
1936 case AArch64::SEH_SaveFPLR:
1940 case AArch64::SEH_SaveFPLR_X:
1941 assert(
MI->getOperand(0).getImm() < 0 &&
1942 "Pre increment SEH opcode must have a negative offset");
1946 case AArch64::SEH_SaveReg:
1948 MI->getOperand(1).getImm());
1951 case AArch64::SEH_SaveReg_X:
1952 assert(
MI->getOperand(1).getImm() < 0 &&
1953 "Pre increment SEH opcode must have a negative offset");
1955 -
MI->getOperand(1).getImm());
1958 case AArch64::SEH_SaveRegP:
1959 if (
MI->getOperand(1).getImm() == 30 &&
MI->getOperand(0).getImm() >= 19 &&
1960 MI->getOperand(0).getImm() <= 28) {
1961 assert((
MI->getOperand(0).getImm() - 19) % 2 == 0 &&
1962 "Register paired with LR must be odd");
1964 MI->getOperand(2).getImm());
1967 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
1968 "Non-consecutive registers not allowed for save_regp");
1970 MI->getOperand(2).getImm());
1973 case AArch64::SEH_SaveRegP_X:
1974 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
1975 "Non-consecutive registers not allowed for save_regp_x");
1976 assert(
MI->getOperand(2).getImm() < 0 &&
1977 "Pre increment SEH opcode must have a negative offset");
1979 -
MI->getOperand(2).getImm());
1982 case AArch64::SEH_SaveFReg:
1984 MI->getOperand(1).getImm());
1987 case AArch64::SEH_SaveFReg_X:
1988 assert(
MI->getOperand(1).getImm() < 0 &&
1989 "Pre increment SEH opcode must have a negative offset");
1991 -
MI->getOperand(1).getImm());
1994 case AArch64::SEH_SaveFRegP:
1995 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
1996 "Non-consecutive registers not allowed for save_regp");
1998 MI->getOperand(2).getImm());
2001 case AArch64::SEH_SaveFRegP_X:
2002 assert((
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1) &&
2003 "Non-consecutive registers not allowed for save_regp_x");
2004 assert(
MI->getOperand(2).getImm() < 0 &&
2005 "Pre increment SEH opcode must have a negative offset");
2007 -
MI->getOperand(2).getImm());
2010 case AArch64::SEH_SetFP:
2014 case AArch64::SEH_AddFP:
2018 case AArch64::SEH_Nop:
2022 case AArch64::SEH_PrologEnd:
2026 case AArch64::SEH_EpilogStart:
2030 case AArch64::SEH_EpilogEnd:
2034 case AArch64::SEH_PACSignLR:
2038 case AArch64::SEH_SaveAnyRegQP:
2039 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2040 "Non-consecutive registers not allowed for save_any_reg");
2041 assert(
MI->getOperand(2).getImm() >= 0 &&
2042 "SaveAnyRegQP SEH opcode offset must be non-negative");
2043 assert(
MI->getOperand(2).getImm() <= 1008 &&
2044 "SaveAnyRegQP SEH opcode offset must fit into 6 bits");
2046 MI->getOperand(2).getImm());
2049 case AArch64::SEH_SaveAnyRegQPX:
2050 assert(
MI->getOperand(1).getImm() -
MI->getOperand(0).getImm() == 1 &&
2051 "Non-consecutive registers not allowed for save_any_reg");
2052 assert(
MI->getOperand(2).getImm() < 0 &&
2053 "SaveAnyRegQPX SEH opcode offset must be negative");
2054 assert(
MI->getOperand(2).getImm() >= -1008 &&
2055 "SaveAnyRegQPX SEH opcode offset must fit into 6 bits");
2057 -
MI->getOperand(2).getImm());
2063 MCInstLowering.Lower(
MI, TmpInst);
2064 EmitToStreamer(*OutStreamer, TmpInst);
2080 MCInstLowering.lowerOperand(
2094 MCInstLowering.lowerOperand(
2104 .addReg(AArch64::X16)
2105 .addReg(AArch64::X16)
2116void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(
Module &M,
2151 .addReg(AArch64::SP)
2152 .addReg(AArch64::FP)
2153 .addReg(AArch64::LR)
2154 .addReg(AArch64::SP)
2159 .addReg(AArch64::FP)
2160 .addReg(AArch64::SP)
2165 for (
int I = 0;
I != 4; ++
I)
2167 .addReg(AArch64::SP)
2168 .addReg(AArch64::X1 + 2 *
I)
2169 .addReg(AArch64::X0 + 2 *
I)
2170 .addReg(AArch64::SP)
2174 for (
int I = 0;
I != 4; ++
I)
2176 .addReg(AArch64::SP)
2177 .addReg(AArch64::D1 + 2 *
I)
2178 .addReg(AArch64::D0 + 2 *
I)
2179 .addReg(AArch64::SP)
2193 MCInstLowering.lowerOperand(
2207 MCInstLowering.lowerOperand(
2217 .addReg(AArch64::X0)
2218 .addReg(AArch64::X16)
2223 .addReg(AArch64::X16)
2224 .addReg(AArch64::X0)
2229 for (
int I = 3;
I != -1; --
I)
2231 .addReg(AArch64::SP)
2232 .addReg(AArch64::D1 + 2 *
I)
2233 .addReg(AArch64::D0 + 2 *
I)
2234 .addReg(AArch64::SP)
2238 for (
int I = 3;
I != -1; --
I)
2240 .addReg(AArch64::SP)
2241 .addReg(AArch64::X1 + 2 *
I)
2242 .addReg(AArch64::X0 + 2 *
I)
2243 .addReg(AArch64::SP)
2248 .addReg(AArch64::SP)
2249 .addReg(AArch64::FP)
2250 .addReg(AArch64::LR)
2251 .addReg(AArch64::SP)
2262const MCExpr *AArch64AsmPrinter::lowerConstant(
const Constant *CV) {
2263 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
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")
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)
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()
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
This class is intended to be used as a driving class for all asm writers.
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
void 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.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
const Constant * getResolver() const
bool hasLocalLinkage() const
static const MCBinaryExpr * createLShr(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)
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)
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()
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
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
static MachineOperand CreateMCSymbol(MCSymbol *Sym, unsigned TargetFlags=0)
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
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.
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.
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()
@ 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,...