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