LLVM  10.0.0svn
AArch64AsmPrinter.cpp
Go to the documentation of this file.
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"
17 #include "AArch64RegisterInfo.h"
18 #include "AArch64Subtarget.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"
41 #include "llvm/CodeGen/StackMaps.h"
43 #include "llvm/IR/DataLayout.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"
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 EmitJumpTableInfo() override;
88  void emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
89  const MachineBasicBlock *MBB, unsigned JTI);
90 
91  void LowerJumpTableDestSmall(MCStreamer &OutStreamer, const MachineInstr &MI);
92 
93  void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
94  const MachineInstr &MI);
95  void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
96  const MachineInstr &MI);
97 
98  void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
99  void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
100  void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
101 
102  std::map<std::pair<unsigned, uint32_t>, MCSymbol *> HwasanMemaccessSymbols;
103  void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
104  void EmitHwasanMemaccessSymbols(Module &M);
105 
106  void EmitSled(const MachineInstr &MI, SledKind Kind);
107 
108  /// tblgen'erated driver function for lowering simple MI->MC
109  /// pseudo instructions.
110  bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
111  const MachineInstr *MI);
112 
113  void EmitInstruction(const MachineInstr *MI) override;
114 
115  void getAnalysisUsage(AnalysisUsage &AU) const override {
117  AU.setPreservesAll();
118  }
119 
120  bool runOnMachineFunction(MachineFunction &MF) override {
121  AArch64FI = MF.getInfo<AArch64FunctionInfo>();
122  STI = static_cast<const AArch64Subtarget*>(&MF.getSubtarget());
123 
124  SetupMachineFunction(MF);
125 
126  if (STI->isTargetCOFF()) {
127  bool Internal = MF.getFunction().hasInternalLinkage();
130  int Type =
132 
133  OutStreamer->BeginCOFFSymbolDef(CurrentFnSym);
134  OutStreamer->EmitCOFFSymbolStorageClass(Scl);
135  OutStreamer->EmitCOFFSymbolType(Type);
136  OutStreamer->EndCOFFSymbolDef();
137  }
138 
139  // Emit the rest of the function body.
140  EmitFunctionBody();
141 
142  // Emit the XRay table for this function.
143  emitXRayTable();
144 
145  // We didn't modify anything.
146  return false;
147  }
148 
149 private:
150  void printOperand(const MachineInstr *MI, unsigned OpNum, raw_ostream &O);
151  bool printAsmMRegister(const MachineOperand &MO, char Mode, raw_ostream &O);
152  bool printAsmRegInClass(const MachineOperand &MO,
153  const TargetRegisterClass *RC, unsigned AltName,
154  raw_ostream &O);
155 
156  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
157  const char *ExtraCode, raw_ostream &O) override;
158  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
159  const char *ExtraCode, raw_ostream &O) override;
160 
161  void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
162 
163  void EmitFunctionBodyEnd() override;
164 
165  MCSymbol *GetCPISymbol(unsigned CPID) const override;
166  void EmitEndOfAsmFile(Module &M) override;
167 
168  AArch64FunctionInfo *AArch64FI = nullptr;
169 
170  /// Emit the LOHs contained in AArch64FI.
171  void EmitLOHs();
172 
173  /// Emit instruction to set float register to zero.
174  void EmitFMov0(const MachineInstr &MI);
175 
176  using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
177 
178  MInstToMCSymbol LOHInstToLabel;
179 };
180 
181 } // end anonymous namespace
182 
183 void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
184 {
185  EmitSled(MI, SledKind::FUNCTION_ENTER);
186 }
187 
188 void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
189 {
190  EmitSled(MI, SledKind::FUNCTION_EXIT);
191 }
192 
193 void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
194 {
195  EmitSled(MI, SledKind::TAIL_CALL);
196 }
197 
198 void AArch64AsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
199 {
200  static const int8_t NoopsInSledCount = 7;
201  // We want to emit the following pattern:
202  //
203  // .Lxray_sled_N:
204  // ALIGN
205  // B #32
206  // ; 7 NOP instructions (28 bytes)
207  // .tmpN
208  //
209  // We need the 28 bytes (7 instructions) because at runtime, we'd be patching
210  // over the full 32 bytes (8 instructions) with the following pattern:
211  //
212  // STP X0, X30, [SP, #-16]! ; push X0 and the link register to the stack
213  // LDR W0, #12 ; W0 := function ID
214  // LDR X16,#12 ; X16 := addr of __xray_FunctionEntry or __xray_FunctionExit
215  // BLR X16 ; call the tracing trampoline
216  // ;DATA: 32 bits of function ID
217  // ;DATA: lower 32 bits of the address of the trampoline
218  // ;DATA: higher 32 bits of the address of the trampoline
219  // LDP X0, X30, [SP], #16 ; pop X0 and the link register from the stack
220  //
221  OutStreamer->EmitCodeAlignment(4);
222  auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
223  OutStreamer->EmitLabel(CurSled);
224  auto Target = OutContext.createTempSymbol();
225 
226  // Emit "B #32" instruction, which jumps over the next 28 bytes.
227  // The operand has to be the number of 4-byte instructions to jump over,
228  // including the current instruction.
229  EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
230 
231  for (int8_t I = 0; I < NoopsInSledCount; I++)
232  EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
233 
234  OutStreamer->EmitLabel(Target);
235  recordSled(CurSled, MI, Kind);
236 }
237 
238 void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
239  Register Reg = MI.getOperand(0).getReg();
240  uint32_t AccessInfo = MI.getOperand(1).getImm();
241  MCSymbol *&Sym = HwasanMemaccessSymbols[{Reg, AccessInfo}];
242  if (!Sym) {
243  // FIXME: Make this work on non-ELF.
244  if (!TM.getTargetTriple().isOSBinFormatELF())
245  report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
246 
247  std::string SymName = "__hwasan_check_x" + utostr(Reg - AArch64::X0) + "_" +
248  utostr(AccessInfo);
249  Sym = OutContext.getOrCreateSymbol(SymName);
250  }
251 
252  EmitToStreamer(*OutStreamer,
254  .addExpr(MCSymbolRefExpr::create(Sym, OutContext)));
255 }
256 
257 void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
258  if (HwasanMemaccessSymbols.empty())
259  return;
260 
261  const Triple &TT = TM.getTargetTriple();
262  assert(TT.isOSBinFormatELF());
263  std::unique_ptr<MCSubtargetInfo> STI(
264  TM.getTarget().createMCSubtargetInfo(TT.str(), "", ""));
265 
266  MCSymbol *HwasanTagMismatchSym =
267  OutContext.getOrCreateSymbol("__hwasan_tag_mismatch");
268 
269  const MCSymbolRefExpr *HwasanTagMismatchRef =
270  MCSymbolRefExpr::create(HwasanTagMismatchSym, OutContext);
271 
272  for (auto &P : HwasanMemaccessSymbols) {
273  unsigned Reg = P.first.first;
274  uint32_t AccessInfo = P.first.second;
275  MCSymbol *Sym = P.second;
276 
277  OutStreamer->SwitchSection(OutContext.getELFSection(
278  ".text.hot", ELF::SHT_PROGBITS,
280  Sym->getName()));
281 
282  OutStreamer->EmitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
283  OutStreamer->EmitSymbolAttribute(Sym, MCSA_Weak);
284  OutStreamer->EmitSymbolAttribute(Sym, MCSA_Hidden);
285  OutStreamer->EmitLabel(Sym);
286 
287  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::UBFMXri)
288  .addReg(AArch64::X16)
289  .addReg(Reg)
290  .addImm(4)
291  .addImm(55),
292  *STI);
293  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::LDRBBroX)
294  .addReg(AArch64::W16)
295  .addReg(AArch64::X9)
296  .addReg(AArch64::X16)
297  .addImm(0)
298  .addImm(0),
299  *STI);
300  OutStreamer->EmitInstruction(
301  MCInstBuilder(AArch64::SUBSXrs)
302  .addReg(AArch64::XZR)
303  .addReg(AArch64::X16)
304  .addReg(Reg)
306  *STI);
307  MCSymbol *HandlePartialSym = OutContext.createTempSymbol();
308  OutStreamer->EmitInstruction(
309  MCInstBuilder(AArch64::Bcc)
310  .addImm(AArch64CC::NE)
311  .addExpr(MCSymbolRefExpr::create(HandlePartialSym, OutContext)),
312  *STI);
313  MCSymbol *ReturnSym = OutContext.createTempSymbol();
314  OutStreamer->EmitLabel(ReturnSym);
315  OutStreamer->EmitInstruction(
316  MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
317 
318  OutStreamer->EmitLabel(HandlePartialSym);
319  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::SUBSWri)
320  .addReg(AArch64::WZR)
321  .addReg(AArch64::W16)
322  .addImm(15)
323  .addImm(0),
324  *STI);
325  MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
326  OutStreamer->EmitInstruction(
327  MCInstBuilder(AArch64::Bcc)
328  .addImm(AArch64CC::HI)
329  .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
330  *STI);
331 
332  OutStreamer->EmitInstruction(
333  MCInstBuilder(AArch64::ANDXri)
334  .addReg(AArch64::X17)
335  .addReg(Reg)
336  .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)),
337  *STI);
338  unsigned Size = 1 << (AccessInfo & 0xf);
339  if (Size != 1)
340  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::ADDXri)
341  .addReg(AArch64::X17)
342  .addReg(AArch64::X17)
343  .addImm(Size - 1)
344  .addImm(0),
345  *STI);
346  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::SUBSWrs)
347  .addReg(AArch64::WZR)
348  .addReg(AArch64::W16)
349  .addReg(AArch64::W17)
350  .addImm(0),
351  *STI);
352  OutStreamer->EmitInstruction(
353  MCInstBuilder(AArch64::Bcc)
354  .addImm(AArch64CC::LS)
355  .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
356  *STI);
357 
358  OutStreamer->EmitInstruction(
359  MCInstBuilder(AArch64::ORRXri)
360  .addReg(AArch64::X16)
361  .addReg(Reg)
362  .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)),
363  *STI);
364  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::LDRBBui)
365  .addReg(AArch64::W16)
366  .addReg(AArch64::X16)
367  .addImm(0),
368  *STI);
369  OutStreamer->EmitInstruction(
370  MCInstBuilder(AArch64::SUBSXrs)
371  .addReg(AArch64::XZR)
372  .addReg(AArch64::X16)
373  .addReg(Reg)
375  *STI);
376  OutStreamer->EmitInstruction(
377  MCInstBuilder(AArch64::Bcc)
378  .addImm(AArch64CC::EQ)
379  .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
380  *STI);
381 
382  OutStreamer->EmitLabel(HandleMismatchSym);
383  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::STPXpre)
384  .addReg(AArch64::SP)
385  .addReg(AArch64::X0)
386  .addReg(AArch64::X1)
387  .addReg(AArch64::SP)
388  .addImm(-32),
389  *STI);
390  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::STPXi)
391  .addReg(AArch64::FP)
392  .addReg(AArch64::LR)
393  .addReg(AArch64::SP)
394  .addImm(29),
395  *STI);
396 
397  if (Reg != AArch64::X0)
398  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::ORRXrs)
399  .addReg(AArch64::X0)
400  .addReg(AArch64::XZR)
401  .addReg(Reg)
402  .addImm(0),
403  *STI);
404  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::MOVZXi)
405  .addReg(AArch64::X1)
406  .addImm(AccessInfo)
407  .addImm(0),
408  *STI);
409 
410  // Intentionally load the GOT entry and branch to it, rather than possibly
411  // late binding the function, which may clobber the registers before we have
412  // a chance to save them.
413  OutStreamer->EmitInstruction(
415  .addReg(AArch64::X16)
416  .addExpr(AArch64MCExpr::create(
417  HwasanTagMismatchRef,
418  AArch64MCExpr::VariantKind::VK_GOT_PAGE, OutContext)),
419  *STI);
420  OutStreamer->EmitInstruction(
421  MCInstBuilder(AArch64::LDRXui)
422  .addReg(AArch64::X16)
423  .addReg(AArch64::X16)
424  .addExpr(AArch64MCExpr::create(
425  HwasanTagMismatchRef,
426  AArch64MCExpr::VariantKind::VK_GOT_LO12, OutContext)),
427  *STI);
428  OutStreamer->EmitInstruction(
429  MCInstBuilder(AArch64::BR).addReg(AArch64::X16), *STI);
430  }
431 }
432 
433 void AArch64AsmPrinter::EmitEndOfAsmFile(Module &M) {
434  EmitHwasanMemaccessSymbols(M);
435 
436  const Triple &TT = TM.getTargetTriple();
437  if (TT.isOSBinFormatMachO()) {
438  // Funny Darwin hack: This flag tells the linker that no global symbols
439  // contain code that falls through to other global symbols (e.g. the obvious
440  // implementation of multiple entry points). If this doesn't occur, the
441  // linker can safely perform dead code stripping. Since LLVM never
442  // generates code that does this, it is always safe to set.
443  OutStreamer->EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
444  emitStackMaps(SM);
445  }
446 }
447 
448 void AArch64AsmPrinter::EmitLOHs() {
450 
451  for (const auto &D : AArch64FI->getLOHContainer()) {
452  for (const MachineInstr *MI : D.getArgs()) {
453  MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(MI);
454  assert(LabelIt != LOHInstToLabel.end() &&
455  "Label hasn't been inserted for LOH related instruction");
456  MCArgs.push_back(LabelIt->second);
457  }
458  OutStreamer->EmitLOHDirective(D.getKind(), MCArgs);
459  MCArgs.clear();
460  }
461 }
462 
463 void AArch64AsmPrinter::EmitFunctionBodyEnd() {
464  if (!AArch64FI->getLOHRelated().empty())
465  EmitLOHs();
466 }
467 
468 /// GetCPISymbol - Return the symbol for the specified constant pool entry.
469 MCSymbol *AArch64AsmPrinter::GetCPISymbol(unsigned CPID) const {
470  // Darwin uses a linker-private symbol name for constant-pools (to
471  // avoid addends on the relocation?), ELF has no such concept and
472  // uses a normal private symbol.
473  if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
474  return OutContext.getOrCreateSymbol(
475  Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) + "CPI" +
476  Twine(getFunctionNumber()) + "_" + Twine(CPID));
477 
478  return AsmPrinter::GetCPISymbol(CPID);
479 }
480 
481 void AArch64AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNum,
482  raw_ostream &O) {
483  const MachineOperand &MO = MI->getOperand(OpNum);
484  switch (MO.getType()) {
485  default:
486  llvm_unreachable("<unknown operand type>");
488  Register Reg = MO.getReg();
490  assert(!MO.getSubReg() && "Subregs should be eliminated!");
492  break;
493  }
495  O << MO.getImm();
496  break;
497  }
499  PrintSymbolOperand(MO, O);
500  break;
501  }
503  MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
504  Sym->print(O, MAI);
505  break;
506  }
507  }
508 }
509 
511  raw_ostream &O) {
512  Register Reg = MO.getReg();
513  switch (Mode) {
514  default:
515  return true; // Unknown mode.
516  case 'w':
517  Reg = getWRegFromXReg(Reg);
518  break;
519  case 'x':
520  Reg = getXRegFromWReg(Reg);
521  break;
522  }
523 
525  return false;
526 }
527 
528 // Prints the register in MO using class RC using the offset in the
529 // new register class. This should not be used for cross class
530 // printing.
531 bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO,
532  const TargetRegisterClass *RC,
533  unsigned AltName, raw_ostream &O) {
534  assert(MO.isReg() && "Should only get here with a register!");
535  const TargetRegisterInfo *RI = STI->getRegisterInfo();
536  Register Reg = MO.getReg();
537  unsigned RegToPrint = RC->getRegister(RI->getEncodingValue(Reg));
538  assert(RI->regsOverlap(RegToPrint, Reg));
539  O << AArch64InstPrinter::getRegisterName(RegToPrint, AltName);
540  return false;
541 }
542 
543 bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
544  const char *ExtraCode, raw_ostream &O) {
545  const MachineOperand &MO = MI->getOperand(OpNum);
546 
547  // First try the generic code, which knows about modifiers like 'c' and 'n'.
548  if (!AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O))
549  return false;
550 
551  // Does this asm operand have a single letter operand modifier?
552  if (ExtraCode && ExtraCode[0]) {
553  if (ExtraCode[1] != 0)
554  return true; // Unknown modifier.
555 
556  switch (ExtraCode[0]) {
557  default:
558  return true; // Unknown modifier.
559  case 'w': // Print W register
560  case 'x': // Print X register
561  if (MO.isReg())
562  return printAsmMRegister(MO, ExtraCode[0], O);
563  if (MO.isImm() && MO.getImm() == 0) {
564  unsigned Reg = ExtraCode[0] == 'w' ? AArch64::WZR : AArch64::XZR;
566  return false;
567  }
568  printOperand(MI, OpNum, O);
569  return false;
570  case 'b': // Print B register.
571  case 'h': // Print H register.
572  case 's': // Print S register.
573  case 'd': // Print D register.
574  case 'q': // Print Q register.
575  case 'z': // Print Z register.
576  if (MO.isReg()) {
577  const TargetRegisterClass *RC;
578  switch (ExtraCode[0]) {
579  case 'b':
580  RC = &AArch64::FPR8RegClass;
581  break;
582  case 'h':
583  RC = &AArch64::FPR16RegClass;
584  break;
585  case 's':
586  RC = &AArch64::FPR32RegClass;
587  break;
588  case 'd':
589  RC = &AArch64::FPR64RegClass;
590  break;
591  case 'q':
592  RC = &AArch64::FPR128RegClass;
593  break;
594  case 'z':
595  RC = &AArch64::ZPRRegClass;
596  break;
597  default:
598  return true;
599  }
600  return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
601  }
602  printOperand(MI, OpNum, O);
603  return false;
604  }
605  }
606 
607  // According to ARM, we should emit x and v registers unless we have a
608  // modifier.
609  if (MO.isReg()) {
610  Register Reg = MO.getReg();
611 
612  // If this is a w or x register, print an x register.
613  if (AArch64::GPR32allRegClass.contains(Reg) ||
614  AArch64::GPR64allRegClass.contains(Reg))
615  return printAsmMRegister(MO, 'x', O);
616 
617  unsigned AltName = AArch64::NoRegAltName;
618  const TargetRegisterClass *RegClass;
619  if (AArch64::ZPRRegClass.contains(Reg)) {
620  RegClass = &AArch64::ZPRRegClass;
621  } else {
622  RegClass = &AArch64::FPR128RegClass;
623  AltName = AArch64::vreg;
624  }
625 
626  // If this is a b, h, s, d, or q register, print it as a v register.
627  return printAsmRegInClass(MO, RegClass, AltName, O);
628  }
629 
630  printOperand(MI, OpNum, O);
631  return false;
632 }
633 
634 bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
635  unsigned OpNum,
636  const char *ExtraCode,
637  raw_ostream &O) {
638  if (ExtraCode && ExtraCode[0] && ExtraCode[0] != 'a')
639  return true; // Unknown modifier.
640 
641  const MachineOperand &MO = MI->getOperand(OpNum);
642  assert(MO.isReg() && "unexpected inline asm memory operand");
643  O << "[" << AArch64InstPrinter::getRegisterName(MO.getReg()) << "]";
644  return false;
645 }
646 
647 void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
648  raw_ostream &OS) {
649  unsigned NOps = MI->getNumOperands();
650  assert(NOps == 4);
651  OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
652  // cast away const; DIetc do not take const operands for some reason.
653  OS << cast<DILocalVariable>(MI->getOperand(NOps - 2).getMetadata())
654  ->getName();
655  OS << " <- ";
656  // Frame address. Currently handles register +- offset only.
657  assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
658  OS << '[';
659  printOperand(MI, 0, OS);
660  OS << '+';
661  printOperand(MI, 1, OS);
662  OS << ']';
663  OS << "+";
664  printOperand(MI, NOps - 2, OS);
665 }
666 
667 void AArch64AsmPrinter::EmitJumpTableInfo() {
668  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
669  if (!MJTI) return;
670 
671  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
672  if (JT.empty()) return;
673 
674  const Function &F = MF->getFunction();
675  const TargetLoweringObjectFile &TLOF = getObjFileLowering();
676  bool JTInDiffSection =
677  !STI->isTargetCOFF() ||
680  F);
681  if (JTInDiffSection) {
682  // Drop it in the readonly section.
683  MCSection *ReadOnlySec = TLOF.getSectionForJumpTable(F, TM);
684  OutStreamer->SwitchSection(ReadOnlySec);
685  }
686 
687  auto AFI = MF->getInfo<AArch64FunctionInfo>();
688  for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
689  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
690 
691  // If this jump table was deleted, ignore it.
692  if (JTBBs.empty()) continue;
693 
694  unsigned Size = AFI->getJumpTableEntrySize(JTI);
695  EmitAlignment(llvm::Align(Size));
696  OutStreamer->EmitLabel(GetJTISymbol(JTI));
697 
698  for (auto *JTBB : JTBBs)
699  emitJumpTableEntry(MJTI, JTBB, JTI);
700  }
701 }
702 
703 void AArch64AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
704  const MachineBasicBlock *MBB,
705  unsigned JTI) {
706  const MCExpr *Value = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
707  auto AFI = MF->getInfo<AArch64FunctionInfo>();
708  unsigned Size = AFI->getJumpTableEntrySize(JTI);
709 
710  if (Size == 4) {
711  // .word LBB - LJTI
712  const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
713  const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF, JTI, OutContext);
714  Value = MCBinaryExpr::createSub(Value, Base, OutContext);
715  } else {
716  // .byte (LBB - LBB) >> 2 (or .hword)
717  const MCSymbol *BaseSym = AFI->getJumpTableEntryPCRelSymbol(JTI);
718  const MCExpr *Base = MCSymbolRefExpr::create(BaseSym, OutContext);
719  Value = MCBinaryExpr::createSub(Value, Base, OutContext);
720  Value = MCBinaryExpr::createLShr(
721  Value, MCConstantExpr::create(2, OutContext), OutContext);
722  }
723 
724  OutStreamer->EmitValue(Value, Size);
725 }
726 
727 /// Small jump tables contain an unsigned byte or half, representing the offset
728 /// from the lowest-addressed possible destination to the desired basic
729 /// block. Since all instructions are 4-byte aligned, this is further compressed
730 /// by counting in instructions rather than bytes (i.e. divided by 4). So, to
731 /// materialize the correct destination we need:
732 ///
733 /// adr xDest, .LBB0_0
734 /// ldrb wScratch, [xTable, xEntry] (with "lsl #1" for ldrh).
735 /// add xDest, xDest, xScratch, lsl #2
736 void AArch64AsmPrinter::LowerJumpTableDestSmall(llvm::MCStreamer &OutStreamer,
737  const llvm::MachineInstr &MI) {
738  Register DestReg = MI.getOperand(0).getReg();
739  Register ScratchReg = MI.getOperand(1).getReg();
740  Register ScratchRegW =
741  STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
742  Register TableReg = MI.getOperand(2).getReg();
743  Register EntryReg = MI.getOperand(3).getReg();
744  int JTIdx = MI.getOperand(4).getIndex();
745  bool IsByteEntry = MI.getOpcode() == AArch64::JumpTableDest8;
746 
747  // This has to be first because the compression pass based its reachability
748  // calculations on the start of the JumpTableDest instruction.
749  auto Label =
750  MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
751  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
752  .addReg(DestReg)
753  .addExpr(MCSymbolRefExpr::create(
754  Label, MF->getContext())));
755 
756  // Load the number of instruction-steps to offset from the label.
757  unsigned LdrOpcode = IsByteEntry ? AArch64::LDRBBroX : AArch64::LDRHHroX;
758  EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
759  .addReg(ScratchRegW)
760  .addReg(TableReg)
761  .addReg(EntryReg)
762  .addImm(0)
763  .addImm(IsByteEntry ? 0 : 1));
764 
765  // Multiply the steps by 4 and add to the already materialized base label
766  // address.
767  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
768  .addReg(DestReg)
769  .addReg(DestReg)
770  .addReg(ScratchReg)
771  .addImm(2));
772 }
773 
774 void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
775  const MachineInstr &MI) {
776  unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
777 
778  SM.recordStackMap(MI);
779  assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
780 
781  // Scan ahead to trim the shadow.
782  const MachineBasicBlock &MBB = *MI.getParent();
784  ++MII;
785  while (NumNOPBytes > 0) {
786  if (MII == MBB.end() || MII->isCall() ||
787  MII->getOpcode() == AArch64::DBG_VALUE ||
788  MII->getOpcode() == TargetOpcode::PATCHPOINT ||
789  MII->getOpcode() == TargetOpcode::STACKMAP)
790  break;
791  ++MII;
792  NumNOPBytes -= 4;
793  }
794 
795  // Emit nops.
796  for (unsigned i = 0; i < NumNOPBytes; i += 4)
797  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
798 }
799 
800 // Lower a patchpoint of the form:
801 // [<def>], <id>, <numBytes>, <target>, <numArgs>
802 void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
803  const MachineInstr &MI) {
804  SM.recordPatchPoint(MI);
805 
806  PatchPointOpers Opers(&MI);
807 
808  int64_t CallTarget = Opers.getCallTarget().getImm();
809  unsigned EncodedBytes = 0;
810  if (CallTarget) {
811  assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
812  "High 16 bits of call target should be zero.");
813  Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
814  EncodedBytes = 16;
815  // Materialize the jump address:
816  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVZXi)
817  .addReg(ScratchReg)
818  .addImm((CallTarget >> 32) & 0xFFFF)
819  .addImm(32));
820  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
821  .addReg(ScratchReg)
822  .addReg(ScratchReg)
823  .addImm((CallTarget >> 16) & 0xFFFF)
824  .addImm(16));
825  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
826  .addReg(ScratchReg)
827  .addReg(ScratchReg)
828  .addImm(CallTarget & 0xFFFF)
829  .addImm(0));
830  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
831  }
832  // Emit padding.
833  unsigned NumBytes = Opers.getNumPatchBytes();
834  assert(NumBytes >= EncodedBytes &&
835  "Patchpoint can't request size less than the length of a call.");
836  assert((NumBytes - EncodedBytes) % 4 == 0 &&
837  "Invalid number of NOP bytes requested!");
838  for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
839  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
840 }
841 
842 void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) {
843  Register DestReg = MI.getOperand(0).getReg();
844  if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) {
845  // Convert H/S/D register to corresponding Q register
846  if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
847  DestReg = AArch64::Q0 + (DestReg - AArch64::H0);
848  else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
849  DestReg = AArch64::Q0 + (DestReg - AArch64::S0);
850  else {
851  assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
852  DestReg = AArch64::Q0 + (DestReg - AArch64::D0);
853  }
854  MCInst MOVI;
855  MOVI.setOpcode(AArch64::MOVIv2d_ns);
856  MOVI.addOperand(MCOperand::createReg(DestReg));
857  MOVI.addOperand(MCOperand::createImm(0));
858  EmitToStreamer(*OutStreamer, MOVI);
859  } else {
860  MCInst FMov;
861  switch (MI.getOpcode()) {
862  default: llvm_unreachable("Unexpected opcode");
863  case AArch64::FMOVH0:
864  FMov.setOpcode(AArch64::FMOVWHr);
865  FMov.addOperand(MCOperand::createReg(DestReg));
866  FMov.addOperand(MCOperand::createReg(AArch64::WZR));
867  break;
868  case AArch64::FMOVS0:
869  FMov.setOpcode(AArch64::FMOVWSr);
870  FMov.addOperand(MCOperand::createReg(DestReg));
871  FMov.addOperand(MCOperand::createReg(AArch64::WZR));
872  break;
873  case AArch64::FMOVD0:
874  FMov.setOpcode(AArch64::FMOVXDr);
875  FMov.addOperand(MCOperand::createReg(DestReg));
876  FMov.addOperand(MCOperand::createReg(AArch64::XZR));
877  break;
878  }
879  EmitToStreamer(*OutStreamer, FMov);
880  }
881 }
882 
883 // Simple pseudo-instructions have their lowering (with expansion to real
884 // instructions) auto-generated.
885 #include "AArch64GenMCPseudoLowering.inc"
886 
887 void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
888  // Do any auto-generated pseudo lowerings.
889  if (emitPseudoExpansionLowering(*OutStreamer, MI))
890  return;
891 
892  if (AArch64FI->getLOHRelated().count(MI)) {
893  // Generate a label for LOH related instruction
894  MCSymbol *LOHLabel = createTempSymbol("loh");
895  // Associate the instruction with the label
896  LOHInstToLabel[MI] = LOHLabel;
897  OutStreamer->EmitLabel(LOHLabel);
898  }
899 
901  static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
902  // Do any manual lowerings.
903  switch (MI->getOpcode()) {
904  default:
905  break;
906  case AArch64::MOVMCSym: {
907  Register DestReg = MI->getOperand(0).getReg();
908  const MachineOperand &MO_Sym = MI->getOperand(1);
909  MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
910  MCOperand Hi_MCSym, Lo_MCSym;
911 
912  Hi_MOSym.setTargetFlags(AArch64II::MO_G1 | AArch64II::MO_S);
914 
915  MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
916  MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
917 
918  MCInst MovZ;
919  MovZ.setOpcode(AArch64::MOVZXi);
920  MovZ.addOperand(MCOperand::createReg(DestReg));
921  MovZ.addOperand(Hi_MCSym);
923  EmitToStreamer(*OutStreamer, MovZ);
924 
925  MCInst MovK;
926  MovK.setOpcode(AArch64::MOVKXi);
927  MovK.addOperand(MCOperand::createReg(DestReg));
928  MovK.addOperand(MCOperand::createReg(DestReg));
929  MovK.addOperand(Lo_MCSym);
931  EmitToStreamer(*OutStreamer, MovK);
932  return;
933  }
934  case AArch64::MOVIv2d_ns:
935  // If the target has <rdar://problem/16473581>, lower this
936  // instruction to movi.16b instead.
937  if (STI->hasZeroCycleZeroingFPWorkaround() &&
938  MI->getOperand(1).getImm() == 0) {
939  MCInst TmpInst;
940  TmpInst.setOpcode(AArch64::MOVIv16b_ns);
943  EmitToStreamer(*OutStreamer, TmpInst);
944  return;
945  }
946  break;
947 
948  case AArch64::DBG_VALUE: {
949  if (isVerbose() && OutStreamer->hasRawTextSupport()) {
950  SmallString<128> TmpStr;
951  raw_svector_ostream OS(TmpStr);
952  PrintDebugValueComment(MI, OS);
953  OutStreamer->EmitRawText(StringRef(OS.str()));
954  }
955  return;
956 
957  case AArch64::EMITBKEY: {
958  ExceptionHandling ExceptionHandlingType = MAI->getExceptionHandlingType();
959  if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
960  ExceptionHandlingType != ExceptionHandling::ARM)
961  return;
962 
963  if (needsCFIMoves() == CFI_M_None)
964  return;
965 
966  OutStreamer->EmitCFIBKeyFrame();
967  return;
968  }
969  }
970 
971  // Tail calls use pseudo instructions so they have the proper code-gen
972  // attributes (isCall, isReturn, etc.). We lower them to the real
973  // instruction here.
974  case AArch64::TCRETURNri:
975  case AArch64::TCRETURNriBTI:
976  case AArch64::TCRETURNriALL: {
977  MCInst TmpInst;
978  TmpInst.setOpcode(AArch64::BR);
980  EmitToStreamer(*OutStreamer, TmpInst);
981  return;
982  }
983  case AArch64::TCRETURNdi: {
984  MCOperand Dest;
985  MCInstLowering.lowerOperand(MI->getOperand(0), Dest);
986  MCInst TmpInst;
987  TmpInst.setOpcode(AArch64::B);
988  TmpInst.addOperand(Dest);
989  EmitToStreamer(*OutStreamer, TmpInst);
990  return;
991  }
993  /// lower this to:
994  /// adrp x0, :tlsdesc:var
995  /// ldr x1, [x0, #:tlsdesc_lo12:var]
996  /// add x0, x0, #:tlsdesc_lo12:var
997  /// .tlsdesccall var
998  /// blr x1
999  /// (TPIDR_EL0 offset now in x0)
1000  const MachineOperand &MO_Sym = MI->getOperand(0);
1001  MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
1002  MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
1003  MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
1005  MCInstLowering.lowerOperand(MO_Sym, Sym);
1006  MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
1007  MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
1008 
1009  MCInst Adrp;
1010  Adrp.setOpcode(AArch64::ADRP);
1011  Adrp.addOperand(MCOperand::createReg(AArch64::X0));
1012  Adrp.addOperand(SymTLSDesc);
1013  EmitToStreamer(*OutStreamer, Adrp);
1014 
1015  MCInst Ldr;
1016  Ldr.setOpcode(AArch64::LDRXui);
1017  Ldr.addOperand(MCOperand::createReg(AArch64::X1));
1018  Ldr.addOperand(MCOperand::createReg(AArch64::X0));
1019  Ldr.addOperand(SymTLSDescLo12);
1021  EmitToStreamer(*OutStreamer, Ldr);
1022 
1023  MCInst Add;
1024  Add.setOpcode(AArch64::ADDXri);
1025  Add.addOperand(MCOperand::createReg(AArch64::X0));
1026  Add.addOperand(MCOperand::createReg(AArch64::X0));
1027  Add.addOperand(SymTLSDescLo12);
1029  EmitToStreamer(*OutStreamer, Add);
1030 
1031  // Emit a relocation-annotation. This expands to no code, but requests
1032  // the following instruction gets an R_AARCH64_TLSDESC_CALL.
1033  MCInst TLSDescCall;
1034  TLSDescCall.setOpcode(AArch64::TLSDESCCALL);
1035  TLSDescCall.addOperand(Sym);
1036  EmitToStreamer(*OutStreamer, TLSDescCall);
1037 
1038  MCInst Blr;
1039  Blr.setOpcode(AArch64::BLR);
1040  Blr.addOperand(MCOperand::createReg(AArch64::X1));
1041  EmitToStreamer(*OutStreamer, Blr);
1042 
1043  return;
1044  }
1045 
1046  case AArch64::JumpTableDest32: {
1047  // We want:
1048  // ldrsw xScratch, [xTable, xEntry, lsl #2]
1049  // add xDest, xTable, xScratch
1050  unsigned DestReg = MI->getOperand(0).getReg(),
1051  ScratchReg = MI->getOperand(1).getReg(),
1052  TableReg = MI->getOperand(2).getReg(),
1053  EntryReg = MI->getOperand(3).getReg();
1054  EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1055  .addReg(ScratchReg)
1056  .addReg(TableReg)
1057  .addReg(EntryReg)
1058  .addImm(0)
1059  .addImm(1));
1060  EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1061  .addReg(DestReg)
1062  .addReg(TableReg)
1063  .addReg(ScratchReg)
1064  .addImm(0));
1065  return;
1066  }
1067  case AArch64::JumpTableDest16:
1068  case AArch64::JumpTableDest8:
1069  LowerJumpTableDestSmall(*OutStreamer, *MI);
1070  return;
1071 
1072  case AArch64::FMOVH0:
1073  case AArch64::FMOVS0:
1074  case AArch64::FMOVD0:
1075  EmitFMov0(*MI);
1076  return;
1077 
1078  case TargetOpcode::STACKMAP:
1079  return LowerSTACKMAP(*OutStreamer, SM, *MI);
1080 
1081  case TargetOpcode::PATCHPOINT:
1082  return LowerPATCHPOINT(*OutStreamer, SM, *MI);
1083 
1084  case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
1085  LowerPATCHABLE_FUNCTION_ENTER(*MI);
1086  return;
1087 
1088  case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1089  LowerPATCHABLE_FUNCTION_EXIT(*MI);
1090  return;
1091 
1092  case TargetOpcode::PATCHABLE_TAIL_CALL:
1093  LowerPATCHABLE_TAIL_CALL(*MI);
1094  return;
1095 
1096  case AArch64::HWASAN_CHECK_MEMACCESS:
1097  LowerHWASAN_CHECK_MEMACCESS(*MI);
1098  return;
1099 
1100  case AArch64::SEH_StackAlloc:
1102  return;
1103 
1104  case AArch64::SEH_SaveFPLR:
1106  return;
1107 
1108  case AArch64::SEH_SaveFPLR_X:
1109  assert(MI->getOperand(0).getImm() < 0 &&
1110  "Pre increment SEH opcode must have a negative offset");
1112  return;
1113 
1114  case AArch64::SEH_SaveReg:
1116  MI->getOperand(1).getImm());
1117  return;
1118 
1119  case AArch64::SEH_SaveReg_X:
1120  assert(MI->getOperand(1).getImm() < 0 &&
1121  "Pre increment SEH opcode must have a negative offset");
1123  -MI->getOperand(1).getImm());
1124  return;
1125 
1126  case AArch64::SEH_SaveRegP:
1127  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1128  "Non-consecutive registers not allowed for save_regp");
1130  MI->getOperand(2).getImm());
1131  return;
1132 
1133  case AArch64::SEH_SaveRegP_X:
1134  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1135  "Non-consecutive registers not allowed for save_regp_x");
1136  assert(MI->getOperand(2).getImm() < 0 &&
1137  "Pre increment SEH opcode must have a negative offset");
1139  -MI->getOperand(2).getImm());
1140  return;
1141 
1142  case AArch64::SEH_SaveFReg:
1144  MI->getOperand(1).getImm());
1145  return;
1146 
1147  case AArch64::SEH_SaveFReg_X:
1148  assert(MI->getOperand(1).getImm() < 0 &&
1149  "Pre increment SEH opcode must have a negative offset");
1151  -MI->getOperand(1).getImm());
1152  return;
1153 
1154  case AArch64::SEH_SaveFRegP:
1155  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1156  "Non-consecutive registers not allowed for save_regp");
1158  MI->getOperand(2).getImm());
1159  return;
1160 
1161  case AArch64::SEH_SaveFRegP_X:
1162  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1163  "Non-consecutive registers not allowed for save_regp_x");
1164  assert(MI->getOperand(2).getImm() < 0 &&
1165  "Pre increment SEH opcode must have a negative offset");
1167  -MI->getOperand(2).getImm());
1168  return;
1169 
1170  case AArch64::SEH_SetFP:
1171  TS->EmitARM64WinCFISetFP();
1172  return;
1173 
1174  case AArch64::SEH_AddFP:
1175  TS->EmitARM64WinCFIAddFP(MI->getOperand(0).getImm());
1176  return;
1177 
1178  case AArch64::SEH_Nop:
1179  TS->EmitARM64WinCFINop();
1180  return;
1181 
1182  case AArch64::SEH_PrologEnd:
1184  return;
1185 
1186  case AArch64::SEH_EpilogStart:
1188  return;
1189 
1190  case AArch64::SEH_EpilogEnd:
1192  return;
1193  }
1194 
1195  // Finally, do the automated lowerings for everything else.
1196  MCInst TmpInst;
1197  MCInstLowering.Lower(MI, TmpInst);
1198  EmitToStreamer(*OutStreamer, TmpInst);
1199 }
1200 
1201 // Force static initialization.
1208 }
Instances of this class represent a uniqued identifier for a section in the current translation unit...
Definition: MCSection.h:39
Target & getTheAArch64beTarget()
static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO, char Mode, raw_ostream &O)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const std::vector< MachineJumpTableEntry > & getJumpTables() const
unsigned getNextScratchIdx(unsigned StartIdx=0) const
Get the next scratch register operand index.
Definition: StackMaps.cpp:69
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
static const char * getRegisterName(unsigned RegNo, unsigned AltIdx=AArch64::NoRegAltName)
SI Whole Quad Mode
void EmitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ...
Definition: MCStreamer.cpp:947
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:327
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
Target & getTheARM64_32Target()
void setTargetFlags(unsigned F)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
static const AArch64MCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
virtual void EndCOFFSymbolDef()
Marks the end of the symbol definition.
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition: Triple.h:623
Target & getTheAArch64leTarget()
unsigned getRegister(unsigned i) const
Return the specified register in the class.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:63
unsigned Reg
unsigned getSubReg() const
virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol)
Start emitting COFF symbol definition.
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:530
static unsigned getXRegFromWReg(unsigned Reg)
F(f)
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address...
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
virtual void EmitCOFFSymbolStorageClass(int StorageClass)
Emit the storage class of the symbol.
return AArch64::GPR64RegClass contains(Reg)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:115
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:414
virtual void EmitARM64WinCFISaveRegP(unsigned Reg, int Offset)
void LLVMInitializeAArch64AsmPrinter()
virtual void EmitCOFFSymbolType(int Type)
Emit the type of the symbol.
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
static StringRef getName(Value *V)
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:169
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:411
Target & getTheARM64Target()
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
zlib style complession
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
Definition: AsmPrinter.cpp:249
virtual void EmitARM64WinCFIAddFP(unsigned Size)
virtual void EmitARM64WinCFIAllocStack(unsigned Size)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:550
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table...
RegisterAsmPrinter - Helper template for registering a target specific assembly printer, for use in the target machine initialization function.
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
Definition: COFF.h:265
virtual void EmitARM64WinCFISaveFRegP(unsigned Reg, int Offset)
const std::string & str() const
Definition: Triple.h:365
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
virtual void EmitARM64WinCFISaveFRegX(unsigned Reg, int Offset)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false)
Definition: MCExpr.cpp:169
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
static unsigned getWRegFromXReg(unsigned Reg)
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText...
Definition: MCStreamer.h:292
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
.hidden (ELF)
Definition: MCDirectives.h:31
#define P(N)
Address of a global value.
Streaming machine code generation interface.
Definition: MCStreamer.h:190
Control flow instructions. These all have token chains.
Definition: ISDOpcodes.h:657
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address...
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:259
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
virtual bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, const Function &F) const
Target & getTheAArch64_32Target()
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:78
Represent the analysis usage information of a pass.
bool hasInternalLinkage() const
Definition: GlobalValue.h:443
Address of a basic block.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
virtual void EmitARM64WinCFISaveFPLRX(int Offset)
.subsections_via_symbols (MachO)
Definition: MCDirectives.h:50
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:37
MI-level patchpoint operands.
Definition: StackMaps.h:76
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition: Triple.h:633
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual MCSymbol * GetCPISymbol(unsigned CPID) const
Return the symbol for the specified constant pool entry.
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:40
void recordPatchPoint(const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
Definition: StackMaps.cpp:372
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:545
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:43
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Definition: STLExtras.h:197
virtual void EmitARM64WinCFISaveReg(unsigned Reg, int Offset)
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
Definition: StackMaps.h:50
void setOpcode(unsigned Op)
Definition: MCInst.h:170
MachineOperand class - Representation of each machine instruction operand.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
virtual void EmitARM64WinCFISaveRegPX(unsigned Reg, int Offset)
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant...
StringRef str()
Return a StringRef for the vector contents.
Definition: raw_ostream.h:555
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
std::string utostr(uint64_t X, bool isNeg=false)
Definition: StringExtras.h:223
int64_t getImm() const
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
const Function & getFunction() const
Return the LLVM function that this machine code represents.
SymbolStorageClass
Storage class tells where and what the symbol represents.
Definition: COFF.h:203
Target - Wrapper for Target specific information.
void recordStackMap(const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
Definition: StackMaps.cpp:363
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
void setPreservesAll()
Set by analyses that do not transform their input at all.
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed...
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:256
Representation of each machine instruction.
Definition: MachineInstr.h:64
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
virtual void EmitARM64WinCFISaveFPLR(int Offset)
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MI-level stackmap operands.
Definition: StackMaps.h:35
virtual void EmitARM64WinCFISaveFRegPX(unsigned Reg, int Offset)
.type _foo, STT_FUNC # aka
Definition: MCDirectives.h:23
const BlockAddress * getBlockAddress() const
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
#define I(x, y, z)
Definition: MD5.cpp:58
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page...
uint32_t Size
Definition: Profile.cpp:46
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given patchpoint should emit.
Definition: StackMaps.h:104
bool isReg() const
isReg - Tests if this is a MO_Register operand.
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:204
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
JTEntryKind getEntryKind() const
ExceptionHandling
virtual void EmitCFIBKeyFrame()
Definition: MCStreamer.cpp:230
virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:399
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
virtual MCSection * getSectionForJumpTable(const Function &F, const TargetMachine &TM) const
IRTranslator LLVM IR MI
const MachineOperand & getCallTarget() const
Returns the target of the underlying call.
Definition: StackMaps.h:109
void addOperand(const MCOperand &Op)
Definition: MCInst.h:183
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow...
DWARF-like instruction based exceptions.
virtual void EmitARM64WinCFISaveFReg(unsigned Reg, int Offset)
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:416
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:122
virtual void EmitARM64WinCFISaveRegX(unsigned Reg, int Offset)
virtual const MCExpr * getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const
This returns the relocation base for the given PIC jumptable, the same as getPICJumpTableRelocBase, but as an MCExpr.
const MDNode * getMetadata() const
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:59
A function that returns a base type.
Definition: COFF.h:261