]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304149, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AArch64 / AArch64AsmPrinter.cpp
1 //===-- AArch64AsmPrinter.cpp - AArch64 LLVM assembly writer --------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to the AArch64 assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "MCTargetDesc/AArch64AddressingModes.h"
16 #include "AArch64.h"
17 #include "AArch64MCInstLower.h"
18 #include "AArch64MachineFunctionInfo.h"
19 #include "AArch64RegisterInfo.h"
20 #include "AArch64Subtarget.h"
21 #include "InstPrinter/AArch64InstPrinter.h"
22 #include "MCTargetDesc/AArch64MCExpr.h"
23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/ADT/Twine.h"
26 #include "llvm/CodeGen/AsmPrinter.h"
27 #include "llvm/CodeGen/MachineInstr.h"
28 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
29 #include "llvm/CodeGen/StackMaps.h"
30 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
31 #include "llvm/IR/DataLayout.h"
32 #include "llvm/IR/DebugInfo.h"
33 #include "llvm/MC/MCAsmInfo.h"
34 #include "llvm/MC/MCContext.h"
35 #include "llvm/MC/MCInst.h"
36 #include "llvm/MC/MCInstBuilder.h"
37 #include "llvm/MC/MCLinkerOptimizationHint.h"
38 #include "llvm/MC/MCStreamer.h"
39 #include "llvm/MC/MCSymbol.h"
40 #include "llvm/MC/MCSymbolELF.h"
41 #include "llvm/MC/MCSectionELF.h"
42 #include "llvm/MC/MCSectionMachO.h"
43 #include "llvm/Support/Debug.h"
44 #include "llvm/Support/TargetRegistry.h"
45 #include "llvm/Support/raw_ostream.h"
46 using namespace llvm;
47
48 #define DEBUG_TYPE "asm-printer"
49
50 namespace {
51
52 class AArch64AsmPrinter : public AsmPrinter {
53   AArch64MCInstLower MCInstLowering;
54   StackMaps SM;
55   const AArch64Subtarget *STI;
56
57 public:
58   AArch64AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
59       : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this),
60         SM(*this), AArch64FI(nullptr) {}
61
62   StringRef getPassName() const override { return "AArch64 Assembly Printer"; }
63
64   /// \brief Wrapper for MCInstLowering.lowerOperand() for the
65   /// tblgen'erated pseudo lowering.
66   bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
67     return MCInstLowering.lowerOperand(MO, MCOp);
68   }
69
70   void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
71                      const MachineInstr &MI);
72   void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
73                        const MachineInstr &MI);
74
75   void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
76   void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
77   void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
78
79   void EmitSled(const MachineInstr &MI, SledKind Kind);
80
81   /// \brief tblgen'erated driver function for lowering simple MI->MC
82   /// pseudo instructions.
83   bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
84                                    const MachineInstr *MI);
85
86   void EmitInstruction(const MachineInstr *MI) override;
87
88   void getAnalysisUsage(AnalysisUsage &AU) const override {
89     AsmPrinter::getAnalysisUsage(AU);
90     AU.setPreservesAll();
91   }
92
93   bool runOnMachineFunction(MachineFunction &F) override {
94     AArch64FI = F.getInfo<AArch64FunctionInfo>();
95     STI = static_cast<const AArch64Subtarget*>(&F.getSubtarget());
96     bool Result = AsmPrinter::runOnMachineFunction(F);
97     emitXRayTable();
98     return Result;
99   }
100
101 private:
102   void printOperand(const MachineInstr *MI, unsigned OpNum, raw_ostream &O);
103   bool printAsmMRegister(const MachineOperand &MO, char Mode, raw_ostream &O);
104   bool printAsmRegInClass(const MachineOperand &MO,
105                           const TargetRegisterClass *RC, bool isVector,
106                           raw_ostream &O);
107
108   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
109                        unsigned AsmVariant, const char *ExtraCode,
110                        raw_ostream &O) override;
111   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
112                              unsigned AsmVariant, const char *ExtraCode,
113                              raw_ostream &O) override;
114
115   void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
116
117   void EmitFunctionBodyEnd() override;
118
119   MCSymbol *GetCPISymbol(unsigned CPID) const override;
120   void EmitEndOfAsmFile(Module &M) override;
121   AArch64FunctionInfo *AArch64FI;
122
123   /// \brief Emit the LOHs contained in AArch64FI.
124   void EmitLOHs();
125
126   /// Emit instruction to set float register to zero.
127   void EmitFMov0(const MachineInstr &MI);
128
129   typedef std::map<const MachineInstr *, MCSymbol *> MInstToMCSymbol;
130   MInstToMCSymbol LOHInstToLabel;
131 };
132
133 } // end of anonymous namespace
134
135 //===----------------------------------------------------------------------===//
136
137 void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
138 {
139   EmitSled(MI, SledKind::FUNCTION_ENTER);
140 }
141
142 void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
143 {
144   EmitSled(MI, SledKind::FUNCTION_EXIT);
145 }
146
147 void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
148 {
149   EmitSled(MI, SledKind::TAIL_CALL);
150 }
151
152 void AArch64AsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
153 {
154   static const int8_t NoopsInSledCount = 7;
155   // We want to emit the following pattern:
156   //
157   // .Lxray_sled_N:
158   //   ALIGN
159   //   B #32
160   //   ; 7 NOP instructions (28 bytes)
161   // .tmpN
162   //
163   // We need the 28 bytes (7 instructions) because at runtime, we'd be patching
164   // over the full 32 bytes (8 instructions) with the following pattern:
165   //
166   //   STP X0, X30, [SP, #-16]! ; push X0 and the link register to the stack
167   //   LDR W0, #12 ; W0 := function ID
168   //   LDR X16,#12 ; X16 := addr of __xray_FunctionEntry or __xray_FunctionExit
169   //   BLR X16 ; call the tracing trampoline
170   //   ;DATA: 32 bits of function ID
171   //   ;DATA: lower 32 bits of the address of the trampoline
172   //   ;DATA: higher 32 bits of the address of the trampoline
173   //   LDP X0, X30, [SP], #16 ; pop X0 and the link register from the stack
174   //
175   OutStreamer->EmitCodeAlignment(4);
176   auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
177   OutStreamer->EmitLabel(CurSled);
178   auto Target = OutContext.createTempSymbol();
179
180   // Emit "B #32" instruction, which jumps over the next 28 bytes.
181   // The operand has to be the number of 4-byte instructions to jump over,
182   // including the current instruction.
183   EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
184
185   for (int8_t I = 0; I < NoopsInSledCount; I++)
186     EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
187
188   OutStreamer->EmitLabel(Target);
189   recordSled(CurSled, MI, Kind);
190 }
191
192 void AArch64AsmPrinter::EmitEndOfAsmFile(Module &M) {
193   const Triple &TT = TM.getTargetTriple();
194   if (TT.isOSBinFormatMachO()) {
195     // Funny Darwin hack: This flag tells the linker that no global symbols
196     // contain code that falls through to other global symbols (e.g. the obvious
197     // implementation of multiple entry points).  If this doesn't occur, the
198     // linker can safely perform dead code stripping.  Since LLVM never
199     // generates code that does this, it is always safe to set.
200     OutStreamer->EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
201     SM.serializeToStackMapSection();
202   }
203 }
204
205 void AArch64AsmPrinter::EmitLOHs() {
206   SmallVector<MCSymbol *, 3> MCArgs;
207
208   for (const auto &D : AArch64FI->getLOHContainer()) {
209     for (const MachineInstr *MI : D.getArgs()) {
210       MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(MI);
211       assert(LabelIt != LOHInstToLabel.end() &&
212              "Label hasn't been inserted for LOH related instruction");
213       MCArgs.push_back(LabelIt->second);
214     }
215     OutStreamer->EmitLOHDirective(D.getKind(), MCArgs);
216     MCArgs.clear();
217   }
218 }
219
220 void AArch64AsmPrinter::EmitFunctionBodyEnd() {
221   if (!AArch64FI->getLOHRelated().empty())
222     EmitLOHs();
223 }
224
225 /// GetCPISymbol - Return the symbol for the specified constant pool entry.
226 MCSymbol *AArch64AsmPrinter::GetCPISymbol(unsigned CPID) const {
227   // Darwin uses a linker-private symbol name for constant-pools (to
228   // avoid addends on the relocation?), ELF has no such concept and
229   // uses a normal private symbol.
230   if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
231     return OutContext.getOrCreateSymbol(
232         Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) + "CPI" +
233         Twine(getFunctionNumber()) + "_" + Twine(CPID));
234
235   return OutContext.getOrCreateSymbol(
236       Twine(getDataLayout().getPrivateGlobalPrefix()) + "CPI" +
237       Twine(getFunctionNumber()) + "_" + Twine(CPID));
238 }
239
240 void AArch64AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNum,
241                                      raw_ostream &O) {
242   const MachineOperand &MO = MI->getOperand(OpNum);
243   switch (MO.getType()) {
244   default:
245     llvm_unreachable("<unknown operand type>");
246   case MachineOperand::MO_Register: {
247     unsigned Reg = MO.getReg();
248     assert(TargetRegisterInfo::isPhysicalRegister(Reg));
249     assert(!MO.getSubReg() && "Subregs should be eliminated!");
250     O << AArch64InstPrinter::getRegisterName(Reg);
251     break;
252   }
253   case MachineOperand::MO_Immediate: {
254     int64_t Imm = MO.getImm();
255     O << '#' << Imm;
256     break;
257   }
258   case MachineOperand::MO_GlobalAddress: {
259     const GlobalValue *GV = MO.getGlobal();
260     MCSymbol *Sym = getSymbol(GV);
261
262     // FIXME: Can we get anything other than a plain symbol here?
263     assert(!MO.getTargetFlags() && "Unknown operand target flag!");
264
265     Sym->print(O, MAI);
266     printOffset(MO.getOffset(), O);
267     break;
268   }
269   }
270 }
271
272 bool AArch64AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode,
273                                           raw_ostream &O) {
274   unsigned Reg = MO.getReg();
275   switch (Mode) {
276   default:
277     return true; // Unknown mode.
278   case 'w':
279     Reg = getWRegFromXReg(Reg);
280     break;
281   case 'x':
282     Reg = getXRegFromWReg(Reg);
283     break;
284   }
285
286   O << AArch64InstPrinter::getRegisterName(Reg);
287   return false;
288 }
289
290 // Prints the register in MO using class RC using the offset in the
291 // new register class. This should not be used for cross class
292 // printing.
293 bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO,
294                                            const TargetRegisterClass *RC,
295                                            bool isVector, raw_ostream &O) {
296   assert(MO.isReg() && "Should only get here with a register!");
297   const TargetRegisterInfo *RI = STI->getRegisterInfo();
298   unsigned Reg = MO.getReg();
299   unsigned RegToPrint = RC->getRegister(RI->getEncodingValue(Reg));
300   assert(RI->regsOverlap(RegToPrint, Reg));
301   O << AArch64InstPrinter::getRegisterName(
302            RegToPrint, isVector ? AArch64::vreg : AArch64::NoRegAltName);
303   return false;
304 }
305
306 bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
307                                         unsigned AsmVariant,
308                                         const char *ExtraCode, raw_ostream &O) {
309   const MachineOperand &MO = MI->getOperand(OpNum);
310
311   // First try the generic code, which knows about modifiers like 'c' and 'n'.
312   if (!AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O))
313     return false;
314
315   // Does this asm operand have a single letter operand modifier?
316   if (ExtraCode && ExtraCode[0]) {
317     if (ExtraCode[1] != 0)
318       return true; // Unknown modifier.
319
320     switch (ExtraCode[0]) {
321     default:
322       return true; // Unknown modifier.
323     case 'a':      // Print 'a' modifier
324       PrintAsmMemoryOperand(MI, OpNum, AsmVariant, ExtraCode, O);
325       return false;
326     case 'w':      // Print W register
327     case 'x':      // Print X register
328       if (MO.isReg())
329         return printAsmMRegister(MO, ExtraCode[0], O);
330       if (MO.isImm() && MO.getImm() == 0) {
331         unsigned Reg = ExtraCode[0] == 'w' ? AArch64::WZR : AArch64::XZR;
332         O << AArch64InstPrinter::getRegisterName(Reg);
333         return false;
334       }
335       printOperand(MI, OpNum, O);
336       return false;
337     case 'b': // Print B register.
338     case 'h': // Print H register.
339     case 's': // Print S register.
340     case 'd': // Print D register.
341     case 'q': // Print Q register.
342       if (MO.isReg()) {
343         const TargetRegisterClass *RC;
344         switch (ExtraCode[0]) {
345         case 'b':
346           RC = &AArch64::FPR8RegClass;
347           break;
348         case 'h':
349           RC = &AArch64::FPR16RegClass;
350           break;
351         case 's':
352           RC = &AArch64::FPR32RegClass;
353           break;
354         case 'd':
355           RC = &AArch64::FPR64RegClass;
356           break;
357         case 'q':
358           RC = &AArch64::FPR128RegClass;
359           break;
360         default:
361           return true;
362         }
363         return printAsmRegInClass(MO, RC, false /* vector */, O);
364       }
365       printOperand(MI, OpNum, O);
366       return false;
367     }
368   }
369
370   // According to ARM, we should emit x and v registers unless we have a
371   // modifier.
372   if (MO.isReg()) {
373     unsigned Reg = MO.getReg();
374
375     // If this is a w or x register, print an x register.
376     if (AArch64::GPR32allRegClass.contains(Reg) ||
377         AArch64::GPR64allRegClass.contains(Reg))
378       return printAsmMRegister(MO, 'x', O);
379
380     // If this is a b, h, s, d, or q register, print it as a v register.
381     return printAsmRegInClass(MO, &AArch64::FPR128RegClass, true /* vector */,
382                               O);
383   }
384
385   printOperand(MI, OpNum, O);
386   return false;
387 }
388
389 bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
390                                               unsigned OpNum,
391                                               unsigned AsmVariant,
392                                               const char *ExtraCode,
393                                               raw_ostream &O) {
394   if (ExtraCode && ExtraCode[0] && ExtraCode[0] != 'a')
395     return true; // Unknown modifier.
396
397   const MachineOperand &MO = MI->getOperand(OpNum);
398   assert(MO.isReg() && "unexpected inline asm memory operand");
399   O << "[" << AArch64InstPrinter::getRegisterName(MO.getReg()) << "]";
400   return false;
401 }
402
403 void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
404                                                raw_ostream &OS) {
405   unsigned NOps = MI->getNumOperands();
406   assert(NOps == 4);
407   OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
408   // cast away const; DIetc do not take const operands for some reason.
409   OS << cast<DILocalVariable>(MI->getOperand(NOps - 2).getMetadata())
410             ->getName();
411   OS << " <- ";
412   // Frame address.  Currently handles register +- offset only.
413   assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
414   OS << '[';
415   printOperand(MI, 0, OS);
416   OS << '+';
417   printOperand(MI, 1, OS);
418   OS << ']';
419   OS << "+";
420   printOperand(MI, NOps - 2, OS);
421 }
422
423 void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
424                                       const MachineInstr &MI) {
425   unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
426
427   SM.recordStackMap(MI);
428   assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
429
430   // Scan ahead to trim the shadow.
431   const MachineBasicBlock &MBB = *MI.getParent();
432   MachineBasicBlock::const_iterator MII(MI);
433   ++MII;
434   while (NumNOPBytes > 0) {
435     if (MII == MBB.end() || MII->isCall() ||
436         MII->getOpcode() == AArch64::DBG_VALUE ||
437         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
438         MII->getOpcode() == TargetOpcode::STACKMAP)
439       break;
440     ++MII;
441     NumNOPBytes -= 4;
442   }
443
444   // Emit nops.
445   for (unsigned i = 0; i < NumNOPBytes; i += 4)
446     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
447 }
448
449 // Lower a patchpoint of the form:
450 // [<def>], <id>, <numBytes>, <target>, <numArgs>
451 void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
452                                         const MachineInstr &MI) {
453   SM.recordPatchPoint(MI);
454
455   PatchPointOpers Opers(&MI);
456
457   int64_t CallTarget = Opers.getCallTarget().getImm();
458   unsigned EncodedBytes = 0;
459   if (CallTarget) {
460     assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
461            "High 16 bits of call target should be zero.");
462     unsigned ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
463     EncodedBytes = 16;
464     // Materialize the jump address:
465     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVZXi)
466                                     .addReg(ScratchReg)
467                                     .addImm((CallTarget >> 32) & 0xFFFF)
468                                     .addImm(32));
469     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
470                                     .addReg(ScratchReg)
471                                     .addReg(ScratchReg)
472                                     .addImm((CallTarget >> 16) & 0xFFFF)
473                                     .addImm(16));
474     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
475                                     .addReg(ScratchReg)
476                                     .addReg(ScratchReg)
477                                     .addImm(CallTarget & 0xFFFF)
478                                     .addImm(0));
479     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
480   }
481   // Emit padding.
482   unsigned NumBytes = Opers.getNumPatchBytes();
483   assert(NumBytes >= EncodedBytes &&
484          "Patchpoint can't request size less than the length of a call.");
485   assert((NumBytes - EncodedBytes) % 4 == 0 &&
486          "Invalid number of NOP bytes requested!");
487   for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
488     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
489 }
490
491 void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) {
492   unsigned DestReg = MI.getOperand(0).getReg();
493   if (STI->hasZeroCycleZeroing()) {
494     // Convert S/D register to corresponding Q register
495     if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31) {
496       DestReg = AArch64::Q0 + (DestReg - AArch64::S0);
497     } else {
498       assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
499       DestReg = AArch64::Q0 + (DestReg - AArch64::D0);
500     }
501     MCInst MOVI;
502     MOVI.setOpcode(AArch64::MOVIv2d_ns);
503     MOVI.addOperand(MCOperand::createReg(DestReg));
504     MOVI.addOperand(MCOperand::createImm(0));
505     EmitToStreamer(*OutStreamer, MOVI);
506   } else {
507     MCInst FMov;
508     switch (MI.getOpcode()) {
509     default: llvm_unreachable("Unexpected opcode");
510     case AArch64::FMOVS0:
511       FMov.setOpcode(AArch64::FMOVWSr);
512       FMov.addOperand(MCOperand::createReg(DestReg));
513       FMov.addOperand(MCOperand::createReg(AArch64::WZR));
514       break;
515     case AArch64::FMOVD0:
516       FMov.setOpcode(AArch64::FMOVXDr);
517       FMov.addOperand(MCOperand::createReg(DestReg));
518       FMov.addOperand(MCOperand::createReg(AArch64::XZR));
519       break;
520     }
521     EmitToStreamer(*OutStreamer, FMov);
522   }
523 }
524
525 // Simple pseudo-instructions have their lowering (with expansion to real
526 // instructions) auto-generated.
527 #include "AArch64GenMCPseudoLowering.inc"
528
529 void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
530   // Do any auto-generated pseudo lowerings.
531   if (emitPseudoExpansionLowering(*OutStreamer, MI))
532     return;
533
534   if (AArch64FI->getLOHRelated().count(MI)) {
535     // Generate a label for LOH related instruction
536     MCSymbol *LOHLabel = createTempSymbol("loh");
537     // Associate the instruction with the label
538     LOHInstToLabel[MI] = LOHLabel;
539     OutStreamer->EmitLabel(LOHLabel);
540   }
541
542   // Do any manual lowerings.
543   switch (MI->getOpcode()) {
544   default:
545     break;
546   case AArch64::DBG_VALUE: {
547     if (isVerbose() && OutStreamer->hasRawTextSupport()) {
548       SmallString<128> TmpStr;
549       raw_svector_ostream OS(TmpStr);
550       PrintDebugValueComment(MI, OS);
551       OutStreamer->EmitRawText(StringRef(OS.str()));
552     }
553     return;
554   }
555
556   // Tail calls use pseudo instructions so they have the proper code-gen
557   // attributes (isCall, isReturn, etc.). We lower them to the real
558   // instruction here.
559   case AArch64::TCRETURNri: {
560     MCInst TmpInst;
561     TmpInst.setOpcode(AArch64::BR);
562     TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
563     EmitToStreamer(*OutStreamer, TmpInst);
564     return;
565   }
566   case AArch64::TCRETURNdi: {
567     MCOperand Dest;
568     MCInstLowering.lowerOperand(MI->getOperand(0), Dest);
569     MCInst TmpInst;
570     TmpInst.setOpcode(AArch64::B);
571     TmpInst.addOperand(Dest);
572     EmitToStreamer(*OutStreamer, TmpInst);
573     return;
574   }
575   case AArch64::TLSDESC_CALLSEQ: {
576     /// lower this to:
577     ///    adrp  x0, :tlsdesc:var
578     ///    ldr   x1, [x0, #:tlsdesc_lo12:var]
579     ///    add   x0, x0, #:tlsdesc_lo12:var
580     ///    .tlsdesccall var
581     ///    blr   x1
582     ///    (TPIDR_EL0 offset now in x0)
583     const MachineOperand &MO_Sym = MI->getOperand(0);
584     MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
585     MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
586     MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
587     MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE);
588     MCInstLowering.lowerOperand(MO_Sym, Sym);
589     MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
590     MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
591
592     MCInst Adrp;
593     Adrp.setOpcode(AArch64::ADRP);
594     Adrp.addOperand(MCOperand::createReg(AArch64::X0));
595     Adrp.addOperand(SymTLSDesc);
596     EmitToStreamer(*OutStreamer, Adrp);
597
598     MCInst Ldr;
599     Ldr.setOpcode(AArch64::LDRXui);
600     Ldr.addOperand(MCOperand::createReg(AArch64::X1));
601     Ldr.addOperand(MCOperand::createReg(AArch64::X0));
602     Ldr.addOperand(SymTLSDescLo12);
603     Ldr.addOperand(MCOperand::createImm(0));
604     EmitToStreamer(*OutStreamer, Ldr);
605
606     MCInst Add;
607     Add.setOpcode(AArch64::ADDXri);
608     Add.addOperand(MCOperand::createReg(AArch64::X0));
609     Add.addOperand(MCOperand::createReg(AArch64::X0));
610     Add.addOperand(SymTLSDescLo12);
611     Add.addOperand(MCOperand::createImm(AArch64_AM::getShiftValue(0)));
612     EmitToStreamer(*OutStreamer, Add);
613
614     // Emit a relocation-annotation. This expands to no code, but requests
615     // the following instruction gets an R_AARCH64_TLSDESC_CALL.
616     MCInst TLSDescCall;
617     TLSDescCall.setOpcode(AArch64::TLSDESCCALL);
618     TLSDescCall.addOperand(Sym);
619     EmitToStreamer(*OutStreamer, TLSDescCall);
620
621     MCInst Blr;
622     Blr.setOpcode(AArch64::BLR);
623     Blr.addOperand(MCOperand::createReg(AArch64::X1));
624     EmitToStreamer(*OutStreamer, Blr);
625
626     return;
627   }
628
629   case AArch64::FMOVS0:
630   case AArch64::FMOVD0:
631     EmitFMov0(*MI);
632     return;
633
634   case TargetOpcode::STACKMAP:
635     return LowerSTACKMAP(*OutStreamer, SM, *MI);
636
637   case TargetOpcode::PATCHPOINT:
638     return LowerPATCHPOINT(*OutStreamer, SM, *MI);
639
640   case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
641     LowerPATCHABLE_FUNCTION_ENTER(*MI);
642     return;
643
644   case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
645     LowerPATCHABLE_FUNCTION_EXIT(*MI);
646     return;
647
648   case TargetOpcode::PATCHABLE_TAIL_CALL:
649     LowerPATCHABLE_TAIL_CALL(*MI);
650     return;
651   }
652
653   // Finally, do the automated lowerings for everything else.
654   MCInst TmpInst;
655   MCInstLowering.Lower(MI, TmpInst);
656   EmitToStreamer(*OutStreamer, TmpInst);
657 }
658
659 // Force static initialization.
660 extern "C" void LLVMInitializeAArch64AsmPrinter() {
661   RegisterAsmPrinter<AArch64AsmPrinter> X(getTheAArch64leTarget());
662   RegisterAsmPrinter<AArch64AsmPrinter> Y(getTheAArch64beTarget());
663   RegisterAsmPrinter<AArch64AsmPrinter> Z(getTheARM64Target());
664 }