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