Fix PR22408 - LLVM producing AArch64 TLS relocations that GNU linkers cannot handle...
[oota-llvm.git] / 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 "MCTargetDesc/AArch64MCExpr.h"
17 #include "AArch64.h"
18 #include "AArch64MCInstLower.h"
19 #include "AArch64MachineFunctionInfo.h"
20 #include "AArch64RegisterInfo.h"
21 #include "AArch64Subtarget.h"
22 #include "InstPrinter/AArch64InstPrinter.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/Support/Debug.h"
40 #include "llvm/Support/TargetRegistry.h"
41 using namespace llvm;
42
43 #define DEBUG_TYPE "asm-printer"
44
45 namespace {
46
47 class AArch64AsmPrinter : public AsmPrinter {
48   AArch64MCInstLower MCInstLowering;
49   StackMaps SM;
50
51 public:
52   AArch64AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
53       : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this),
54         SM(*this), AArch64FI(nullptr), LOHLabelCounter(0) {}
55
56   const char *getPassName() const override {
57     return "AArch64 Assembly Printer";
58   }
59
60   /// \brief Wrapper for MCInstLowering.lowerOperand() for the
61   /// tblgen'erated pseudo lowering.
62   bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
63     return MCInstLowering.lowerOperand(MO, MCOp);
64   }
65
66   void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
67                      const MachineInstr &MI);
68   void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
69                        const MachineInstr &MI);
70   /// \brief tblgen'erated driver function for lowering simple MI->MC
71   /// pseudo instructions.
72   bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
73                                    const MachineInstr *MI);
74
75   void EmitInstruction(const MachineInstr *MI) override;
76
77   void getAnalysisUsage(AnalysisUsage &AU) const override {
78     AsmPrinter::getAnalysisUsage(AU);
79     AU.setPreservesAll();
80   }
81
82   bool runOnMachineFunction(MachineFunction &F) override {
83     AArch64FI = F.getInfo<AArch64FunctionInfo>();
84     return AsmPrinter::runOnMachineFunction(F);
85   }
86
87 private:
88   MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
89   void printOperand(const MachineInstr *MI, unsigned OpNum, raw_ostream &O);
90   bool printAsmMRegister(const MachineOperand &MO, char Mode, raw_ostream &O);
91   bool printAsmRegInClass(const MachineOperand &MO,
92                           const TargetRegisterClass *RC, bool isVector,
93                           raw_ostream &O);
94
95   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
96                        unsigned AsmVariant, const char *ExtraCode,
97                        raw_ostream &O) override;
98   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
99                              unsigned AsmVariant, const char *ExtraCode,
100                              raw_ostream &O) override;
101
102   void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
103
104   void EmitFunctionBodyEnd() override;
105
106   MCSymbol *GetCPISymbol(unsigned CPID) const override;
107   void EmitEndOfAsmFile(Module &M) override;
108   AArch64FunctionInfo *AArch64FI;
109
110   /// \brief Emit the LOHs contained in AArch64FI.
111   void EmitLOHs();
112
113   typedef std::map<const MachineInstr *, MCSymbol *> MInstToMCSymbol;
114   MInstToMCSymbol LOHInstToLabel;
115   unsigned LOHLabelCounter;
116 };
117
118 } // end of anonymous namespace
119
120 //===----------------------------------------------------------------------===//
121
122 void AArch64AsmPrinter::EmitEndOfAsmFile(Module &M) {
123   Triple TT(TM.getTargetTriple());
124   if (TT.isOSBinFormatMachO()) {
125     // Funny Darwin hack: This flag tells the linker that no global symbols
126     // contain code that falls through to other global symbols (e.g. the obvious
127     // implementation of multiple entry points).  If this doesn't occur, the
128     // linker can safely perform dead code stripping.  Since LLVM never
129     // generates code that does this, it is always safe to set.
130     OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
131     SM.serializeToStackMapSection();
132   }
133
134   // Emit a .data.rel section containing any stubs that were created.
135   if (TT.isOSBinFormatELF()) {
136     const TargetLoweringObjectFileELF &TLOFELF =
137       static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
138
139     MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
140
141     // Output stubs for external and common global variables.
142     MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
143     if (!Stubs.empty()) {
144       OutStreamer.SwitchSection(TLOFELF.getDataRelSection());
145       const DataLayout *TD = TM.getDataLayout();
146
147       for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
148         OutStreamer.EmitLabel(Stubs[i].first);
149         OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(),
150                                     TD->getPointerSize(0));
151       }
152       Stubs.clear();
153     }
154   }
155
156 }
157
158 MachineLocation
159 AArch64AsmPrinter::getDebugValueLocation(const MachineInstr *MI) const {
160   MachineLocation Location;
161   assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
162   // Frame address.  Currently handles register +- offset only.
163   if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm())
164     Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
165   else {
166     DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n");
167   }
168   return Location;
169 }
170
171 void AArch64AsmPrinter::EmitLOHs() {
172   SmallVector<MCSymbol *, 3> MCArgs;
173
174   for (const auto &D : AArch64FI->getLOHContainer()) {
175     for (const MachineInstr *MI : D.getArgs()) {
176       MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(MI);
177       assert(LabelIt != LOHInstToLabel.end() &&
178              "Label hasn't been inserted for LOH related instruction");
179       MCArgs.push_back(LabelIt->second);
180     }
181     OutStreamer.EmitLOHDirective(D.getKind(), MCArgs);
182     MCArgs.clear();
183   }
184 }
185
186 void AArch64AsmPrinter::EmitFunctionBodyEnd() {
187   if (!AArch64FI->getLOHRelated().empty())
188     EmitLOHs();
189 }
190
191 /// GetCPISymbol - Return the symbol for the specified constant pool entry.
192 MCSymbol *AArch64AsmPrinter::GetCPISymbol(unsigned CPID) const {
193   // Darwin uses a linker-private symbol name for constant-pools (to
194   // avoid addends on the relocation?), ELF has no such concept and
195   // uses a normal private symbol.
196   if (getDataLayout().getLinkerPrivateGlobalPrefix()[0])
197     return OutContext.GetOrCreateSymbol(
198         Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) + "CPI" +
199         Twine(getFunctionNumber()) + "_" + Twine(CPID));
200
201   return OutContext.GetOrCreateSymbol(
202       Twine(getDataLayout().getPrivateGlobalPrefix()) + "CPI" +
203       Twine(getFunctionNumber()) + "_" + Twine(CPID));
204 }
205
206 void AArch64AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNum,
207                                      raw_ostream &O) {
208   const MachineOperand &MO = MI->getOperand(OpNum);
209   switch (MO.getType()) {
210   default:
211     llvm_unreachable("<unknown operand type>");
212   case MachineOperand::MO_Register: {
213     unsigned Reg = MO.getReg();
214     assert(TargetRegisterInfo::isPhysicalRegister(Reg));
215     assert(!MO.getSubReg() && "Subregs should be eliminated!");
216     O << AArch64InstPrinter::getRegisterName(Reg);
217     break;
218   }
219   case MachineOperand::MO_Immediate: {
220     int64_t Imm = MO.getImm();
221     O << '#' << Imm;
222     break;
223   }
224   }
225 }
226
227 bool AArch64AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode,
228                                           raw_ostream &O) {
229   unsigned Reg = MO.getReg();
230   switch (Mode) {
231   default:
232     return true; // Unknown mode.
233   case 'w':
234     Reg = getWRegFromXReg(Reg);
235     break;
236   case 'x':
237     Reg = getXRegFromWReg(Reg);
238     break;
239   }
240
241   O << AArch64InstPrinter::getRegisterName(Reg);
242   return false;
243 }
244
245 // Prints the register in MO using class RC using the offset in the
246 // new register class. This should not be used for cross class
247 // printing.
248 bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO,
249                                            const TargetRegisterClass *RC,
250                                            bool isVector, raw_ostream &O) {
251   assert(MO.isReg() && "Should only get here with a register!");
252   const AArch64RegisterInfo *RI =
253       MF->getSubtarget<AArch64Subtarget>().getRegisterInfo();
254   unsigned Reg = MO.getReg();
255   unsigned RegToPrint = RC->getRegister(RI->getEncodingValue(Reg));
256   assert(RI->regsOverlap(RegToPrint, Reg));
257   O << AArch64InstPrinter::getRegisterName(
258            RegToPrint, isVector ? AArch64::vreg : AArch64::NoRegAltName);
259   return false;
260 }
261
262 bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
263                                         unsigned AsmVariant,
264                                         const char *ExtraCode, raw_ostream &O) {
265   const MachineOperand &MO = MI->getOperand(OpNum);
266
267   // First try the generic code, which knows about modifiers like 'c' and 'n'.
268   if (!AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O))
269     return false;
270
271   // Does this asm operand have a single letter operand modifier?
272   if (ExtraCode && ExtraCode[0]) {
273     if (ExtraCode[1] != 0)
274       return true; // Unknown modifier.
275
276     switch (ExtraCode[0]) {
277     default:
278       return true; // Unknown modifier.
279     case 'w':      // Print W register
280     case 'x':      // Print X register
281       if (MO.isReg())
282         return printAsmMRegister(MO, ExtraCode[0], O);
283       if (MO.isImm() && MO.getImm() == 0) {
284         unsigned Reg = ExtraCode[0] == 'w' ? AArch64::WZR : AArch64::XZR;
285         O << AArch64InstPrinter::getRegisterName(Reg);
286         return false;
287       }
288       printOperand(MI, OpNum, O);
289       return false;
290     case 'b': // Print B register.
291     case 'h': // Print H register.
292     case 's': // Print S register.
293     case 'd': // Print D register.
294     case 'q': // Print Q register.
295       if (MO.isReg()) {
296         const TargetRegisterClass *RC;
297         switch (ExtraCode[0]) {
298         case 'b':
299           RC = &AArch64::FPR8RegClass;
300           break;
301         case 'h':
302           RC = &AArch64::FPR16RegClass;
303           break;
304         case 's':
305           RC = &AArch64::FPR32RegClass;
306           break;
307         case 'd':
308           RC = &AArch64::FPR64RegClass;
309           break;
310         case 'q':
311           RC = &AArch64::FPR128RegClass;
312           break;
313         default:
314           return true;
315         }
316         return printAsmRegInClass(MO, RC, false /* vector */, O);
317       }
318       printOperand(MI, OpNum, O);
319       return false;
320     }
321   }
322
323   // According to ARM, we should emit x and v registers unless we have a
324   // modifier.
325   if (MO.isReg()) {
326     unsigned Reg = MO.getReg();
327
328     // If this is a w or x register, print an x register.
329     if (AArch64::GPR32allRegClass.contains(Reg) ||
330         AArch64::GPR64allRegClass.contains(Reg))
331       return printAsmMRegister(MO, 'x', O);
332
333     // If this is a b, h, s, d, or q register, print it as a v register.
334     return printAsmRegInClass(MO, &AArch64::FPR128RegClass, true /* vector */,
335                               O);
336   }
337
338   printOperand(MI, OpNum, O);
339   return false;
340 }
341
342 bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
343                                               unsigned OpNum,
344                                               unsigned AsmVariant,
345                                               const char *ExtraCode,
346                                               raw_ostream &O) {
347   if (ExtraCode && ExtraCode[0])
348     return true; // Unknown modifier.
349
350   const MachineOperand &MO = MI->getOperand(OpNum);
351   assert(MO.isReg() && "unexpected inline asm memory operand");
352   O << "[" << AArch64InstPrinter::getRegisterName(MO.getReg()) << "]";
353   return false;
354 }
355
356 void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
357                                                raw_ostream &OS) {
358   unsigned NOps = MI->getNumOperands();
359   assert(NOps == 4);
360   OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
361   // cast away const; DIetc do not take const operands for some reason.
362   DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps - 1).getMetadata()));
363   OS << V.getName();
364   OS << " <- ";
365   // Frame address.  Currently handles register +- offset only.
366   assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
367   OS << '[';
368   printOperand(MI, 0, OS);
369   OS << '+';
370   printOperand(MI, 1, OS);
371   OS << ']';
372   OS << "+";
373   printOperand(MI, NOps - 2, OS);
374 }
375
376 void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
377                                       const MachineInstr &MI) {
378   unsigned NumNOPBytes = MI.getOperand(1).getImm();
379
380   SM.recordStackMap(MI);
381   assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
382
383   // Scan ahead to trim the shadow.
384   const MachineBasicBlock &MBB = *MI.getParent();
385   MachineBasicBlock::const_iterator MII(MI);
386   ++MII;
387   while (NumNOPBytes > 0) {
388     if (MII == MBB.end() || MII->isCall() ||
389         MII->getOpcode() == AArch64::DBG_VALUE ||
390         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
391         MII->getOpcode() == TargetOpcode::STACKMAP)
392       break;
393     ++MII;
394     NumNOPBytes -= 4;
395   }
396
397   // Emit nops.
398   for (unsigned i = 0; i < NumNOPBytes; i += 4)
399     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
400 }
401
402 // Lower a patchpoint of the form:
403 // [<def>], <id>, <numBytes>, <target>, <numArgs>
404 void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
405                                         const MachineInstr &MI) {
406   SM.recordPatchPoint(MI);
407
408   PatchPointOpers Opers(&MI);
409
410   int64_t CallTarget = Opers.getMetaOper(PatchPointOpers::TargetPos).getImm();
411   unsigned EncodedBytes = 0;
412   if (CallTarget) {
413     assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
414            "High 16 bits of call target should be zero.");
415     unsigned ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
416     EncodedBytes = 16;
417     // Materialize the jump address:
418     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVZWi)
419                                     .addReg(ScratchReg)
420                                     .addImm((CallTarget >> 32) & 0xFFFF)
421                                     .addImm(32));
422     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKWi)
423                                     .addReg(ScratchReg)
424                                     .addReg(ScratchReg)
425                                     .addImm((CallTarget >> 16) & 0xFFFF)
426                                     .addImm(16));
427     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKWi)
428                                     .addReg(ScratchReg)
429                                     .addReg(ScratchReg)
430                                     .addImm(CallTarget & 0xFFFF)
431                                     .addImm(0));
432     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
433   }
434   // Emit padding.
435   unsigned NumBytes = Opers.getMetaOper(PatchPointOpers::NBytesPos).getImm();
436   assert(NumBytes >= EncodedBytes &&
437          "Patchpoint can't request size less than the length of a call.");
438   assert((NumBytes - EncodedBytes) % 4 == 0 &&
439          "Invalid number of NOP bytes requested!");
440   for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
441     EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
442 }
443
444 // Simple pseudo-instructions have their lowering (with expansion to real
445 // instructions) auto-generated.
446 #include "AArch64GenMCPseudoLowering.inc"
447
448 void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
449   // Do any auto-generated pseudo lowerings.
450   if (emitPseudoExpansionLowering(OutStreamer, MI))
451     return;
452
453   if (AArch64FI->getLOHRelated().count(MI)) {
454     // Generate a label for LOH related instruction
455     MCSymbol *LOHLabel = GetTempSymbol("loh", LOHLabelCounter++);
456     // Associate the instruction with the label
457     LOHInstToLabel[MI] = LOHLabel;
458     OutStreamer.EmitLabel(LOHLabel);
459   }
460
461   // Do any manual lowerings.
462   switch (MI->getOpcode()) {
463   default:
464     break;
465   case AArch64::DBG_VALUE: {
466     if (isVerbose() && OutStreamer.hasRawTextSupport()) {
467       SmallString<128> TmpStr;
468       raw_svector_ostream OS(TmpStr);
469       PrintDebugValueComment(MI, OS);
470       OutStreamer.EmitRawText(StringRef(OS.str()));
471     }
472     return;
473   }
474
475   // Tail calls use pseudo instructions so they have the proper code-gen
476   // attributes (isCall, isReturn, etc.). We lower them to the real
477   // instruction here.
478   case AArch64::TCRETURNri: {
479     MCInst TmpInst;
480     TmpInst.setOpcode(AArch64::BR);
481     TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
482     EmitToStreamer(OutStreamer, TmpInst);
483     return;
484   }
485   case AArch64::TCRETURNdi: {
486     MCOperand Dest;
487     MCInstLowering.lowerOperand(MI->getOperand(0), Dest);
488     MCInst TmpInst;
489     TmpInst.setOpcode(AArch64::B);
490     TmpInst.addOperand(Dest);
491     EmitToStreamer(OutStreamer, TmpInst);
492     return;
493   }
494   case AArch64::TLSDESC_CALLSEQ: {
495     /// lower this to:
496     ///    adrp  x0, :tlsdesc:var
497     ///    ldr   x1, [x0, #:tlsdesc_lo12:var]
498     ///    add   x0, x0, #:tlsdesc_lo12:var
499     ///    .tlsdesccall var
500     ///    blr   x1
501     ///    (TPIDR_EL0 offset now in x0)
502     const MachineOperand &MO_Sym = MI->getOperand(0);
503     MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
504     MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
505     MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF |
506                                    AArch64II::MO_NC);
507     MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE);
508     MCInstLowering.lowerOperand(MO_Sym, Sym);
509     MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
510     MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
511
512     MCInst Adrp;
513     Adrp.setOpcode(AArch64::ADRP);
514     Adrp.addOperand(MCOperand::CreateReg(AArch64::X0));
515     Adrp.addOperand(SymTLSDesc);
516     EmitToStreamer(OutStreamer, Adrp);
517
518     MCInst Ldr;
519     Ldr.setOpcode(AArch64::LDRXui);
520     Ldr.addOperand(MCOperand::CreateReg(AArch64::X1));
521     Ldr.addOperand(MCOperand::CreateReg(AArch64::X0));
522     Ldr.addOperand(SymTLSDescLo12);
523     Ldr.addOperand(MCOperand::CreateImm(0));
524     EmitToStreamer(OutStreamer, Ldr);
525
526     MCInst Add;
527     Add.setOpcode(AArch64::ADDXri);
528     Add.addOperand(MCOperand::CreateReg(AArch64::X0));
529     Add.addOperand(MCOperand::CreateReg(AArch64::X0));
530     Add.addOperand(SymTLSDescLo12);
531     Add.addOperand(MCOperand::CreateImm(AArch64_AM::getShiftValue(0)));
532     EmitToStreamer(OutStreamer, Add);
533
534     // Emit a relocation-annotation. This expands to no code, but requests
535     // the following instruction gets an R_AARCH64_TLSDESC_CALL.
536     MCInst TLSDescCall;
537     TLSDescCall.setOpcode(AArch64::TLSDESCCALL);
538     TLSDescCall.addOperand(Sym);
539     EmitToStreamer(OutStreamer, TLSDescCall);
540
541     MCInst Blr;
542     Blr.setOpcode(AArch64::BLR);
543     Blr.addOperand(MCOperand::CreateReg(AArch64::X1));
544     EmitToStreamer(OutStreamer, Blr);
545
546     return;
547   }
548
549   case TargetOpcode::STACKMAP:
550     return LowerSTACKMAP(OutStreamer, SM, *MI);
551
552   case TargetOpcode::PATCHPOINT:
553     return LowerPATCHPOINT(OutStreamer, SM, *MI);
554   }
555
556   // Finally, do the automated lowerings for everything else.
557   MCInst TmpInst;
558   MCInstLowering.Lower(MI, TmpInst);
559   EmitToStreamer(OutStreamer, TmpInst);
560 }
561
562 // Force static initialization.
563 extern "C" void LLVMInitializeAArch64AsmPrinter() {
564   RegisterAsmPrinter<AArch64AsmPrinter> X(TheAArch64leTarget);
565   RegisterAsmPrinter<AArch64AsmPrinter> Y(TheAArch64beTarget);
566   RegisterAsmPrinter<AArch64AsmPrinter> Z(TheARM64Target);
567 }