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