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