AArch64AsmPrinter.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557
  1. //===- AArch64AsmPrinter.cpp - AArch64 LLVM assembly writer ---------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains a printer that converts from our internal representation
  10. // of machine-dependent LLVM code to the AArch64 assembly language.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "AArch64.h"
  14. #include "AArch64MCInstLower.h"
  15. #include "AArch64MachineFunctionInfo.h"
  16. #include "AArch64RegisterInfo.h"
  17. #include "AArch64Subtarget.h"
  18. #include "AArch64TargetObjectFile.h"
  19. #include "MCTargetDesc/AArch64AddressingModes.h"
  20. #include "MCTargetDesc/AArch64InstPrinter.h"
  21. #include "MCTargetDesc/AArch64MCExpr.h"
  22. #include "MCTargetDesc/AArch64MCTargetDesc.h"
  23. #include "MCTargetDesc/AArch64TargetStreamer.h"
  24. #include "TargetInfo/AArch64TargetInfo.h"
  25. #include "Utils/AArch64BaseInfo.h"
  26. #include "llvm/ADT/SmallString.h"
  27. #include "llvm/ADT/SmallVector.h"
  28. #include "llvm/ADT/StringRef.h"
  29. #include "llvm/ADT/Triple.h"
  30. #include "llvm/ADT/Twine.h"
  31. #include "llvm/BinaryFormat/COFF.h"
  32. #include "llvm/BinaryFormat/ELF.h"
  33. #include "llvm/CodeGen/AsmPrinter.h"
  34. #include "llvm/CodeGen/FaultMaps.h"
  35. #include "llvm/CodeGen/MachineBasicBlock.h"
  36. #include "llvm/CodeGen/MachineFunction.h"
  37. #include "llvm/CodeGen/MachineInstr.h"
  38. #include "llvm/CodeGen/MachineJumpTableInfo.h"
  39. #include "llvm/CodeGen/MachineModuleInfoImpls.h"
  40. #include "llvm/CodeGen/MachineOperand.h"
  41. #include "llvm/CodeGen/StackMaps.h"
  42. #include "llvm/CodeGen/TargetRegisterInfo.h"
  43. #include "llvm/IR/DataLayout.h"
  44. #include "llvm/IR/DebugInfoMetadata.h"
  45. #include "llvm/MC/MCAsmInfo.h"
  46. #include "llvm/MC/MCContext.h"
  47. #include "llvm/MC/MCInst.h"
  48. #include "llvm/MC/MCInstBuilder.h"
  49. #include "llvm/MC/MCSectionELF.h"
  50. #include "llvm/MC/MCStreamer.h"
  51. #include "llvm/MC/MCSymbol.h"
  52. #include "llvm/MC/TargetRegistry.h"
  53. #include "llvm/Support/Casting.h"
  54. #include "llvm/Support/ErrorHandling.h"
  55. #include "llvm/Support/raw_ostream.h"
  56. #include "llvm/Target/TargetMachine.h"
  57. #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
  58. #include <algorithm>
  59. #include <cassert>
  60. #include <cstdint>
  61. #include <map>
  62. #include <memory>
  63. using namespace llvm;
  64. #define DEBUG_TYPE "asm-printer"
  65. namespace {
  66. class AArch64AsmPrinter : public AsmPrinter {
  67. AArch64MCInstLower MCInstLowering;
  68. StackMaps SM;
  69. FaultMaps FM;
  70. const AArch64Subtarget *STI;
  71. bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false;
  72. public:
  73. AArch64AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
  74. : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this),
  75. SM(*this), FM(*this) {}
  76. StringRef getPassName() const override { return "AArch64 Assembly Printer"; }
  77. /// Wrapper for MCInstLowering.lowerOperand() for the
  78. /// tblgen'erated pseudo lowering.
  79. bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
  80. return MCInstLowering.lowerOperand(MO, MCOp);
  81. }
  82. void emitStartOfAsmFile(Module &M) override;
  83. void emitJumpTableInfo() override;
  84. void emitFunctionEntryLabel() override;
  85. void LowerJumpTableDest(MCStreamer &OutStreamer, const MachineInstr &MI);
  86. void LowerMOPS(MCStreamer &OutStreamer, const MachineInstr &MI);
  87. void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
  88. const MachineInstr &MI);
  89. void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
  90. const MachineInstr &MI);
  91. void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
  92. const MachineInstr &MI);
  93. void LowerFAULTING_OP(const MachineInstr &MI);
  94. void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
  95. void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
  96. void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
  97. typedef std::tuple<unsigned, bool, uint32_t> HwasanMemaccessTuple;
  98. std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
  99. void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
  100. void emitHwasanMemaccessSymbols(Module &M);
  101. void emitSled(const MachineInstr &MI, SledKind Kind);
  102. /// tblgen'erated driver function for lowering simple MI->MC
  103. /// pseudo instructions.
  104. bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
  105. const MachineInstr *MI);
  106. void emitInstruction(const MachineInstr *MI) override;
  107. void emitFunctionHeaderComment() override;
  108. void getAnalysisUsage(AnalysisUsage &AU) const override {
  109. AsmPrinter::getAnalysisUsage(AU);
  110. AU.setPreservesAll();
  111. }
  112. bool runOnMachineFunction(MachineFunction &MF) override {
  113. AArch64FI = MF.getInfo<AArch64FunctionInfo>();
  114. STI = static_cast<const AArch64Subtarget*>(&MF.getSubtarget());
  115. SetupMachineFunction(MF);
  116. if (STI->isTargetCOFF()) {
  117. bool Internal = MF.getFunction().hasInternalLinkage();
  118. COFF::SymbolStorageClass Scl = Internal ? COFF::IMAGE_SYM_CLASS_STATIC
  119. : COFF::IMAGE_SYM_CLASS_EXTERNAL;
  120. int Type =
  121. COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT;
  122. OutStreamer->BeginCOFFSymbolDef(CurrentFnSym);
  123. OutStreamer->EmitCOFFSymbolStorageClass(Scl);
  124. OutStreamer->EmitCOFFSymbolType(Type);
  125. OutStreamer->EndCOFFSymbolDef();
  126. }
  127. // Emit the rest of the function body.
  128. emitFunctionBody();
  129. // Emit the XRay table for this function.
  130. emitXRayTable();
  131. // We didn't modify anything.
  132. return false;
  133. }
  134. private:
  135. void printOperand(const MachineInstr *MI, unsigned OpNum, raw_ostream &O);
  136. bool printAsmMRegister(const MachineOperand &MO, char Mode, raw_ostream &O);
  137. bool printAsmRegInClass(const MachineOperand &MO,
  138. const TargetRegisterClass *RC, unsigned AltName,
  139. raw_ostream &O);
  140. bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
  141. const char *ExtraCode, raw_ostream &O) override;
  142. bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
  143. const char *ExtraCode, raw_ostream &O) override;
  144. void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
  145. void emitFunctionBodyEnd() override;
  146. MCSymbol *GetCPISymbol(unsigned CPID) const override;
  147. void emitEndOfAsmFile(Module &M) override;
  148. AArch64FunctionInfo *AArch64FI = nullptr;
  149. /// Emit the LOHs contained in AArch64FI.
  150. void emitLOHs();
  151. /// Emit instruction to set float register to zero.
  152. void emitFMov0(const MachineInstr &MI);
  153. using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
  154. MInstToMCSymbol LOHInstToLabel;
  155. bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override {
  156. return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
  157. }
  158. };
  159. } // end anonymous namespace
  160. void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
  161. const Triple &TT = TM.getTargetTriple();
  162. if (TT.isOSBinFormatCOFF()) {
  163. // Emit an absolute @feat.00 symbol. This appears to be some kind of
  164. // compiler features bitfield read by link.exe.
  165. MCSymbol *S = MMI->getContext().getOrCreateSymbol(StringRef("@feat.00"));
  166. OutStreamer->BeginCOFFSymbolDef(S);
  167. OutStreamer->EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC);
  168. OutStreamer->EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL);
  169. OutStreamer->EndCOFFSymbolDef();
  170. int64_t Feat00Flags = 0;
  171. if (M.getModuleFlag("cfguard")) {
  172. Feat00Flags |= 0x800; // Object is CFG-aware.
  173. }
  174. if (M.getModuleFlag("ehcontguard")) {
  175. Feat00Flags |= 0x4000; // Object also has EHCont.
  176. }
  177. OutStreamer->emitSymbolAttribute(S, MCSA_Global);
  178. OutStreamer->emitAssignment(
  179. S, MCConstantExpr::create(Feat00Flags, MMI->getContext()));
  180. }
  181. if (!TT.isOSBinFormatELF())
  182. return;
  183. // Assemble feature flags that may require creation of a note section.
  184. unsigned Flags = 0;
  185. if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
  186. M.getModuleFlag("branch-target-enforcement")))
  187. if (BTE->getZExtValue())
  188. Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
  189. if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
  190. M.getModuleFlag("sign-return-address")))
  191. if (Sign->getZExtValue())
  192. Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
  193. if (Flags == 0)
  194. return;
  195. // Emit a .note.gnu.property section with the flags.
  196. if (auto *TS = static_cast<AArch64TargetStreamer *>(
  197. OutStreamer->getTargetStreamer()))
  198. TS->emitNoteSection(Flags);
  199. }
  200. void AArch64AsmPrinter::emitFunctionHeaderComment() {
  201. const AArch64FunctionInfo *FI = MF->getInfo<AArch64FunctionInfo>();
  202. Optional<std::string> OutlinerString = FI->getOutliningStyle();
  203. if (OutlinerString != None)
  204. OutStreamer->GetCommentOS() << ' ' << OutlinerString;
  205. }
  206. void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
  207. {
  208. const Function &F = MF->getFunction();
  209. if (F.hasFnAttribute("patchable-function-entry")) {
  210. unsigned Num;
  211. if (F.getFnAttribute("patchable-function-entry")
  212. .getValueAsString()
  213. .getAsInteger(10, Num))
  214. return;
  215. emitNops(Num);
  216. return;
  217. }
  218. emitSled(MI, SledKind::FUNCTION_ENTER);
  219. }
  220. void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) {
  221. emitSled(MI, SledKind::FUNCTION_EXIT);
  222. }
  223. void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) {
  224. emitSled(MI, SledKind::TAIL_CALL);
  225. }
  226. void AArch64AsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
  227. static const int8_t NoopsInSledCount = 7;
  228. // We want to emit the following pattern:
  229. //
  230. // .Lxray_sled_N:
  231. // ALIGN
  232. // B #32
  233. // ; 7 NOP instructions (28 bytes)
  234. // .tmpN
  235. //
  236. // We need the 28 bytes (7 instructions) because at runtime, we'd be patching
  237. // over the full 32 bytes (8 instructions) with the following pattern:
  238. //
  239. // STP X0, X30, [SP, #-16]! ; push X0 and the link register to the stack
  240. // LDR W0, #12 ; W0 := function ID
  241. // LDR X16,#12 ; X16 := addr of __xray_FunctionEntry or __xray_FunctionExit
  242. // BLR X16 ; call the tracing trampoline
  243. // ;DATA: 32 bits of function ID
  244. // ;DATA: lower 32 bits of the address of the trampoline
  245. // ;DATA: higher 32 bits of the address of the trampoline
  246. // LDP X0, X30, [SP], #16 ; pop X0 and the link register from the stack
  247. //
  248. OutStreamer->emitCodeAlignment(4, &getSubtargetInfo());
  249. auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
  250. OutStreamer->emitLabel(CurSled);
  251. auto Target = OutContext.createTempSymbol();
  252. // Emit "B #32" instruction, which jumps over the next 28 bytes.
  253. // The operand has to be the number of 4-byte instructions to jump over,
  254. // including the current instruction.
  255. EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
  256. for (int8_t I = 0; I < NoopsInSledCount; I++)
  257. EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
  258. OutStreamer->emitLabel(Target);
  259. recordSled(CurSled, MI, Kind, 2);
  260. }
  261. void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
  262. Register Reg = MI.getOperand(0).getReg();
  263. bool IsShort =
  264. MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES;
  265. uint32_t AccessInfo = MI.getOperand(1).getImm();
  266. MCSymbol *&Sym =
  267. HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, IsShort, AccessInfo)];
  268. if (!Sym) {
  269. // FIXME: Make this work on non-ELF.
  270. if (!TM.getTargetTriple().isOSBinFormatELF())
  271. report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
  272. std::string SymName = "__hwasan_check_x" + utostr(Reg - AArch64::X0) + "_" +
  273. utostr(AccessInfo);
  274. if (IsShort)
  275. SymName += "_short_v2";
  276. Sym = OutContext.getOrCreateSymbol(SymName);
  277. }
  278. EmitToStreamer(*OutStreamer,
  279. MCInstBuilder(AArch64::BL)
  280. .addExpr(MCSymbolRefExpr::create(Sym, OutContext)));
  281. }
  282. void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
  283. if (HwasanMemaccessSymbols.empty())
  284. return;
  285. const Triple &TT = TM.getTargetTriple();
  286. assert(TT.isOSBinFormatELF());
  287. std::unique_ptr<MCSubtargetInfo> STI(
  288. TM.getTarget().createMCSubtargetInfo(TT.str(), "", ""));
  289. assert(STI && "Unable to create subtarget info");
  290. MCSymbol *HwasanTagMismatchV1Sym =
  291. OutContext.getOrCreateSymbol("__hwasan_tag_mismatch");
  292. MCSymbol *HwasanTagMismatchV2Sym =
  293. OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
  294. const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
  295. MCSymbolRefExpr::create(HwasanTagMismatchV1Sym, OutContext);
  296. const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
  297. MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
  298. for (auto &P : HwasanMemaccessSymbols) {
  299. unsigned Reg = std::get<0>(P.first);
  300. bool IsShort = std::get<1>(P.first);
  301. uint32_t AccessInfo = std::get<2>(P.first);
  302. const MCSymbolRefExpr *HwasanTagMismatchRef =
  303. IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
  304. MCSymbol *Sym = P.second;
  305. bool HasMatchAllTag =
  306. (AccessInfo >> HWASanAccessInfo::HasMatchAllShift) & 1;
  307. uint8_t MatchAllTag =
  308. (AccessInfo >> HWASanAccessInfo::MatchAllShift) & 0xff;
  309. unsigned Size =
  310. 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
  311. bool CompileKernel =
  312. (AccessInfo >> HWASanAccessInfo::CompileKernelShift) & 1;
  313. OutStreamer->SwitchSection(OutContext.getELFSection(
  314. ".text.hot", ELF::SHT_PROGBITS,
  315. ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
  316. Sym->getName(), /*IsComdat=*/true));
  317. OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
  318. OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
  319. OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
  320. OutStreamer->emitLabel(Sym);
  321. OutStreamer->emitInstruction(MCInstBuilder(AArch64::SBFMXri)
  322. .addReg(AArch64::X16)
  323. .addReg(Reg)
  324. .addImm(4)
  325. .addImm(55),
  326. *STI);
  327. OutStreamer->emitInstruction(
  328. MCInstBuilder(AArch64::LDRBBroX)
  329. .addReg(AArch64::W16)
  330. .addReg(IsShort ? AArch64::X20 : AArch64::X9)
  331. .addReg(AArch64::X16)
  332. .addImm(0)
  333. .addImm(0),
  334. *STI);
  335. OutStreamer->emitInstruction(
  336. MCInstBuilder(AArch64::SUBSXrs)
  337. .addReg(AArch64::XZR)
  338. .addReg(AArch64::X16)
  339. .addReg(Reg)
  340. .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSR, 56)),
  341. *STI);
  342. MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
  343. OutStreamer->emitInstruction(
  344. MCInstBuilder(AArch64::Bcc)
  345. .addImm(AArch64CC::NE)
  346. .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym,
  347. OutContext)),
  348. *STI);
  349. MCSymbol *ReturnSym = OutContext.createTempSymbol();
  350. OutStreamer->emitLabel(ReturnSym);
  351. OutStreamer->emitInstruction(
  352. MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
  353. OutStreamer->emitLabel(HandleMismatchOrPartialSym);
  354. if (HasMatchAllTag) {
  355. OutStreamer->emitInstruction(MCInstBuilder(AArch64::UBFMXri)
  356. .addReg(AArch64::X16)
  357. .addReg(Reg)
  358. .addImm(56)
  359. .addImm(63),
  360. *STI);
  361. OutStreamer->emitInstruction(MCInstBuilder(AArch64::SUBSXri)
  362. .addReg(AArch64::XZR)
  363. .addReg(AArch64::X16)
  364. .addImm(MatchAllTag)
  365. .addImm(0),
  366. *STI);
  367. OutStreamer->emitInstruction(
  368. MCInstBuilder(AArch64::Bcc)
  369. .addImm(AArch64CC::EQ)
  370. .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
  371. *STI);
  372. }
  373. if (IsShort) {
  374. OutStreamer->emitInstruction(MCInstBuilder(AArch64::SUBSWri)
  375. .addReg(AArch64::WZR)
  376. .addReg(AArch64::W16)
  377. .addImm(15)
  378. .addImm(0),
  379. *STI);
  380. MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
  381. OutStreamer->emitInstruction(
  382. MCInstBuilder(AArch64::Bcc)
  383. .addImm(AArch64CC::HI)
  384. .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
  385. *STI);
  386. OutStreamer->emitInstruction(
  387. MCInstBuilder(AArch64::ANDXri)
  388. .addReg(AArch64::X17)
  389. .addReg(Reg)
  390. .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)),
  391. *STI);
  392. if (Size != 1)
  393. OutStreamer->emitInstruction(MCInstBuilder(AArch64::ADDXri)
  394. .addReg(AArch64::X17)
  395. .addReg(AArch64::X17)
  396. .addImm(Size - 1)
  397. .addImm(0),
  398. *STI);
  399. OutStreamer->emitInstruction(MCInstBuilder(AArch64::SUBSWrs)
  400. .addReg(AArch64::WZR)
  401. .addReg(AArch64::W16)
  402. .addReg(AArch64::W17)
  403. .addImm(0),
  404. *STI);
  405. OutStreamer->emitInstruction(
  406. MCInstBuilder(AArch64::Bcc)
  407. .addImm(AArch64CC::LS)
  408. .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
  409. *STI);
  410. OutStreamer->emitInstruction(
  411. MCInstBuilder(AArch64::ORRXri)
  412. .addReg(AArch64::X16)
  413. .addReg(Reg)
  414. .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)),
  415. *STI);
  416. OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDRBBui)
  417. .addReg(AArch64::W16)
  418. .addReg(AArch64::X16)
  419. .addImm(0),
  420. *STI);
  421. OutStreamer->emitInstruction(
  422. MCInstBuilder(AArch64::SUBSXrs)
  423. .addReg(AArch64::XZR)
  424. .addReg(AArch64::X16)
  425. .addReg(Reg)
  426. .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSR, 56)),
  427. *STI);
  428. OutStreamer->emitInstruction(
  429. MCInstBuilder(AArch64::Bcc)
  430. .addImm(AArch64CC::EQ)
  431. .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
  432. *STI);
  433. OutStreamer->emitLabel(HandleMismatchSym);
  434. }
  435. OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
  436. .addReg(AArch64::SP)
  437. .addReg(AArch64::X0)
  438. .addReg(AArch64::X1)
  439. .addReg(AArch64::SP)
  440. .addImm(-32),
  441. *STI);
  442. OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXi)
  443. .addReg(AArch64::FP)
  444. .addReg(AArch64::LR)
  445. .addReg(AArch64::SP)
  446. .addImm(29),
  447. *STI);
  448. if (Reg != AArch64::X0)
  449. OutStreamer->emitInstruction(MCInstBuilder(AArch64::ORRXrs)
  450. .addReg(AArch64::X0)
  451. .addReg(AArch64::XZR)
  452. .addReg(Reg)
  453. .addImm(0),
  454. *STI);
  455. OutStreamer->emitInstruction(
  456. MCInstBuilder(AArch64::MOVZXi)
  457. .addReg(AArch64::X1)
  458. .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask)
  459. .addImm(0),
  460. *STI);
  461. if (CompileKernel) {
  462. // The Linux kernel's dynamic loader doesn't support GOT relative
  463. // relocations, but it doesn't support late binding either, so just call
  464. // the function directly.
  465. OutStreamer->emitInstruction(
  466. MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef), *STI);
  467. } else {
  468. // Intentionally load the GOT entry and branch to it, rather than possibly
  469. // late binding the function, which may clobber the registers before we
  470. // have a chance to save them.
  471. OutStreamer->emitInstruction(
  472. MCInstBuilder(AArch64::ADRP)
  473. .addReg(AArch64::X16)
  474. .addExpr(AArch64MCExpr::create(
  475. HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
  476. OutContext)),
  477. *STI);
  478. OutStreamer->emitInstruction(
  479. MCInstBuilder(AArch64::LDRXui)
  480. .addReg(AArch64::X16)
  481. .addReg(AArch64::X16)
  482. .addExpr(AArch64MCExpr::create(
  483. HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
  484. OutContext)),
  485. *STI);
  486. OutStreamer->emitInstruction(
  487. MCInstBuilder(AArch64::BR).addReg(AArch64::X16), *STI);
  488. }
  489. }
  490. }
  491. void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
  492. emitHwasanMemaccessSymbols(M);
  493. const Triple &TT = TM.getTargetTriple();
  494. if (TT.isOSBinFormatMachO()) {
  495. // Funny Darwin hack: This flag tells the linker that no global symbols
  496. // contain code that falls through to other global symbols (e.g. the obvious
  497. // implementation of multiple entry points). If this doesn't occur, the
  498. // linker can safely perform dead code stripping. Since LLVM never
  499. // generates code that does this, it is always safe to set.
  500. OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
  501. }
  502. // Emit stack and fault map information.
  503. emitStackMaps(SM);
  504. FM.serializeToFaultMapSection();
  505. }
  506. void AArch64AsmPrinter::emitLOHs() {
  507. SmallVector<MCSymbol *, 3> MCArgs;
  508. for (const auto &D : AArch64FI->getLOHContainer()) {
  509. for (const MachineInstr *MI : D.getArgs()) {
  510. MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(MI);
  511. assert(LabelIt != LOHInstToLabel.end() &&
  512. "Label hasn't been inserted for LOH related instruction");
  513. MCArgs.push_back(LabelIt->second);
  514. }
  515. OutStreamer->emitLOHDirective(D.getKind(), MCArgs);
  516. MCArgs.clear();
  517. }
  518. }
  519. void AArch64AsmPrinter::emitFunctionBodyEnd() {
  520. if (!AArch64FI->getLOHRelated().empty())
  521. emitLOHs();
  522. }
  523. /// GetCPISymbol - Return the symbol for the specified constant pool entry.
  524. MCSymbol *AArch64AsmPrinter::GetCPISymbol(unsigned CPID) const {
  525. // Darwin uses a linker-private symbol name for constant-pools (to
  526. // avoid addends on the relocation?), ELF has no such concept and
  527. // uses a normal private symbol.
  528. if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
  529. return OutContext.getOrCreateSymbol(
  530. Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) + "CPI" +
  531. Twine(getFunctionNumber()) + "_" + Twine(CPID));
  532. return AsmPrinter::GetCPISymbol(CPID);
  533. }
  534. void AArch64AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNum,
  535. raw_ostream &O) {
  536. const MachineOperand &MO = MI->getOperand(OpNum);
  537. switch (MO.getType()) {
  538. default:
  539. llvm_unreachable("<unknown operand type>");
  540. case MachineOperand::MO_Register: {
  541. Register Reg = MO.getReg();
  542. assert(Register::isPhysicalRegister(Reg));
  543. assert(!MO.getSubReg() && "Subregs should be eliminated!");
  544. O << AArch64InstPrinter::getRegisterName(Reg);
  545. break;
  546. }
  547. case MachineOperand::MO_Immediate: {
  548. O << MO.getImm();
  549. break;
  550. }
  551. case MachineOperand::MO_GlobalAddress: {
  552. PrintSymbolOperand(MO, O);
  553. break;
  554. }
  555. case MachineOperand::MO_BlockAddress: {
  556. MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
  557. Sym->print(O, MAI);
  558. break;
  559. }
  560. }
  561. }
  562. bool AArch64AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode,
  563. raw_ostream &O) {
  564. Register Reg = MO.getReg();
  565. switch (Mode) {
  566. default:
  567. return true; // Unknown mode.
  568. case 'w':
  569. Reg = getWRegFromXReg(Reg);
  570. break;
  571. case 'x':
  572. Reg = getXRegFromWReg(Reg);
  573. break;
  574. case 't':
  575. Reg = getXRegFromXRegTuple(Reg);
  576. break;
  577. }
  578. O << AArch64InstPrinter::getRegisterName(Reg);
  579. return false;
  580. }
  581. // Prints the register in MO using class RC using the offset in the
  582. // new register class. This should not be used for cross class
  583. // printing.
  584. bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO,
  585. const TargetRegisterClass *RC,
  586. unsigned AltName, raw_ostream &O) {
  587. assert(MO.isReg() && "Should only get here with a register!");
  588. const TargetRegisterInfo *RI = STI->getRegisterInfo();
  589. Register Reg = MO.getReg();
  590. unsigned RegToPrint = RC->getRegister(RI->getEncodingValue(Reg));
  591. if (!RI->regsOverlap(RegToPrint, Reg))
  592. return true;
  593. O << AArch64InstPrinter::getRegisterName(RegToPrint, AltName);
  594. return false;
  595. }
  596. bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
  597. const char *ExtraCode, raw_ostream &O) {
  598. const MachineOperand &MO = MI->getOperand(OpNum);
  599. // First try the generic code, which knows about modifiers like 'c' and 'n'.
  600. if (!AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O))
  601. return false;
  602. // Does this asm operand have a single letter operand modifier?
  603. if (ExtraCode && ExtraCode[0]) {
  604. if (ExtraCode[1] != 0)
  605. return true; // Unknown modifier.
  606. switch (ExtraCode[0]) {
  607. default:
  608. return true; // Unknown modifier.
  609. case 'w': // Print W register
  610. case 'x': // Print X register
  611. if (MO.isReg())
  612. return printAsmMRegister(MO, ExtraCode[0], O);
  613. if (MO.isImm() && MO.getImm() == 0) {
  614. unsigned Reg = ExtraCode[0] == 'w' ? AArch64::WZR : AArch64::XZR;
  615. O << AArch64InstPrinter::getRegisterName(Reg);
  616. return false;
  617. }
  618. printOperand(MI, OpNum, O);
  619. return false;
  620. case 'b': // Print B register.
  621. case 'h': // Print H register.
  622. case 's': // Print S register.
  623. case 'd': // Print D register.
  624. case 'q': // Print Q register.
  625. case 'z': // Print Z register.
  626. if (MO.isReg()) {
  627. const TargetRegisterClass *RC;
  628. switch (ExtraCode[0]) {
  629. case 'b':
  630. RC = &AArch64::FPR8RegClass;
  631. break;
  632. case 'h':
  633. RC = &AArch64::FPR16RegClass;
  634. break;
  635. case 's':
  636. RC = &AArch64::FPR32RegClass;
  637. break;
  638. case 'd':
  639. RC = &AArch64::FPR64RegClass;
  640. break;
  641. case 'q':
  642. RC = &AArch64::FPR128RegClass;
  643. break;
  644. case 'z':
  645. RC = &AArch64::ZPRRegClass;
  646. break;
  647. default:
  648. return true;
  649. }
  650. return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
  651. }
  652. printOperand(MI, OpNum, O);
  653. return false;
  654. }
  655. }
  656. // According to ARM, we should emit x and v registers unless we have a
  657. // modifier.
  658. if (MO.isReg()) {
  659. Register Reg = MO.getReg();
  660. // If this is a w or x register, print an x register.
  661. if (AArch64::GPR32allRegClass.contains(Reg) ||
  662. AArch64::GPR64allRegClass.contains(Reg))
  663. return printAsmMRegister(MO, 'x', O);
  664. // If this is an x register tuple, print an x register.
  665. if (AArch64::GPR64x8ClassRegClass.contains(Reg))
  666. return printAsmMRegister(MO, 't', O);
  667. unsigned AltName = AArch64::NoRegAltName;
  668. const TargetRegisterClass *RegClass;
  669. if (AArch64::ZPRRegClass.contains(Reg)) {
  670. RegClass = &AArch64::ZPRRegClass;
  671. } else if (AArch64::PPRRegClass.contains(Reg)) {
  672. RegClass = &AArch64::PPRRegClass;
  673. } else {
  674. RegClass = &AArch64::FPR128RegClass;
  675. AltName = AArch64::vreg;
  676. }
  677. // If this is a b, h, s, d, or q register, print it as a v register.
  678. return printAsmRegInClass(MO, RegClass, AltName, O);
  679. }
  680. printOperand(MI, OpNum, O);
  681. return false;
  682. }
  683. bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
  684. unsigned OpNum,
  685. const char *ExtraCode,
  686. raw_ostream &O) {
  687. if (ExtraCode && ExtraCode[0] && ExtraCode[0] != 'a')
  688. return true; // Unknown modifier.
  689. const MachineOperand &MO = MI->getOperand(OpNum);
  690. assert(MO.isReg() && "unexpected inline asm memory operand");
  691. O << "[" << AArch64InstPrinter::getRegisterName(MO.getReg()) << "]";
  692. return false;
  693. }
  694. void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
  695. raw_ostream &OS) {
  696. unsigned NOps = MI->getNumOperands();
  697. assert(NOps == 4);
  698. OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
  699. // cast away const; DIetc do not take const operands for some reason.
  700. OS << MI->getDebugVariable()->getName();
  701. OS << " <- ";
  702. // Frame address. Currently handles register +- offset only.
  703. assert(MI->isIndirectDebugValue());
  704. OS << '[';
  705. for (unsigned I = 0, E = std::distance(MI->debug_operands().begin(),
  706. MI->debug_operands().end());
  707. I < E; ++I) {
  708. if (I != 0)
  709. OS << ", ";
  710. printOperand(MI, I, OS);
  711. }
  712. OS << ']';
  713. OS << "+";
  714. printOperand(MI, NOps - 2, OS);
  715. }
  716. void AArch64AsmPrinter::emitJumpTableInfo() {
  717. const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
  718. if (!MJTI) return;
  719. const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
  720. if (JT.empty()) return;
  721. const TargetLoweringObjectFile &TLOF = getObjFileLowering();
  722. MCSection *ReadOnlySec = TLOF.getSectionForJumpTable(MF->getFunction(), TM);
  723. OutStreamer->SwitchSection(ReadOnlySec);
  724. auto AFI = MF->getInfo<AArch64FunctionInfo>();
  725. for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
  726. const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
  727. // If this jump table was deleted, ignore it.
  728. if (JTBBs.empty()) continue;
  729. unsigned Size = AFI->getJumpTableEntrySize(JTI);
  730. emitAlignment(Align(Size));
  731. OutStreamer->emitLabel(GetJTISymbol(JTI));
  732. const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
  733. const MCExpr *Base = MCSymbolRefExpr::create(BaseSym, OutContext);
  734. for (auto *JTBB : JTBBs) {
  735. const MCExpr *Value =
  736. MCSymbolRefExpr::create(JTBB->getSymbol(), OutContext);
  737. // Each entry is:
  738. // .byte/.hword (LBB - Lbase)>>2
  739. // or plain:
  740. // .word LBB - Lbase
  741. Value = MCBinaryExpr::createSub(Value, Base, OutContext);
  742. if (Size != 4)
  743. Value = MCBinaryExpr::createLShr(
  744. Value, MCConstantExpr::create(2, OutContext), OutContext);
  745. OutStreamer->emitValue(Value, Size);
  746. }
  747. }
  748. }
  749. void AArch64AsmPrinter::emitFunctionEntryLabel() {
  750. if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall ||
  751. MF->getFunction().getCallingConv() ==
  752. CallingConv::AArch64_SVE_VectorCall ||
  753. STI->getRegisterInfo()->hasSVEArgsOrReturn(MF)) {
  754. auto *TS =
  755. static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
  756. TS->emitDirectiveVariantPCS(CurrentFnSym);
  757. }
  758. return AsmPrinter::emitFunctionEntryLabel();
  759. }
  760. /// Small jump tables contain an unsigned byte or half, representing the offset
  761. /// from the lowest-addressed possible destination to the desired basic
  762. /// block. Since all instructions are 4-byte aligned, this is further compressed
  763. /// by counting in instructions rather than bytes (i.e. divided by 4). So, to
  764. /// materialize the correct destination we need:
  765. ///
  766. /// adr xDest, .LBB0_0
  767. /// ldrb wScratch, [xTable, xEntry] (with "lsl #1" for ldrh).
  768. /// add xDest, xDest, xScratch (with "lsl #2" for smaller entries)
  769. void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
  770. const llvm::MachineInstr &MI) {
  771. Register DestReg = MI.getOperand(0).getReg();
  772. Register ScratchReg = MI.getOperand(1).getReg();
  773. Register ScratchRegW =
  774. STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
  775. Register TableReg = MI.getOperand(2).getReg();
  776. Register EntryReg = MI.getOperand(3).getReg();
  777. int JTIdx = MI.getOperand(4).getIndex();
  778. int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
  779. // This has to be first because the compression pass based its reachability
  780. // calculations on the start of the JumpTableDest instruction.
  781. auto Label =
  782. MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
  783. // If we don't already have a symbol to use as the base, use the ADR
  784. // instruction itself.
  785. if (!Label) {
  786. Label = MF->getContext().createTempSymbol();
  787. AArch64FI->setJumpTableEntryInfo(JTIdx, Size, Label);
  788. OutStreamer.emitLabel(Label);
  789. }
  790. auto LabelExpr = MCSymbolRefExpr::create(Label, MF->getContext());
  791. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
  792. .addReg(DestReg)
  793. .addExpr(LabelExpr));
  794. // Load the number of instruction-steps to offset from the label.
  795. unsigned LdrOpcode;
  796. switch (Size) {
  797. case 1: LdrOpcode = AArch64::LDRBBroX; break;
  798. case 2: LdrOpcode = AArch64::LDRHHroX; break;
  799. case 4: LdrOpcode = AArch64::LDRSWroX; break;
  800. default:
  801. llvm_unreachable("Unknown jump table size");
  802. }
  803. EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
  804. .addReg(Size == 4 ? ScratchReg : ScratchRegW)
  805. .addReg(TableReg)
  806. .addReg(EntryReg)
  807. .addImm(0)
  808. .addImm(Size == 1 ? 0 : 1));
  809. // Add to the already materialized base label address, multiplying by 4 if
  810. // compressed.
  811. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
  812. .addReg(DestReg)
  813. .addReg(DestReg)
  814. .addReg(ScratchReg)
  815. .addImm(Size == 4 ? 0 : 2));
  816. }
  817. void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer,
  818. const llvm::MachineInstr &MI) {
  819. unsigned Opcode = MI.getOpcode();
  820. assert(STI->hasMOPS());
  821. assert(STI->hasMTE() || Opcode != AArch64::MOPSMemorySetTaggingPseudo);
  822. const auto Ops = [Opcode]() -> std::array<unsigned, 3> {
  823. if (Opcode == AArch64::MOPSMemoryCopyPseudo)
  824. return {AArch64::CPYFP, AArch64::CPYFM, AArch64::CPYFE};
  825. if (Opcode == AArch64::MOPSMemoryMovePseudo)
  826. return {AArch64::CPYP, AArch64::CPYM, AArch64::CPYE};
  827. if (Opcode == AArch64::MOPSMemorySetPseudo)
  828. return {AArch64::SETP, AArch64::SETM, AArch64::SETE};
  829. if (Opcode == AArch64::MOPSMemorySetTaggingPseudo)
  830. return {AArch64::SETGP, AArch64::SETGM, AArch64::MOPSSETGE};
  831. llvm_unreachable("Unhandled memory operation pseudo");
  832. }();
  833. const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
  834. Opcode == AArch64::MOPSMemorySetTaggingPseudo;
  835. for (auto Op : Ops) {
  836. int i = 0;
  837. auto MCIB = MCInstBuilder(Op);
  838. // Destination registers
  839. MCIB.addReg(MI.getOperand(i++).getReg());
  840. MCIB.addReg(MI.getOperand(i++).getReg());
  841. if (!IsSet)
  842. MCIB.addReg(MI.getOperand(i++).getReg());
  843. // Input registers
  844. MCIB.addReg(MI.getOperand(i++).getReg());
  845. MCIB.addReg(MI.getOperand(i++).getReg());
  846. MCIB.addReg(MI.getOperand(i++).getReg());
  847. EmitToStreamer(OutStreamer, MCIB);
  848. }
  849. }
  850. void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
  851. const MachineInstr &MI) {
  852. unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
  853. auto &Ctx = OutStreamer.getContext();
  854. MCSymbol *MILabel = Ctx.createTempSymbol();
  855. OutStreamer.emitLabel(MILabel);
  856. SM.recordStackMap(*MILabel, MI);
  857. assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
  858. // Scan ahead to trim the shadow.
  859. const MachineBasicBlock &MBB = *MI.getParent();
  860. MachineBasicBlock::const_iterator MII(MI);
  861. ++MII;
  862. while (NumNOPBytes > 0) {
  863. if (MII == MBB.end() || MII->isCall() ||
  864. MII->getOpcode() == AArch64::DBG_VALUE ||
  865. MII->getOpcode() == TargetOpcode::PATCHPOINT ||
  866. MII->getOpcode() == TargetOpcode::STACKMAP)
  867. break;
  868. ++MII;
  869. NumNOPBytes -= 4;
  870. }
  871. // Emit nops.
  872. for (unsigned i = 0; i < NumNOPBytes; i += 4)
  873. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
  874. }
  875. // Lower a patchpoint of the form:
  876. // [<def>], <id>, <numBytes>, <target>, <numArgs>
  877. void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
  878. const MachineInstr &MI) {
  879. auto &Ctx = OutStreamer.getContext();
  880. MCSymbol *MILabel = Ctx.createTempSymbol();
  881. OutStreamer.emitLabel(MILabel);
  882. SM.recordPatchPoint(*MILabel, MI);
  883. PatchPointOpers Opers(&MI);
  884. int64_t CallTarget = Opers.getCallTarget().getImm();
  885. unsigned EncodedBytes = 0;
  886. if (CallTarget) {
  887. assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
  888. "High 16 bits of call target should be zero.");
  889. Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
  890. EncodedBytes = 16;
  891. // Materialize the jump address:
  892. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVZXi)
  893. .addReg(ScratchReg)
  894. .addImm((CallTarget >> 32) & 0xFFFF)
  895. .addImm(32));
  896. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
  897. .addReg(ScratchReg)
  898. .addReg(ScratchReg)
  899. .addImm((CallTarget >> 16) & 0xFFFF)
  900. .addImm(16));
  901. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
  902. .addReg(ScratchReg)
  903. .addReg(ScratchReg)
  904. .addImm(CallTarget & 0xFFFF)
  905. .addImm(0));
  906. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
  907. }
  908. // Emit padding.
  909. unsigned NumBytes = Opers.getNumPatchBytes();
  910. assert(NumBytes >= EncodedBytes &&
  911. "Patchpoint can't request size less than the length of a call.");
  912. assert((NumBytes - EncodedBytes) % 4 == 0 &&
  913. "Invalid number of NOP bytes requested!");
  914. for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
  915. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
  916. }
  917. void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
  918. const MachineInstr &MI) {
  919. StatepointOpers SOpers(&MI);
  920. if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
  921. assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
  922. for (unsigned i = 0; i < PatchBytes; i += 4)
  923. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
  924. } else {
  925. // Lower call target and choose correct opcode
  926. const MachineOperand &CallTarget = SOpers.getCallTarget();
  927. MCOperand CallTargetMCOp;
  928. unsigned CallOpcode;
  929. switch (CallTarget.getType()) {
  930. case MachineOperand::MO_GlobalAddress:
  931. case MachineOperand::MO_ExternalSymbol:
  932. MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
  933. CallOpcode = AArch64::BL;
  934. break;
  935. case MachineOperand::MO_Immediate:
  936. CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
  937. CallOpcode = AArch64::BL;
  938. break;
  939. case MachineOperand::MO_Register:
  940. CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
  941. CallOpcode = AArch64::BLR;
  942. break;
  943. default:
  944. llvm_unreachable("Unsupported operand type in statepoint call target");
  945. break;
  946. }
  947. EmitToStreamer(OutStreamer,
  948. MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp));
  949. }
  950. auto &Ctx = OutStreamer.getContext();
  951. MCSymbol *MILabel = Ctx.createTempSymbol();
  952. OutStreamer.emitLabel(MILabel);
  953. SM.recordStatepoint(*MILabel, MI);
  954. }
  955. void AArch64AsmPrinter::LowerFAULTING_OP(const MachineInstr &FaultingMI) {
  956. // FAULTING_LOAD_OP <def>, <faltinf type>, <MBB handler>,
  957. // <opcode>, <operands>
  958. Register DefRegister = FaultingMI.getOperand(0).getReg();
  959. FaultMaps::FaultKind FK =
  960. static_cast<FaultMaps::FaultKind>(FaultingMI.getOperand(1).getImm());
  961. MCSymbol *HandlerLabel = FaultingMI.getOperand(2).getMBB()->getSymbol();
  962. unsigned Opcode = FaultingMI.getOperand(3).getImm();
  963. unsigned OperandsBeginIdx = 4;
  964. auto &Ctx = OutStreamer->getContext();
  965. MCSymbol *FaultingLabel = Ctx.createTempSymbol();
  966. OutStreamer->emitLabel(FaultingLabel);
  967. assert(FK < FaultMaps::FaultKindMax && "Invalid Faulting Kind!");
  968. FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
  969. MCInst MI;
  970. MI.setOpcode(Opcode);
  971. if (DefRegister != (Register)0)
  972. MI.addOperand(MCOperand::createReg(DefRegister));
  973. for (auto I = FaultingMI.operands_begin() + OperandsBeginIdx,
  974. E = FaultingMI.operands_end();
  975. I != E; ++I) {
  976. MCOperand Dest;
  977. lowerOperand(*I, Dest);
  978. MI.addOperand(Dest);
  979. }
  980. OutStreamer->AddComment("on-fault: " + HandlerLabel->getName());
  981. OutStreamer->emitInstruction(MI, getSubtargetInfo());
  982. }
  983. void AArch64AsmPrinter::emitFMov0(const MachineInstr &MI) {
  984. Register DestReg = MI.getOperand(0).getReg();
  985. if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) {
  986. // Convert H/S register to corresponding D register
  987. if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
  988. DestReg = AArch64::D0 + (DestReg - AArch64::H0);
  989. else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
  990. DestReg = AArch64::D0 + (DestReg - AArch64::S0);
  991. else
  992. assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
  993. MCInst MOVI;
  994. MOVI.setOpcode(AArch64::MOVID);
  995. MOVI.addOperand(MCOperand::createReg(DestReg));
  996. MOVI.addOperand(MCOperand::createImm(0));
  997. EmitToStreamer(*OutStreamer, MOVI);
  998. } else {
  999. MCInst FMov;
  1000. switch (MI.getOpcode()) {
  1001. default: llvm_unreachable("Unexpected opcode");
  1002. case AArch64::FMOVH0:
  1003. FMov.setOpcode(AArch64::FMOVWHr);
  1004. FMov.addOperand(MCOperand::createReg(DestReg));
  1005. FMov.addOperand(MCOperand::createReg(AArch64::WZR));
  1006. break;
  1007. case AArch64::FMOVS0:
  1008. FMov.setOpcode(AArch64::FMOVWSr);
  1009. FMov.addOperand(MCOperand::createReg(DestReg));
  1010. FMov.addOperand(MCOperand::createReg(AArch64::WZR));
  1011. break;
  1012. case AArch64::FMOVD0:
  1013. FMov.setOpcode(AArch64::FMOVXDr);
  1014. FMov.addOperand(MCOperand::createReg(DestReg));
  1015. FMov.addOperand(MCOperand::createReg(AArch64::XZR));
  1016. break;
  1017. }
  1018. EmitToStreamer(*OutStreamer, FMov);
  1019. }
  1020. }
  1021. // Simple pseudo-instructions have their lowering (with expansion to real
  1022. // instructions) auto-generated.
  1023. #include "AArch64GenMCPseudoLowering.inc"
  1024. void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
  1025. // Do any auto-generated pseudo lowerings.
  1026. if (emitPseudoExpansionLowering(*OutStreamer, MI))
  1027. return;
  1028. if (MI->getOpcode() == AArch64::ADRP) {
  1029. for (auto &Opd : MI->operands()) {
  1030. if (Opd.isSymbol() && StringRef(Opd.getSymbolName()) ==
  1031. "swift_async_extendedFramePointerFlags") {
  1032. ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = true;
  1033. }
  1034. }
  1035. }
  1036. if (AArch64FI->getLOHRelated().count(MI)) {
  1037. // Generate a label for LOH related instruction
  1038. MCSymbol *LOHLabel = createTempSymbol("loh");
  1039. // Associate the instruction with the label
  1040. LOHInstToLabel[MI] = LOHLabel;
  1041. OutStreamer->emitLabel(LOHLabel);
  1042. }
  1043. AArch64TargetStreamer *TS =
  1044. static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
  1045. // Do any manual lowerings.
  1046. switch (MI->getOpcode()) {
  1047. default:
  1048. break;
  1049. case AArch64::HINT: {
  1050. // CurrentPatchableFunctionEntrySym can be CurrentFnBegin only for
  1051. // -fpatchable-function-entry=N,0. The entry MBB is guaranteed to be
  1052. // non-empty. If MI is the initial BTI, place the
  1053. // __patchable_function_entries label after BTI.
  1054. if (CurrentPatchableFunctionEntrySym &&
  1055. CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
  1056. MI == &MF->front().front()) {
  1057. int64_t Imm = MI->getOperand(0).getImm();
  1058. if ((Imm & 32) && (Imm & 6)) {
  1059. MCInst Inst;
  1060. MCInstLowering.Lower(MI, Inst);
  1061. EmitToStreamer(*OutStreamer, Inst);
  1062. CurrentPatchableFunctionEntrySym = createTempSymbol("patch");
  1063. OutStreamer->emitLabel(CurrentPatchableFunctionEntrySym);
  1064. return;
  1065. }
  1066. }
  1067. break;
  1068. }
  1069. case AArch64::MOVMCSym: {
  1070. Register DestReg = MI->getOperand(0).getReg();
  1071. const MachineOperand &MO_Sym = MI->getOperand(1);
  1072. MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
  1073. MCOperand Hi_MCSym, Lo_MCSym;
  1074. Hi_MOSym.setTargetFlags(AArch64II::MO_G1 | AArch64II::MO_S);
  1075. Lo_MOSym.setTargetFlags(AArch64II::MO_G0 | AArch64II::MO_NC);
  1076. MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
  1077. MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
  1078. MCInst MovZ;
  1079. MovZ.setOpcode(AArch64::MOVZXi);
  1080. MovZ.addOperand(MCOperand::createReg(DestReg));
  1081. MovZ.addOperand(Hi_MCSym);
  1082. MovZ.addOperand(MCOperand::createImm(16));
  1083. EmitToStreamer(*OutStreamer, MovZ);
  1084. MCInst MovK;
  1085. MovK.setOpcode(AArch64::MOVKXi);
  1086. MovK.addOperand(MCOperand::createReg(DestReg));
  1087. MovK.addOperand(MCOperand::createReg(DestReg));
  1088. MovK.addOperand(Lo_MCSym);
  1089. MovK.addOperand(MCOperand::createImm(0));
  1090. EmitToStreamer(*OutStreamer, MovK);
  1091. return;
  1092. }
  1093. case AArch64::MOVIv2d_ns:
  1094. // If the target has <rdar://problem/16473581>, lower this
  1095. // instruction to movi.16b instead.
  1096. if (STI->hasZeroCycleZeroingFPWorkaround() &&
  1097. MI->getOperand(1).getImm() == 0) {
  1098. MCInst TmpInst;
  1099. TmpInst.setOpcode(AArch64::MOVIv16b_ns);
  1100. TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
  1101. TmpInst.addOperand(MCOperand::createImm(MI->getOperand(1).getImm()));
  1102. EmitToStreamer(*OutStreamer, TmpInst);
  1103. return;
  1104. }
  1105. break;
  1106. case AArch64::DBG_VALUE:
  1107. case AArch64::DBG_VALUE_LIST: {
  1108. if (isVerbose() && OutStreamer->hasRawTextSupport()) {
  1109. SmallString<128> TmpStr;
  1110. raw_svector_ostream OS(TmpStr);
  1111. PrintDebugValueComment(MI, OS);
  1112. OutStreamer->emitRawText(StringRef(OS.str()));
  1113. }
  1114. return;
  1115. case AArch64::EMITBKEY: {
  1116. ExceptionHandling ExceptionHandlingType = MAI->getExceptionHandlingType();
  1117. if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
  1118. ExceptionHandlingType != ExceptionHandling::ARM)
  1119. return;
  1120. if (getFunctionCFISectionType(*MF) == CFISection::None)
  1121. return;
  1122. OutStreamer->emitCFIBKeyFrame();
  1123. return;
  1124. }
  1125. }
  1126. // Tail calls use pseudo instructions so they have the proper code-gen
  1127. // attributes (isCall, isReturn, etc.). We lower them to the real
  1128. // instruction here.
  1129. case AArch64::TCRETURNri:
  1130. case AArch64::TCRETURNriBTI:
  1131. case AArch64::TCRETURNriALL: {
  1132. MCInst TmpInst;
  1133. TmpInst.setOpcode(AArch64::BR);
  1134. TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
  1135. EmitToStreamer(*OutStreamer, TmpInst);
  1136. return;
  1137. }
  1138. case AArch64::TCRETURNdi: {
  1139. MCOperand Dest;
  1140. MCInstLowering.lowerOperand(MI->getOperand(0), Dest);
  1141. MCInst TmpInst;
  1142. TmpInst.setOpcode(AArch64::B);
  1143. TmpInst.addOperand(Dest);
  1144. EmitToStreamer(*OutStreamer, TmpInst);
  1145. return;
  1146. }
  1147. case AArch64::SpeculationBarrierISBDSBEndBB: {
  1148. // Print DSB SYS + ISB
  1149. MCInst TmpInstDSB;
  1150. TmpInstDSB.setOpcode(AArch64::DSB);
  1151. TmpInstDSB.addOperand(MCOperand::createImm(0xf));
  1152. EmitToStreamer(*OutStreamer, TmpInstDSB);
  1153. MCInst TmpInstISB;
  1154. TmpInstISB.setOpcode(AArch64::ISB);
  1155. TmpInstISB.addOperand(MCOperand::createImm(0xf));
  1156. EmitToStreamer(*OutStreamer, TmpInstISB);
  1157. return;
  1158. }
  1159. case AArch64::SpeculationBarrierSBEndBB: {
  1160. // Print SB
  1161. MCInst TmpInstSB;
  1162. TmpInstSB.setOpcode(AArch64::SB);
  1163. EmitToStreamer(*OutStreamer, TmpInstSB);
  1164. return;
  1165. }
  1166. case AArch64::TLSDESC_CALLSEQ: {
  1167. /// lower this to:
  1168. /// adrp x0, :tlsdesc:var
  1169. /// ldr x1, [x0, #:tlsdesc_lo12:var]
  1170. /// add x0, x0, #:tlsdesc_lo12:var
  1171. /// .tlsdesccall var
  1172. /// blr x1
  1173. /// (TPIDR_EL0 offset now in x0)
  1174. const MachineOperand &MO_Sym = MI->getOperand(0);
  1175. MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
  1176. MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
  1177. MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
  1178. MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE);
  1179. MCInstLowering.lowerOperand(MO_Sym, Sym);
  1180. MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
  1181. MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
  1182. MCInst Adrp;
  1183. Adrp.setOpcode(AArch64::ADRP);
  1184. Adrp.addOperand(MCOperand::createReg(AArch64::X0));
  1185. Adrp.addOperand(SymTLSDesc);
  1186. EmitToStreamer(*OutStreamer, Adrp);
  1187. MCInst Ldr;
  1188. if (STI->isTargetILP32()) {
  1189. Ldr.setOpcode(AArch64::LDRWui);
  1190. Ldr.addOperand(MCOperand::createReg(AArch64::W1));
  1191. } else {
  1192. Ldr.setOpcode(AArch64::LDRXui);
  1193. Ldr.addOperand(MCOperand::createReg(AArch64::X1));
  1194. }
  1195. Ldr.addOperand(MCOperand::createReg(AArch64::X0));
  1196. Ldr.addOperand(SymTLSDescLo12);
  1197. Ldr.addOperand(MCOperand::createImm(0));
  1198. EmitToStreamer(*OutStreamer, Ldr);
  1199. MCInst Add;
  1200. if (STI->isTargetILP32()) {
  1201. Add.setOpcode(AArch64::ADDWri);
  1202. Add.addOperand(MCOperand::createReg(AArch64::W0));
  1203. Add.addOperand(MCOperand::createReg(AArch64::W0));
  1204. } else {
  1205. Add.setOpcode(AArch64::ADDXri);
  1206. Add.addOperand(MCOperand::createReg(AArch64::X0));
  1207. Add.addOperand(MCOperand::createReg(AArch64::X0));
  1208. }
  1209. Add.addOperand(SymTLSDescLo12);
  1210. Add.addOperand(MCOperand::createImm(AArch64_AM::getShiftValue(0)));
  1211. EmitToStreamer(*OutStreamer, Add);
  1212. // Emit a relocation-annotation. This expands to no code, but requests
  1213. // the following instruction gets an R_AARCH64_TLSDESC_CALL.
  1214. MCInst TLSDescCall;
  1215. TLSDescCall.setOpcode(AArch64::TLSDESCCALL);
  1216. TLSDescCall.addOperand(Sym);
  1217. EmitToStreamer(*OutStreamer, TLSDescCall);
  1218. MCInst Blr;
  1219. Blr.setOpcode(AArch64::BLR);
  1220. Blr.addOperand(MCOperand::createReg(AArch64::X1));
  1221. EmitToStreamer(*OutStreamer, Blr);
  1222. return;
  1223. }
  1224. case AArch64::JumpTableDest32:
  1225. case AArch64::JumpTableDest16:
  1226. case AArch64::JumpTableDest8:
  1227. LowerJumpTableDest(*OutStreamer, *MI);
  1228. return;
  1229. case AArch64::FMOVH0:
  1230. case AArch64::FMOVS0:
  1231. case AArch64::FMOVD0:
  1232. emitFMov0(*MI);
  1233. return;
  1234. case AArch64::MOPSMemoryCopyPseudo:
  1235. case AArch64::MOPSMemoryMovePseudo:
  1236. case AArch64::MOPSMemorySetPseudo:
  1237. case AArch64::MOPSMemorySetTaggingPseudo:
  1238. LowerMOPS(*OutStreamer, *MI);
  1239. return;
  1240. case TargetOpcode::STACKMAP:
  1241. return LowerSTACKMAP(*OutStreamer, SM, *MI);
  1242. case TargetOpcode::PATCHPOINT:
  1243. return LowerPATCHPOINT(*OutStreamer, SM, *MI);
  1244. case TargetOpcode::STATEPOINT:
  1245. return LowerSTATEPOINT(*OutStreamer, SM, *MI);
  1246. case TargetOpcode::FAULTING_OP:
  1247. return LowerFAULTING_OP(*MI);
  1248. case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
  1249. LowerPATCHABLE_FUNCTION_ENTER(*MI);
  1250. return;
  1251. case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
  1252. LowerPATCHABLE_FUNCTION_EXIT(*MI);
  1253. return;
  1254. case TargetOpcode::PATCHABLE_TAIL_CALL:
  1255. LowerPATCHABLE_TAIL_CALL(*MI);
  1256. return;
  1257. case AArch64::HWASAN_CHECK_MEMACCESS:
  1258. case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
  1259. LowerHWASAN_CHECK_MEMACCESS(*MI);
  1260. return;
  1261. case AArch64::SEH_StackAlloc:
  1262. TS->emitARM64WinCFIAllocStack(MI->getOperand(0).getImm());
  1263. return;
  1264. case AArch64::SEH_SaveFPLR:
  1265. TS->emitARM64WinCFISaveFPLR(MI->getOperand(0).getImm());
  1266. return;
  1267. case AArch64::SEH_SaveFPLR_X:
  1268. assert(MI->getOperand(0).getImm() < 0 &&
  1269. "Pre increment SEH opcode must have a negative offset");
  1270. TS->emitARM64WinCFISaveFPLRX(-MI->getOperand(0).getImm());
  1271. return;
  1272. case AArch64::SEH_SaveReg:
  1273. TS->emitARM64WinCFISaveReg(MI->getOperand(0).getImm(),
  1274. MI->getOperand(1).getImm());
  1275. return;
  1276. case AArch64::SEH_SaveReg_X:
  1277. assert(MI->getOperand(1).getImm() < 0 &&
  1278. "Pre increment SEH opcode must have a negative offset");
  1279. TS->emitARM64WinCFISaveRegX(MI->getOperand(0).getImm(),
  1280. -MI->getOperand(1).getImm());
  1281. return;
  1282. case AArch64::SEH_SaveRegP:
  1283. if (MI->getOperand(1).getImm() == 30 && MI->getOperand(0).getImm() >= 19 &&
  1284. MI->getOperand(0).getImm() <= 28) {
  1285. assert((MI->getOperand(0).getImm() - 19) % 2 == 0 &&
  1286. "Register paired with LR must be odd");
  1287. TS->emitARM64WinCFISaveLRPair(MI->getOperand(0).getImm(),
  1288. MI->getOperand(2).getImm());
  1289. return;
  1290. }
  1291. assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
  1292. "Non-consecutive registers not allowed for save_regp");
  1293. TS->emitARM64WinCFISaveRegP(MI->getOperand(0).getImm(),
  1294. MI->getOperand(2).getImm());
  1295. return;
  1296. case AArch64::SEH_SaveRegP_X:
  1297. assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
  1298. "Non-consecutive registers not allowed for save_regp_x");
  1299. assert(MI->getOperand(2).getImm() < 0 &&
  1300. "Pre increment SEH opcode must have a negative offset");
  1301. TS->emitARM64WinCFISaveRegPX(MI->getOperand(0).getImm(),
  1302. -MI->getOperand(2).getImm());
  1303. return;
  1304. case AArch64::SEH_SaveFReg:
  1305. TS->emitARM64WinCFISaveFReg(MI->getOperand(0).getImm(),
  1306. MI->getOperand(1).getImm());
  1307. return;
  1308. case AArch64::SEH_SaveFReg_X:
  1309. assert(MI->getOperand(1).getImm() < 0 &&
  1310. "Pre increment SEH opcode must have a negative offset");
  1311. TS->emitARM64WinCFISaveFRegX(MI->getOperand(0).getImm(),
  1312. -MI->getOperand(1).getImm());
  1313. return;
  1314. case AArch64::SEH_SaveFRegP:
  1315. assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
  1316. "Non-consecutive registers not allowed for save_regp");
  1317. TS->emitARM64WinCFISaveFRegP(MI->getOperand(0).getImm(),
  1318. MI->getOperand(2).getImm());
  1319. return;
  1320. case AArch64::SEH_SaveFRegP_X:
  1321. assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
  1322. "Non-consecutive registers not allowed for save_regp_x");
  1323. assert(MI->getOperand(2).getImm() < 0 &&
  1324. "Pre increment SEH opcode must have a negative offset");
  1325. TS->emitARM64WinCFISaveFRegPX(MI->getOperand(0).getImm(),
  1326. -MI->getOperand(2).getImm());
  1327. return;
  1328. case AArch64::SEH_SetFP:
  1329. TS->emitARM64WinCFISetFP();
  1330. return;
  1331. case AArch64::SEH_AddFP:
  1332. TS->emitARM64WinCFIAddFP(MI->getOperand(0).getImm());
  1333. return;
  1334. case AArch64::SEH_Nop:
  1335. TS->emitARM64WinCFINop();
  1336. return;
  1337. case AArch64::SEH_PrologEnd:
  1338. TS->emitARM64WinCFIPrologEnd();
  1339. return;
  1340. case AArch64::SEH_EpilogStart:
  1341. TS->emitARM64WinCFIEpilogStart();
  1342. return;
  1343. case AArch64::SEH_EpilogEnd:
  1344. TS->emitARM64WinCFIEpilogEnd();
  1345. return;
  1346. }
  1347. // Finally, do the automated lowerings for everything else.
  1348. MCInst TmpInst;
  1349. MCInstLowering.Lower(MI, TmpInst);
  1350. EmitToStreamer(*OutStreamer, TmpInst);
  1351. }
  1352. // Force static initialization.
  1353. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64AsmPrinter() {
  1354. RegisterAsmPrinter<AArch64AsmPrinter> X(getTheAArch64leTarget());
  1355. RegisterAsmPrinter<AArch64AsmPrinter> Y(getTheAArch64beTarget());
  1356. RegisterAsmPrinter<AArch64AsmPrinter> Z(getTheARM64Target());
  1357. RegisterAsmPrinter<AArch64AsmPrinter> W(getTheARM64_32Target());
  1358. RegisterAsmPrinter<AArch64AsmPrinter> V(getTheAArch64_32Target());
  1359. }