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, bool isVector,
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  bool isVector, 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));
540  RegToPrint, isVector ? AArch64::vreg : AArch64::NoRegAltName);
541  return false;
542 }
543 
544 bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
545  const char *ExtraCode, raw_ostream &O) {
546  const MachineOperand &MO = MI->getOperand(OpNum);
547 
548  // First try the generic code, which knows about modifiers like 'c' and 'n'.
549  if (!AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O))
550  return false;
551 
552  // Does this asm operand have a single letter operand modifier?
553  if (ExtraCode && ExtraCode[0]) {
554  if (ExtraCode[1] != 0)
555  return true; // Unknown modifier.
556 
557  switch (ExtraCode[0]) {
558  default:
559  return true; // Unknown modifier.
560  case 'w': // Print W register
561  case 'x': // Print X register
562  if (MO.isReg())
563  return printAsmMRegister(MO, ExtraCode[0], O);
564  if (MO.isImm() && MO.getImm() == 0) {
565  unsigned Reg = ExtraCode[0] == 'w' ? AArch64::WZR : AArch64::XZR;
567  return false;
568  }
569  printOperand(MI, OpNum, O);
570  return false;
571  case 'b': // Print B register.
572  case 'h': // Print H register.
573  case 's': // Print S register.
574  case 'd': // Print D register.
575  case 'q': // Print Q 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  default:
595  return true;
596  }
597  return printAsmRegInClass(MO, RC, false /* vector */, O);
598  }
599  printOperand(MI, OpNum, O);
600  return false;
601  }
602  }
603 
604  // According to ARM, we should emit x and v registers unless we have a
605  // modifier.
606  if (MO.isReg()) {
607  Register Reg = MO.getReg();
608 
609  // If this is a w or x register, print an x register.
610  if (AArch64::GPR32allRegClass.contains(Reg) ||
611  AArch64::GPR64allRegClass.contains(Reg))
612  return printAsmMRegister(MO, 'x', O);
613 
614  // If this is a b, h, s, d, or q register, print it as a v register.
615  return printAsmRegInClass(MO, &AArch64::FPR128RegClass, true /* vector */,
616  O);
617  }
618 
619  printOperand(MI, OpNum, O);
620  return false;
621 }
622 
623 bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
624  unsigned OpNum,
625  const char *ExtraCode,
626  raw_ostream &O) {
627  if (ExtraCode && ExtraCode[0] && ExtraCode[0] != 'a')
628  return true; // Unknown modifier.
629 
630  const MachineOperand &MO = MI->getOperand(OpNum);
631  assert(MO.isReg() && "unexpected inline asm memory operand");
632  O << "[" << AArch64InstPrinter::getRegisterName(MO.getReg()) << "]";
633  return false;
634 }
635 
636 void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
637  raw_ostream &OS) {
638  unsigned NOps = MI->getNumOperands();
639  assert(NOps == 4);
640  OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
641  // cast away const; DIetc do not take const operands for some reason.
642  OS << cast<DILocalVariable>(MI->getOperand(NOps - 2).getMetadata())
643  ->getName();
644  OS << " <- ";
645  // Frame address. Currently handles register +- offset only.
646  assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
647  OS << '[';
648  printOperand(MI, 0, OS);
649  OS << '+';
650  printOperand(MI, 1, OS);
651  OS << ']';
652  OS << "+";
653  printOperand(MI, NOps - 2, OS);
654 }
655 
656 void AArch64AsmPrinter::EmitJumpTableInfo() {
657  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
658  if (!MJTI) return;
659 
660  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
661  if (JT.empty()) return;
662 
663  const Function &F = MF->getFunction();
664  const TargetLoweringObjectFile &TLOF = getObjFileLowering();
665  bool JTInDiffSection =
666  !STI->isTargetCOFF() ||
669  F);
670  if (JTInDiffSection) {
671  // Drop it in the readonly section.
672  MCSection *ReadOnlySec = TLOF.getSectionForJumpTable(F, TM);
673  OutStreamer->SwitchSection(ReadOnlySec);
674  }
675 
676  auto AFI = MF->getInfo<AArch64FunctionInfo>();
677  for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
678  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
679 
680  // If this jump table was deleted, ignore it.
681  if (JTBBs.empty()) continue;
682 
683  unsigned Size = AFI->getJumpTableEntrySize(JTI);
684  EmitAlignment(Log2_32(Size));
685  OutStreamer->EmitLabel(GetJTISymbol(JTI));
686 
687  for (auto *JTBB : JTBBs)
688  emitJumpTableEntry(MJTI, JTBB, JTI);
689  }
690 }
691 
692 void AArch64AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
693  const MachineBasicBlock *MBB,
694  unsigned JTI) {
695  const MCExpr *Value = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
696  auto AFI = MF->getInfo<AArch64FunctionInfo>();
697  unsigned Size = AFI->getJumpTableEntrySize(JTI);
698 
699  if (Size == 4) {
700  // .word LBB - LJTI
701  const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
702  const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF, JTI, OutContext);
703  Value = MCBinaryExpr::createSub(Value, Base, OutContext);
704  } else {
705  // .byte (LBB - LBB) >> 2 (or .hword)
706  const MCSymbol *BaseSym = AFI->getJumpTableEntryPCRelSymbol(JTI);
707  const MCExpr *Base = MCSymbolRefExpr::create(BaseSym, OutContext);
708  Value = MCBinaryExpr::createSub(Value, Base, OutContext);
709  Value = MCBinaryExpr::createLShr(
710  Value, MCConstantExpr::create(2, OutContext), OutContext);
711  }
712 
713  OutStreamer->EmitValue(Value, Size);
714 }
715 
716 /// Small jump tables contain an unsigned byte or half, representing the offset
717 /// from the lowest-addressed possible destination to the desired basic
718 /// block. Since all instructions are 4-byte aligned, this is further compressed
719 /// by counting in instructions rather than bytes (i.e. divided by 4). So, to
720 /// materialize the correct destination we need:
721 ///
722 /// adr xDest, .LBB0_0
723 /// ldrb wScratch, [xTable, xEntry] (with "lsl #1" for ldrh).
724 /// add xDest, xDest, xScratch, lsl #2
725 void AArch64AsmPrinter::LowerJumpTableDestSmall(llvm::MCStreamer &OutStreamer,
726  const llvm::MachineInstr &MI) {
727  Register DestReg = MI.getOperand(0).getReg();
728  Register ScratchReg = MI.getOperand(1).getReg();
729  Register ScratchRegW =
730  STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
731  Register TableReg = MI.getOperand(2).getReg();
732  Register EntryReg = MI.getOperand(3).getReg();
733  int JTIdx = MI.getOperand(4).getIndex();
734  bool IsByteEntry = MI.getOpcode() == AArch64::JumpTableDest8;
735 
736  // This has to be first because the compression pass based its reachability
737  // calculations on the start of the JumpTableDest instruction.
738  auto Label =
739  MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
740  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
741  .addReg(DestReg)
742  .addExpr(MCSymbolRefExpr::create(
743  Label, MF->getContext())));
744 
745  // Load the number of instruction-steps to offset from the label.
746  unsigned LdrOpcode = IsByteEntry ? AArch64::LDRBBroX : AArch64::LDRHHroX;
747  EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
748  .addReg(ScratchRegW)
749  .addReg(TableReg)
750  .addReg(EntryReg)
751  .addImm(0)
752  .addImm(IsByteEntry ? 0 : 1));
753 
754  // Multiply the steps by 4 and add to the already materialized base label
755  // address.
756  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
757  .addReg(DestReg)
758  .addReg(DestReg)
759  .addReg(ScratchReg)
760  .addImm(2));
761 }
762 
763 void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
764  const MachineInstr &MI) {
765  unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
766 
767  SM.recordStackMap(MI);
768  assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
769 
770  // Scan ahead to trim the shadow.
771  const MachineBasicBlock &MBB = *MI.getParent();
773  ++MII;
774  while (NumNOPBytes > 0) {
775  if (MII == MBB.end() || MII->isCall() ||
776  MII->getOpcode() == AArch64::DBG_VALUE ||
777  MII->getOpcode() == TargetOpcode::PATCHPOINT ||
778  MII->getOpcode() == TargetOpcode::STACKMAP)
779  break;
780  ++MII;
781  NumNOPBytes -= 4;
782  }
783 
784  // Emit nops.
785  for (unsigned i = 0; i < NumNOPBytes; i += 4)
786  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
787 }
788 
789 // Lower a patchpoint of the form:
790 // [<def>], <id>, <numBytes>, <target>, <numArgs>
791 void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
792  const MachineInstr &MI) {
793  SM.recordPatchPoint(MI);
794 
795  PatchPointOpers Opers(&MI);
796 
797  int64_t CallTarget = Opers.getCallTarget().getImm();
798  unsigned EncodedBytes = 0;
799  if (CallTarget) {
800  assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
801  "High 16 bits of call target should be zero.");
802  Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
803  EncodedBytes = 16;
804  // Materialize the jump address:
805  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVZXi)
806  .addReg(ScratchReg)
807  .addImm((CallTarget >> 32) & 0xFFFF)
808  .addImm(32));
809  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
810  .addReg(ScratchReg)
811  .addReg(ScratchReg)
812  .addImm((CallTarget >> 16) & 0xFFFF)
813  .addImm(16));
814  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
815  .addReg(ScratchReg)
816  .addReg(ScratchReg)
817  .addImm(CallTarget & 0xFFFF)
818  .addImm(0));
819  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
820  }
821  // Emit padding.
822  unsigned NumBytes = Opers.getNumPatchBytes();
823  assert(NumBytes >= EncodedBytes &&
824  "Patchpoint can't request size less than the length of a call.");
825  assert((NumBytes - EncodedBytes) % 4 == 0 &&
826  "Invalid number of NOP bytes requested!");
827  for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
828  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
829 }
830 
831 void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) {
832  Register DestReg = MI.getOperand(0).getReg();
833  if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) {
834  // Convert H/S/D register to corresponding Q register
835  if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
836  DestReg = AArch64::Q0 + (DestReg - AArch64::H0);
837  else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
838  DestReg = AArch64::Q0 + (DestReg - AArch64::S0);
839  else {
840  assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
841  DestReg = AArch64::Q0 + (DestReg - AArch64::D0);
842  }
843  MCInst MOVI;
844  MOVI.setOpcode(AArch64::MOVIv2d_ns);
845  MOVI.addOperand(MCOperand::createReg(DestReg));
846  MOVI.addOperand(MCOperand::createImm(0));
847  EmitToStreamer(*OutStreamer, MOVI);
848  } else {
849  MCInst FMov;
850  switch (MI.getOpcode()) {
851  default: llvm_unreachable("Unexpected opcode");
852  case AArch64::FMOVH0:
853  FMov.setOpcode(AArch64::FMOVWHr);
854  FMov.addOperand(MCOperand::createReg(DestReg));
855  FMov.addOperand(MCOperand::createReg(AArch64::WZR));
856  break;
857  case AArch64::FMOVS0:
858  FMov.setOpcode(AArch64::FMOVWSr);
859  FMov.addOperand(MCOperand::createReg(DestReg));
860  FMov.addOperand(MCOperand::createReg(AArch64::WZR));
861  break;
862  case AArch64::FMOVD0:
863  FMov.setOpcode(AArch64::FMOVXDr);
864  FMov.addOperand(MCOperand::createReg(DestReg));
865  FMov.addOperand(MCOperand::createReg(AArch64::XZR));
866  break;
867  }
868  EmitToStreamer(*OutStreamer, FMov);
869  }
870 }
871 
872 // Simple pseudo-instructions have their lowering (with expansion to real
873 // instructions) auto-generated.
874 #include "AArch64GenMCPseudoLowering.inc"
875 
876 void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
877  // Do any auto-generated pseudo lowerings.
878  if (emitPseudoExpansionLowering(*OutStreamer, MI))
879  return;
880 
881  if (AArch64FI->getLOHRelated().count(MI)) {
882  // Generate a label for LOH related instruction
883  MCSymbol *LOHLabel = createTempSymbol("loh");
884  // Associate the instruction with the label
885  LOHInstToLabel[MI] = LOHLabel;
886  OutStreamer->EmitLabel(LOHLabel);
887  }
888 
890  static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
891  // Do any manual lowerings.
892  switch (MI->getOpcode()) {
893  default:
894  break;
895  case AArch64::MOVMCSym: {
896  Register DestReg = MI->getOperand(0).getReg();
897  const MachineOperand &MO_Sym = MI->getOperand(1);
898  MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
899  MCOperand Hi_MCSym, Lo_MCSym;
900 
901  Hi_MOSym.setTargetFlags(AArch64II::MO_G1 | AArch64II::MO_S);
903 
904  MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
905  MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
906 
907  MCInst MovZ;
908  MovZ.setOpcode(AArch64::MOVZXi);
909  MovZ.addOperand(MCOperand::createReg(DestReg));
910  MovZ.addOperand(Hi_MCSym);
912  EmitToStreamer(*OutStreamer, MovZ);
913 
914  MCInst MovK;
915  MovK.setOpcode(AArch64::MOVKXi);
916  MovK.addOperand(MCOperand::createReg(DestReg));
917  MovK.addOperand(MCOperand::createReg(DestReg));
918  MovK.addOperand(Lo_MCSym);
920  EmitToStreamer(*OutStreamer, MovK);
921  return;
922  }
923  case AArch64::MOVIv2d_ns:
924  // If the target has <rdar://problem/16473581>, lower this
925  // instruction to movi.16b instead.
926  if (STI->hasZeroCycleZeroingFPWorkaround() &&
927  MI->getOperand(1).getImm() == 0) {
928  MCInst TmpInst;
929  TmpInst.setOpcode(AArch64::MOVIv16b_ns);
932  EmitToStreamer(*OutStreamer, TmpInst);
933  return;
934  }
935  break;
936 
937  case AArch64::DBG_VALUE: {
938  if (isVerbose() && OutStreamer->hasRawTextSupport()) {
939  SmallString<128> TmpStr;
940  raw_svector_ostream OS(TmpStr);
941  PrintDebugValueComment(MI, OS);
942  OutStreamer->EmitRawText(StringRef(OS.str()));
943  }
944  return;
945 
946  case AArch64::EMITBKEY: {
947  ExceptionHandling ExceptionHandlingType = MAI->getExceptionHandlingType();
948  if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
949  ExceptionHandlingType != ExceptionHandling::ARM)
950  return;
951 
952  if (needsCFIMoves() == CFI_M_None)
953  return;
954 
955  OutStreamer->EmitCFIBKeyFrame();
956  return;
957  }
958  }
959 
960  // Tail calls use pseudo instructions so they have the proper code-gen
961  // attributes (isCall, isReturn, etc.). We lower them to the real
962  // instruction here.
963  case AArch64::TCRETURNri:
964  case AArch64::TCRETURNriBTI:
965  case AArch64::TCRETURNriALL: {
966  MCInst TmpInst;
967  TmpInst.setOpcode(AArch64::BR);
969  EmitToStreamer(*OutStreamer, TmpInst);
970  return;
971  }
972  case AArch64::TCRETURNdi: {
973  MCOperand Dest;
974  MCInstLowering.lowerOperand(MI->getOperand(0), Dest);
975  MCInst TmpInst;
976  TmpInst.setOpcode(AArch64::B);
977  TmpInst.addOperand(Dest);
978  EmitToStreamer(*OutStreamer, TmpInst);
979  return;
980  }
982  /// lower this to:
983  /// adrp x0, :tlsdesc:var
984  /// ldr x1, [x0, #:tlsdesc_lo12:var]
985  /// add x0, x0, #:tlsdesc_lo12:var
986  /// .tlsdesccall var
987  /// blr x1
988  /// (TPIDR_EL0 offset now in x0)
989  const MachineOperand &MO_Sym = MI->getOperand(0);
990  MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
991  MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
992  MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
994  MCInstLowering.lowerOperand(MO_Sym, Sym);
995  MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
996  MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
997 
998  MCInst Adrp;
999  Adrp.setOpcode(AArch64::ADRP);
1000  Adrp.addOperand(MCOperand::createReg(AArch64::X0));
1001  Adrp.addOperand(SymTLSDesc);
1002  EmitToStreamer(*OutStreamer, Adrp);
1003 
1004  MCInst Ldr;
1005  Ldr.setOpcode(AArch64::LDRXui);
1006  Ldr.addOperand(MCOperand::createReg(AArch64::X1));
1007  Ldr.addOperand(MCOperand::createReg(AArch64::X0));
1008  Ldr.addOperand(SymTLSDescLo12);
1010  EmitToStreamer(*OutStreamer, Ldr);
1011 
1012  MCInst Add;
1013  Add.setOpcode(AArch64::ADDXri);
1014  Add.addOperand(MCOperand::createReg(AArch64::X0));
1015  Add.addOperand(MCOperand::createReg(AArch64::X0));
1016  Add.addOperand(SymTLSDescLo12);
1018  EmitToStreamer(*OutStreamer, Add);
1019 
1020  // Emit a relocation-annotation. This expands to no code, but requests
1021  // the following instruction gets an R_AARCH64_TLSDESC_CALL.
1022  MCInst TLSDescCall;
1023  TLSDescCall.setOpcode(AArch64::TLSDESCCALL);
1024  TLSDescCall.addOperand(Sym);
1025  EmitToStreamer(*OutStreamer, TLSDescCall);
1026 
1027  MCInst Blr;
1028  Blr.setOpcode(AArch64::BLR);
1029  Blr.addOperand(MCOperand::createReg(AArch64::X1));
1030  EmitToStreamer(*OutStreamer, Blr);
1031 
1032  return;
1033  }
1034 
1035  case AArch64::JumpTableDest32: {
1036  // We want:
1037  // ldrsw xScratch, [xTable, xEntry, lsl #2]
1038  // add xDest, xTable, xScratch
1039  unsigned DestReg = MI->getOperand(0).getReg(),
1040  ScratchReg = MI->getOperand(1).getReg(),
1041  TableReg = MI->getOperand(2).getReg(),
1042  EntryReg = MI->getOperand(3).getReg();
1043  EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
1044  .addReg(ScratchReg)
1045  .addReg(TableReg)
1046  .addReg(EntryReg)
1047  .addImm(0)
1048  .addImm(1));
1049  EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
1050  .addReg(DestReg)
1051  .addReg(TableReg)
1052  .addReg(ScratchReg)
1053  .addImm(0));
1054  return;
1055  }
1056  case AArch64::JumpTableDest16:
1057  case AArch64::JumpTableDest8:
1058  LowerJumpTableDestSmall(*OutStreamer, *MI);
1059  return;
1060 
1061  case AArch64::FMOVH0:
1062  case AArch64::FMOVS0:
1063  case AArch64::FMOVD0:
1064  EmitFMov0(*MI);
1065  return;
1066 
1067  case TargetOpcode::STACKMAP:
1068  return LowerSTACKMAP(*OutStreamer, SM, *MI);
1069 
1070  case TargetOpcode::PATCHPOINT:
1071  return LowerPATCHPOINT(*OutStreamer, SM, *MI);
1072 
1073  case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
1074  LowerPATCHABLE_FUNCTION_ENTER(*MI);
1075  return;
1076 
1077  case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1078  LowerPATCHABLE_FUNCTION_EXIT(*MI);
1079  return;
1080 
1081  case TargetOpcode::PATCHABLE_TAIL_CALL:
1082  LowerPATCHABLE_TAIL_CALL(*MI);
1083  return;
1084 
1085  case AArch64::HWASAN_CHECK_MEMACCESS:
1086  LowerHWASAN_CHECK_MEMACCESS(*MI);
1087  return;
1088 
1089  case AArch64::SEH_StackAlloc:
1091  return;
1092 
1093  case AArch64::SEH_SaveFPLR:
1095  return;
1096 
1097  case AArch64::SEH_SaveFPLR_X:
1098  assert(MI->getOperand(0).getImm() < 0 &&
1099  "Pre increment SEH opcode must have a negative offset");
1101  return;
1102 
1103  case AArch64::SEH_SaveReg:
1105  MI->getOperand(1).getImm());
1106  return;
1107 
1108  case AArch64::SEH_SaveReg_X:
1109  assert(MI->getOperand(1).getImm() < 0 &&
1110  "Pre increment SEH opcode must have a negative offset");
1112  -MI->getOperand(1).getImm());
1113  return;
1114 
1115  case AArch64::SEH_SaveRegP:
1116  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1117  "Non-consecutive registers not allowed for save_regp");
1119  MI->getOperand(2).getImm());
1120  return;
1121 
1122  case AArch64::SEH_SaveRegP_X:
1123  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1124  "Non-consecutive registers not allowed for save_regp_x");
1125  assert(MI->getOperand(2).getImm() < 0 &&
1126  "Pre increment SEH opcode must have a negative offset");
1128  -MI->getOperand(2).getImm());
1129  return;
1130 
1131  case AArch64::SEH_SaveFReg:
1133  MI->getOperand(1).getImm());
1134  return;
1135 
1136  case AArch64::SEH_SaveFReg_X:
1137  assert(MI->getOperand(1).getImm() < 0 &&
1138  "Pre increment SEH opcode must have a negative offset");
1140  -MI->getOperand(1).getImm());
1141  return;
1142 
1143  case AArch64::SEH_SaveFRegP:
1144  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1145  "Non-consecutive registers not allowed for save_regp");
1147  MI->getOperand(2).getImm());
1148  return;
1149 
1150  case AArch64::SEH_SaveFRegP_X:
1151  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1152  "Non-consecutive registers not allowed for save_regp_x");
1153  assert(MI->getOperand(2).getImm() < 0 &&
1154  "Pre increment SEH opcode must have a negative offset");
1156  -MI->getOperand(2).getImm());
1157  return;
1158 
1159  case AArch64::SEH_SetFP:
1160  TS->EmitARM64WinCFISetFP();
1161  return;
1162 
1163  case AArch64::SEH_AddFP:
1164  TS->EmitARM64WinCFIAddFP(MI->getOperand(0).getImm());
1165  return;
1166 
1167  case AArch64::SEH_Nop:
1168  TS->EmitARM64WinCFINop();
1169  return;
1170 
1171  case AArch64::SEH_PrologEnd:
1173  return;
1174 
1175  case AArch64::SEH_EpilogStart:
1177  return;
1178 
1179  case AArch64::SEH_EpilogEnd:
1181  return;
1182  }
1183 
1184  // Finally, do the automated lowerings for everything else.
1185  MCInst TmpInst;
1186  MCInstLowering.Lower(MI, TmpInst);
1187  EmitToStreamer(*OutStreamer, TmpInst);
1188 }
1189 
1190 // Force static initialization.
1195 }
Instances of this class represent a uniqued identifier for a section in the current translation unit...
Definition: MCSection.h:38
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:940
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:331
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...
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.
LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
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:173
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:248
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:554
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:291
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:189
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:258
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
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.
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:549
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:209
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.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:538
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:228
virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:397
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