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