LLVM  9.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  unsigned 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(MCInstBuilder(AArch64::UBFMXri)
301  .addReg(AArch64::X17)
302  .addReg(Reg)
303  .addImm(56)
304  .addImm(63),
305  *STI);
306  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::SUBSWrs)
307  .addReg(AArch64::WZR)
308  .addReg(AArch64::W16)
309  .addReg(AArch64::W17)
310  .addImm(0),
311  *STI);
312  MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
313  OutStreamer->EmitInstruction(
314  MCInstBuilder(AArch64::Bcc)
315  .addImm(AArch64CC::NE)
316  .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
317  *STI);
318  OutStreamer->EmitInstruction(
319  MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
320 
321  OutStreamer->EmitLabel(HandleMismatchSym);
322 
323  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::STPXpre)
324  .addReg(AArch64::SP)
325  .addReg(AArch64::X0)
326  .addReg(AArch64::X1)
327  .addReg(AArch64::SP)
328  .addImm(-32),
329  *STI);
330  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::STPXi)
331  .addReg(AArch64::FP)
332  .addReg(AArch64::LR)
333  .addReg(AArch64::SP)
334  .addImm(29),
335  *STI);
336 
337  if (Reg != AArch64::X0)
338  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::ORRXrs)
339  .addReg(AArch64::X0)
340  .addReg(AArch64::XZR)
341  .addReg(Reg)
342  .addImm(0),
343  *STI);
344  OutStreamer->EmitInstruction(MCInstBuilder(AArch64::MOVZXi)
345  .addReg(AArch64::X1)
346  .addImm(AccessInfo)
347  .addImm(0),
348  *STI);
349 
350  // Intentionally load the GOT entry and branch to it, rather than possibly
351  // late binding the function, which may clobber the registers before we have
352  // a chance to save them.
353  OutStreamer->EmitInstruction(
355  .addReg(AArch64::X16)
356  .addExpr(AArch64MCExpr::create(
357  HwasanTagMismatchRef,
358  AArch64MCExpr::VariantKind::VK_GOT_PAGE, OutContext)),
359  *STI);
360  OutStreamer->EmitInstruction(
361  MCInstBuilder(AArch64::LDRXui)
362  .addReg(AArch64::X16)
363  .addReg(AArch64::X16)
364  .addExpr(AArch64MCExpr::create(
365  HwasanTagMismatchRef,
366  AArch64MCExpr::VariantKind::VK_GOT_LO12, OutContext)),
367  *STI);
368  OutStreamer->EmitInstruction(
369  MCInstBuilder(AArch64::BR).addReg(AArch64::X16), *STI);
370  }
371 }
372 
373 void AArch64AsmPrinter::EmitEndOfAsmFile(Module &M) {
374  EmitHwasanMemaccessSymbols(M);
375 
376  const Triple &TT = TM.getTargetTriple();
377  if (TT.isOSBinFormatMachO()) {
378  // Funny Darwin hack: This flag tells the linker that no global symbols
379  // contain code that falls through to other global symbols (e.g. the obvious
380  // implementation of multiple entry points). If this doesn't occur, the
381  // linker can safely perform dead code stripping. Since LLVM never
382  // generates code that does this, it is always safe to set.
383  OutStreamer->EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
384  emitStackMaps(SM);
385  }
386 }
387 
388 void AArch64AsmPrinter::EmitLOHs() {
390 
391  for (const auto &D : AArch64FI->getLOHContainer()) {
392  for (const MachineInstr *MI : D.getArgs()) {
393  MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(MI);
394  assert(LabelIt != LOHInstToLabel.end() &&
395  "Label hasn't been inserted for LOH related instruction");
396  MCArgs.push_back(LabelIt->second);
397  }
398  OutStreamer->EmitLOHDirective(D.getKind(), MCArgs);
399  MCArgs.clear();
400  }
401 }
402 
403 void AArch64AsmPrinter::EmitFunctionBodyEnd() {
404  if (!AArch64FI->getLOHRelated().empty())
405  EmitLOHs();
406 }
407 
408 /// GetCPISymbol - Return the symbol for the specified constant pool entry.
409 MCSymbol *AArch64AsmPrinter::GetCPISymbol(unsigned CPID) const {
410  // Darwin uses a linker-private symbol name for constant-pools (to
411  // avoid addends on the relocation?), ELF has no such concept and
412  // uses a normal private symbol.
413  if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
414  return OutContext.getOrCreateSymbol(
415  Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) + "CPI" +
416  Twine(getFunctionNumber()) + "_" + Twine(CPID));
417 
418  return AsmPrinter::GetCPISymbol(CPID);
419 }
420 
421 void AArch64AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNum,
422  raw_ostream &O) {
423  const MachineOperand &MO = MI->getOperand(OpNum);
424  switch (MO.getType()) {
425  default:
426  llvm_unreachable("<unknown operand type>");
428  unsigned Reg = MO.getReg();
430  assert(!MO.getSubReg() && "Subregs should be eliminated!");
432  break;
433  }
435  int64_t Imm = MO.getImm();
436  O << '#' << Imm;
437  break;
438  }
440  PrintSymbolOperand(MO, O);
441  break;
442  }
444  MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
445  Sym->print(O, MAI);
446  break;
447  }
448  }
449 }
450 
452  raw_ostream &O) {
453  unsigned Reg = MO.getReg();
454  switch (Mode) {
455  default:
456  return true; // Unknown mode.
457  case 'w':
458  Reg = getWRegFromXReg(Reg);
459  break;
460  case 'x':
461  Reg = getXRegFromWReg(Reg);
462  break;
463  }
464 
466  return false;
467 }
468 
469 // Prints the register in MO using class RC using the offset in the
470 // new register class. This should not be used for cross class
471 // printing.
472 bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO,
473  const TargetRegisterClass *RC,
474  bool isVector, raw_ostream &O) {
475  assert(MO.isReg() && "Should only get here with a register!");
476  const TargetRegisterInfo *RI = STI->getRegisterInfo();
477  unsigned Reg = MO.getReg();
478  unsigned RegToPrint = RC->getRegister(RI->getEncodingValue(Reg));
479  assert(RI->regsOverlap(RegToPrint, Reg));
481  RegToPrint, isVector ? AArch64::vreg : AArch64::NoRegAltName);
482  return false;
483 }
484 
485 bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
486  const char *ExtraCode, raw_ostream &O) {
487  const MachineOperand &MO = MI->getOperand(OpNum);
488 
489  // First try the generic code, which knows about modifiers like 'c' and 'n'.
490  if (!AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O))
491  return false;
492 
493  // Does this asm operand have a single letter operand modifier?
494  if (ExtraCode && ExtraCode[0]) {
495  if (ExtraCode[1] != 0)
496  return true; // Unknown modifier.
497 
498  switch (ExtraCode[0]) {
499  default:
500  return true; // Unknown modifier.
501  case 'w': // Print W register
502  case 'x': // Print X register
503  if (MO.isReg())
504  return printAsmMRegister(MO, ExtraCode[0], O);
505  if (MO.isImm() && MO.getImm() == 0) {
506  unsigned Reg = ExtraCode[0] == 'w' ? AArch64::WZR : AArch64::XZR;
508  return false;
509  }
510  printOperand(MI, OpNum, O);
511  return false;
512  case 'b': // Print B register.
513  case 'h': // Print H register.
514  case 's': // Print S register.
515  case 'd': // Print D register.
516  case 'q': // Print Q register.
517  if (MO.isReg()) {
518  const TargetRegisterClass *RC;
519  switch (ExtraCode[0]) {
520  case 'b':
521  RC = &AArch64::FPR8RegClass;
522  break;
523  case 'h':
524  RC = &AArch64::FPR16RegClass;
525  break;
526  case 's':
527  RC = &AArch64::FPR32RegClass;
528  break;
529  case 'd':
530  RC = &AArch64::FPR64RegClass;
531  break;
532  case 'q':
533  RC = &AArch64::FPR128RegClass;
534  break;
535  default:
536  return true;
537  }
538  return printAsmRegInClass(MO, RC, false /* vector */, O);
539  }
540  printOperand(MI, OpNum, O);
541  return false;
542  }
543  }
544 
545  // According to ARM, we should emit x and v registers unless we have a
546  // modifier.
547  if (MO.isReg()) {
548  unsigned Reg = MO.getReg();
549 
550  // If this is a w or x register, print an x register.
551  if (AArch64::GPR32allRegClass.contains(Reg) ||
552  AArch64::GPR64allRegClass.contains(Reg))
553  return printAsmMRegister(MO, 'x', O);
554 
555  // If this is a b, h, s, d, or q register, print it as a v register.
556  return printAsmRegInClass(MO, &AArch64::FPR128RegClass, true /* vector */,
557  O);
558  }
559 
560  printOperand(MI, OpNum, O);
561  return false;
562 }
563 
564 bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
565  unsigned OpNum,
566  const char *ExtraCode,
567  raw_ostream &O) {
568  if (ExtraCode && ExtraCode[0] && ExtraCode[0] != 'a')
569  return true; // Unknown modifier.
570 
571  const MachineOperand &MO = MI->getOperand(OpNum);
572  assert(MO.isReg() && "unexpected inline asm memory operand");
573  O << "[" << AArch64InstPrinter::getRegisterName(MO.getReg()) << "]";
574  return false;
575 }
576 
577 void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
578  raw_ostream &OS) {
579  unsigned NOps = MI->getNumOperands();
580  assert(NOps == 4);
581  OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
582  // cast away const; DIetc do not take const operands for some reason.
583  OS << cast<DILocalVariable>(MI->getOperand(NOps - 2).getMetadata())
584  ->getName();
585  OS << " <- ";
586  // Frame address. Currently handles register +- offset only.
587  assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
588  OS << '[';
589  printOperand(MI, 0, OS);
590  OS << '+';
591  printOperand(MI, 1, OS);
592  OS << ']';
593  OS << "+";
594  printOperand(MI, NOps - 2, OS);
595 }
596 
597 void AArch64AsmPrinter::EmitJumpTableInfo() {
598  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
599  if (!MJTI) return;
600 
601  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
602  if (JT.empty()) return;
603 
604  const Function &F = MF->getFunction();
605  const TargetLoweringObjectFile &TLOF = getObjFileLowering();
606  bool JTInDiffSection =
607  !STI->isTargetCOFF() ||
610  F);
611  if (JTInDiffSection) {
612  // Drop it in the readonly section.
613  MCSection *ReadOnlySec = TLOF.getSectionForJumpTable(F, TM);
614  OutStreamer->SwitchSection(ReadOnlySec);
615  }
616 
617  auto AFI = MF->getInfo<AArch64FunctionInfo>();
618  for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
619  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
620 
621  // If this jump table was deleted, ignore it.
622  if (JTBBs.empty()) continue;
623 
624  unsigned Size = AFI->getJumpTableEntrySize(JTI);
625  EmitAlignment(Log2_32(Size));
626  OutStreamer->EmitLabel(GetJTISymbol(JTI));
627 
628  for (auto *JTBB : JTBBs)
629  emitJumpTableEntry(MJTI, JTBB, JTI);
630  }
631 }
632 
633 void AArch64AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
634  const MachineBasicBlock *MBB,
635  unsigned JTI) {
636  const MCExpr *Value = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
637  auto AFI = MF->getInfo<AArch64FunctionInfo>();
638  unsigned Size = AFI->getJumpTableEntrySize(JTI);
639 
640  if (Size == 4) {
641  // .word LBB - LJTI
642  const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
643  const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF, JTI, OutContext);
644  Value = MCBinaryExpr::createSub(Value, Base, OutContext);
645  } else {
646  // .byte (LBB - LBB) >> 2 (or .hword)
647  const MCSymbol *BaseSym = AFI->getJumpTableEntryPCRelSymbol(JTI);
648  const MCExpr *Base = MCSymbolRefExpr::create(BaseSym, OutContext);
649  Value = MCBinaryExpr::createSub(Value, Base, OutContext);
650  Value = MCBinaryExpr::createLShr(
651  Value, MCConstantExpr::create(2, OutContext), OutContext);
652  }
653 
654  OutStreamer->EmitValue(Value, Size);
655 }
656 
657 /// Small jump tables contain an unsigned byte or half, representing the offset
658 /// from the lowest-addressed possible destination to the desired basic
659 /// block. Since all instructions are 4-byte aligned, this is further compressed
660 /// by counting in instructions rather than bytes (i.e. divided by 4). So, to
661 /// materialize the correct destination we need:
662 ///
663 /// adr xDest, .LBB0_0
664 /// ldrb wScratch, [xTable, xEntry] (with "lsl #1" for ldrh).
665 /// add xDest, xDest, xScratch, lsl #2
666 void AArch64AsmPrinter::LowerJumpTableDestSmall(llvm::MCStreamer &OutStreamer,
667  const llvm::MachineInstr &MI) {
668  unsigned DestReg = MI.getOperand(0).getReg();
669  unsigned ScratchReg = MI.getOperand(1).getReg();
670  unsigned ScratchRegW =
671  STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
672  unsigned TableReg = MI.getOperand(2).getReg();
673  unsigned EntryReg = MI.getOperand(3).getReg();
674  int JTIdx = MI.getOperand(4).getIndex();
675  bool IsByteEntry = MI.getOpcode() == AArch64::JumpTableDest8;
676 
677  // This has to be first because the compression pass based its reachability
678  // calculations on the start of the JumpTableDest instruction.
679  auto Label =
680  MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
681  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
682  .addReg(DestReg)
683  .addExpr(MCSymbolRefExpr::create(
684  Label, MF->getContext())));
685 
686  // Load the number of instruction-steps to offset from the label.
687  unsigned LdrOpcode = IsByteEntry ? AArch64::LDRBBroX : AArch64::LDRHHroX;
688  EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
689  .addReg(ScratchRegW)
690  .addReg(TableReg)
691  .addReg(EntryReg)
692  .addImm(0)
693  .addImm(IsByteEntry ? 0 : 1));
694 
695  // Multiply the steps by 4 and add to the already materialized base label
696  // address.
697  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
698  .addReg(DestReg)
699  .addReg(DestReg)
700  .addReg(ScratchReg)
701  .addImm(2));
702 }
703 
704 void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
705  const MachineInstr &MI) {
706  unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
707 
708  SM.recordStackMap(MI);
709  assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
710 
711  // Scan ahead to trim the shadow.
712  const MachineBasicBlock &MBB = *MI.getParent();
714  ++MII;
715  while (NumNOPBytes > 0) {
716  if (MII == MBB.end() || MII->isCall() ||
717  MII->getOpcode() == AArch64::DBG_VALUE ||
718  MII->getOpcode() == TargetOpcode::PATCHPOINT ||
719  MII->getOpcode() == TargetOpcode::STACKMAP)
720  break;
721  ++MII;
722  NumNOPBytes -= 4;
723  }
724 
725  // Emit nops.
726  for (unsigned i = 0; i < NumNOPBytes; i += 4)
727  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
728 }
729 
730 // Lower a patchpoint of the form:
731 // [<def>], <id>, <numBytes>, <target>, <numArgs>
732 void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
733  const MachineInstr &MI) {
734  SM.recordPatchPoint(MI);
735 
736  PatchPointOpers Opers(&MI);
737 
738  int64_t CallTarget = Opers.getCallTarget().getImm();
739  unsigned EncodedBytes = 0;
740  if (CallTarget) {
741  assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
742  "High 16 bits of call target should be zero.");
743  unsigned ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
744  EncodedBytes = 16;
745  // Materialize the jump address:
746  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVZXi)
747  .addReg(ScratchReg)
748  .addImm((CallTarget >> 32) & 0xFFFF)
749  .addImm(32));
750  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
751  .addReg(ScratchReg)
752  .addReg(ScratchReg)
753  .addImm((CallTarget >> 16) & 0xFFFF)
754  .addImm(16));
755  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
756  .addReg(ScratchReg)
757  .addReg(ScratchReg)
758  .addImm(CallTarget & 0xFFFF)
759  .addImm(0));
760  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
761  }
762  // Emit padding.
763  unsigned NumBytes = Opers.getNumPatchBytes();
764  assert(NumBytes >= EncodedBytes &&
765  "Patchpoint can't request size less than the length of a call.");
766  assert((NumBytes - EncodedBytes) % 4 == 0 &&
767  "Invalid number of NOP bytes requested!");
768  for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
769  EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
770 }
771 
772 void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) {
773  unsigned DestReg = MI.getOperand(0).getReg();
774  if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) {
775  // Convert H/S/D register to corresponding Q register
776  if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
777  DestReg = AArch64::Q0 + (DestReg - AArch64::H0);
778  else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
779  DestReg = AArch64::Q0 + (DestReg - AArch64::S0);
780  else {
781  assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
782  DestReg = AArch64::Q0 + (DestReg - AArch64::D0);
783  }
784  MCInst MOVI;
785  MOVI.setOpcode(AArch64::MOVIv2d_ns);
786  MOVI.addOperand(MCOperand::createReg(DestReg));
787  MOVI.addOperand(MCOperand::createImm(0));
788  EmitToStreamer(*OutStreamer, MOVI);
789  } else {
790  MCInst FMov;
791  switch (MI.getOpcode()) {
792  default: llvm_unreachable("Unexpected opcode");
793  case AArch64::FMOVH0:
794  FMov.setOpcode(AArch64::FMOVWHr);
795  FMov.addOperand(MCOperand::createReg(DestReg));
796  FMov.addOperand(MCOperand::createReg(AArch64::WZR));
797  break;
798  case AArch64::FMOVS0:
799  FMov.setOpcode(AArch64::FMOVWSr);
800  FMov.addOperand(MCOperand::createReg(DestReg));
801  FMov.addOperand(MCOperand::createReg(AArch64::WZR));
802  break;
803  case AArch64::FMOVD0:
804  FMov.setOpcode(AArch64::FMOVXDr);
805  FMov.addOperand(MCOperand::createReg(DestReg));
806  FMov.addOperand(MCOperand::createReg(AArch64::XZR));
807  break;
808  }
809  EmitToStreamer(*OutStreamer, FMov);
810  }
811 }
812 
813 // Simple pseudo-instructions have their lowering (with expansion to real
814 // instructions) auto-generated.
815 #include "AArch64GenMCPseudoLowering.inc"
816 
817 void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
818  // Do any auto-generated pseudo lowerings.
819  if (emitPseudoExpansionLowering(*OutStreamer, MI))
820  return;
821 
822  if (AArch64FI->getLOHRelated().count(MI)) {
823  // Generate a label for LOH related instruction
824  MCSymbol *LOHLabel = createTempSymbol("loh");
825  // Associate the instruction with the label
826  LOHInstToLabel[MI] = LOHLabel;
827  OutStreamer->EmitLabel(LOHLabel);
828  }
829 
831  static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
832  // Do any manual lowerings.
833  switch (MI->getOpcode()) {
834  default:
835  break;
836  case AArch64::MOVMCSym: {
837  unsigned DestReg = MI->getOperand(0).getReg();
838  const MachineOperand &MO_Sym = MI->getOperand(1);
839  MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
840  MCOperand Hi_MCSym, Lo_MCSym;
841 
842  Hi_MOSym.setTargetFlags(AArch64II::MO_G1 | AArch64II::MO_S);
844 
845  MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
846  MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
847 
848  MCInst MovZ;
849  MovZ.setOpcode(AArch64::MOVZXi);
850  MovZ.addOperand(MCOperand::createReg(DestReg));
851  MovZ.addOperand(Hi_MCSym);
853  EmitToStreamer(*OutStreamer, MovZ);
854 
855  MCInst MovK;
856  MovK.setOpcode(AArch64::MOVKXi);
857  MovK.addOperand(MCOperand::createReg(DestReg));
858  MovK.addOperand(MCOperand::createReg(DestReg));
859  MovK.addOperand(Lo_MCSym);
861  EmitToStreamer(*OutStreamer, MovK);
862  return;
863  }
864  case AArch64::MOVIv2d_ns:
865  // If the target has <rdar://problem/16473581>, lower this
866  // instruction to movi.16b instead.
867  if (STI->hasZeroCycleZeroingFPWorkaround() &&
868  MI->getOperand(1).getImm() == 0) {
869  MCInst TmpInst;
870  TmpInst.setOpcode(AArch64::MOVIv16b_ns);
873  EmitToStreamer(*OutStreamer, TmpInst);
874  return;
875  }
876  break;
877 
878  case AArch64::DBG_VALUE: {
879  if (isVerbose() && OutStreamer->hasRawTextSupport()) {
880  SmallString<128> TmpStr;
881  raw_svector_ostream OS(TmpStr);
882  PrintDebugValueComment(MI, OS);
883  OutStreamer->EmitRawText(StringRef(OS.str()));
884  }
885  return;
886 
887  case AArch64::EMITBKEY: {
888  ExceptionHandling ExceptionHandlingType = MAI->getExceptionHandlingType();
889  if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
890  ExceptionHandlingType != ExceptionHandling::ARM)
891  return;
892 
893  if (needsCFIMoves() == CFI_M_None)
894  return;
895 
896  OutStreamer->EmitCFIBKeyFrame();
897  return;
898  }
899  }
900 
901  // Tail calls use pseudo instructions so they have the proper code-gen
902  // attributes (isCall, isReturn, etc.). We lower them to the real
903  // instruction here.
904  case AArch64::TCRETURNri:
905  case AArch64::TCRETURNriBTI:
906  case AArch64::TCRETURNriALL: {
907  MCInst TmpInst;
908  TmpInst.setOpcode(AArch64::BR);
910  EmitToStreamer(*OutStreamer, TmpInst);
911  return;
912  }
913  case AArch64::TCRETURNdi: {
914  MCOperand Dest;
915  MCInstLowering.lowerOperand(MI->getOperand(0), Dest);
916  MCInst TmpInst;
917  TmpInst.setOpcode(AArch64::B);
918  TmpInst.addOperand(Dest);
919  EmitToStreamer(*OutStreamer, TmpInst);
920  return;
921  }
923  /// lower this to:
924  /// adrp x0, :tlsdesc:var
925  /// ldr x1, [x0, #:tlsdesc_lo12:var]
926  /// add x0, x0, #:tlsdesc_lo12:var
927  /// .tlsdesccall var
928  /// blr x1
929  /// (TPIDR_EL0 offset now in x0)
930  const MachineOperand &MO_Sym = MI->getOperand(0);
931  MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
932  MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
933  MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
935  MCInstLowering.lowerOperand(MO_Sym, Sym);
936  MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
937  MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
938 
939  MCInst Adrp;
940  Adrp.setOpcode(AArch64::ADRP);
941  Adrp.addOperand(MCOperand::createReg(AArch64::X0));
942  Adrp.addOperand(SymTLSDesc);
943  EmitToStreamer(*OutStreamer, Adrp);
944 
945  MCInst Ldr;
946  Ldr.setOpcode(AArch64::LDRXui);
947  Ldr.addOperand(MCOperand::createReg(AArch64::X1));
948  Ldr.addOperand(MCOperand::createReg(AArch64::X0));
949  Ldr.addOperand(SymTLSDescLo12);
951  EmitToStreamer(*OutStreamer, Ldr);
952 
953  MCInst Add;
954  Add.setOpcode(AArch64::ADDXri);
955  Add.addOperand(MCOperand::createReg(AArch64::X0));
956  Add.addOperand(MCOperand::createReg(AArch64::X0));
957  Add.addOperand(SymTLSDescLo12);
959  EmitToStreamer(*OutStreamer, Add);
960 
961  // Emit a relocation-annotation. This expands to no code, but requests
962  // the following instruction gets an R_AARCH64_TLSDESC_CALL.
963  MCInst TLSDescCall;
964  TLSDescCall.setOpcode(AArch64::TLSDESCCALL);
965  TLSDescCall.addOperand(Sym);
966  EmitToStreamer(*OutStreamer, TLSDescCall);
967 
968  MCInst Blr;
969  Blr.setOpcode(AArch64::BLR);
970  Blr.addOperand(MCOperand::createReg(AArch64::X1));
971  EmitToStreamer(*OutStreamer, Blr);
972 
973  return;
974  }
975 
976  case AArch64::JumpTableDest32: {
977  // We want:
978  // ldrsw xScratch, [xTable, xEntry, lsl #2]
979  // add xDest, xTable, xScratch
980  unsigned DestReg = MI->getOperand(0).getReg(),
981  ScratchReg = MI->getOperand(1).getReg(),
982  TableReg = MI->getOperand(2).getReg(),
983  EntryReg = MI->getOperand(3).getReg();
984  EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX)
985  .addReg(ScratchReg)
986  .addReg(TableReg)
987  .addReg(EntryReg)
988  .addImm(0)
989  .addImm(1));
990  EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs)
991  .addReg(DestReg)
992  .addReg(TableReg)
993  .addReg(ScratchReg)
994  .addImm(0));
995  return;
996  }
997  case AArch64::JumpTableDest16:
998  case AArch64::JumpTableDest8:
999  LowerJumpTableDestSmall(*OutStreamer, *MI);
1000  return;
1001 
1002  case AArch64::FMOVH0:
1003  case AArch64::FMOVS0:
1004  case AArch64::FMOVD0:
1005  EmitFMov0(*MI);
1006  return;
1007 
1008  case TargetOpcode::STACKMAP:
1009  return LowerSTACKMAP(*OutStreamer, SM, *MI);
1010 
1011  case TargetOpcode::PATCHPOINT:
1012  return LowerPATCHPOINT(*OutStreamer, SM, *MI);
1013 
1014  case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
1015  LowerPATCHABLE_FUNCTION_ENTER(*MI);
1016  return;
1017 
1018  case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1019  LowerPATCHABLE_FUNCTION_EXIT(*MI);
1020  return;
1021 
1022  case TargetOpcode::PATCHABLE_TAIL_CALL:
1023  LowerPATCHABLE_TAIL_CALL(*MI);
1024  return;
1025 
1026  case AArch64::HWASAN_CHECK_MEMACCESS:
1027  LowerHWASAN_CHECK_MEMACCESS(*MI);
1028  return;
1029 
1030  case AArch64::SEH_StackAlloc:
1032  return;
1033 
1034  case AArch64::SEH_SaveFPLR:
1036  return;
1037 
1038  case AArch64::SEH_SaveFPLR_X:
1039  assert(MI->getOperand(0).getImm() < 0 &&
1040  "Pre increment SEH opcode must have a negative offset");
1042  return;
1043 
1044  case AArch64::SEH_SaveReg:
1046  MI->getOperand(1).getImm());
1047  return;
1048 
1049  case AArch64::SEH_SaveReg_X:
1050  assert(MI->getOperand(1).getImm() < 0 &&
1051  "Pre increment SEH opcode must have a negative offset");
1053  -MI->getOperand(1).getImm());
1054  return;
1055 
1056  case AArch64::SEH_SaveRegP:
1057  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1058  "Non-consecutive registers not allowed for save_regp");
1060  MI->getOperand(2).getImm());
1061  return;
1062 
1063  case AArch64::SEH_SaveRegP_X:
1064  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1065  "Non-consecutive registers not allowed for save_regp_x");
1066  assert(MI->getOperand(2).getImm() < 0 &&
1067  "Pre increment SEH opcode must have a negative offset");
1069  -MI->getOperand(2).getImm());
1070  return;
1071 
1072  case AArch64::SEH_SaveFReg:
1074  MI->getOperand(1).getImm());
1075  return;
1076 
1077  case AArch64::SEH_SaveFReg_X:
1078  assert(MI->getOperand(1).getImm() < 0 &&
1079  "Pre increment SEH opcode must have a negative offset");
1081  -MI->getOperand(1).getImm());
1082  return;
1083 
1084  case AArch64::SEH_SaveFRegP:
1085  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1086  "Non-consecutive registers not allowed for save_regp");
1088  MI->getOperand(2).getImm());
1089  return;
1090 
1091  case AArch64::SEH_SaveFRegP_X:
1092  assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
1093  "Non-consecutive registers not allowed for save_regp_x");
1094  assert(MI->getOperand(2).getImm() < 0 &&
1095  "Pre increment SEH opcode must have a negative offset");
1097  -MI->getOperand(2).getImm());
1098  return;
1099 
1100  case AArch64::SEH_SetFP:
1101  TS->EmitARM64WinCFISetFP();
1102  return;
1103 
1104  case AArch64::SEH_AddFP:
1105  TS->EmitARM64WinCFIAddFP(MI->getOperand(0).getImm());
1106  return;
1107 
1108  case AArch64::SEH_Nop:
1109  TS->EmitARM64WinCFINop();
1110  return;
1111 
1112  case AArch64::SEH_PrologEnd:
1114  return;
1115 
1116  case AArch64::SEH_EpilogStart:
1118  return;
1119 
1120  case AArch64::SEH_EpilogEnd:
1122  return;
1123  }
1124 
1125  // Finally, do the automated lowerings for everything else.
1126  MCInst TmpInst;
1127  MCInstLowering.Lower(MI, TmpInst);
1128  EmitToStreamer(*OutStreamer, TmpInst);
1129 }
1130 
1131 // Force static initialization.
1136 }
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:894
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:323
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:618
Target & getTheAArch64leTarget()
unsigned getRegister(unsigned i) const
Return the specified register in the class.
unsigned getReg() const
getReg - Returns the register number.
unsigned Reg
unsigned getSubReg() const
virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol)
Start emitting COFF symbol definition.
Definition: MCStreamer.cpp:999
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:509
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: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:165
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:247
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:546
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:364
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
virtual void EmitARM64WinCFISaveFRegX(unsigned Reg, int Offset)
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:290
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:188
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:257
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:628
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:541
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)
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:534
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:255
Representation of each machine instruction.
Definition: MachineInstr.h:63
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
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:203
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:72
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:351
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)
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.
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:163
const MDNode * getMetadata() const
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