LLVM  15.0.0git
AArch64AsmBackend.cpp
Go to the documentation of this file.
1 //===-- AArch64AsmBackend.cpp - AArch64 Assembler Backend -----------------===//
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 
12 #include "Utils/AArch64BaseInfo.h"
13 #include "llvm/ADT/Triple.h"
15 #include "llvm/MC/MCAsmBackend.h"
16 #include "llvm/MC/MCAssembler.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCDirectives.h"
21 #include "llvm/MC/MCObjectWriter.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/MC/MCSectionELF.h"
24 #include "llvm/MC/MCSectionMachO.h"
27 #include "llvm/MC/MCValue.h"
28 #include "llvm/MC/TargetRegistry.h"
31 using namespace llvm;
32 
33 namespace {
34 
35 class AArch64AsmBackend : public MCAsmBackend {
36  static const unsigned PCRelFlagVal =
38 protected:
39  Triple TheTriple;
40 
41 public:
42  AArch64AsmBackend(const Target &T, const Triple &TT, bool IsLittleEndian)
43  : MCAsmBackend(IsLittleEndian ? support::little : support::big),
44  TheTriple(TT) {}
45 
46  unsigned getNumFixupKinds() const override {
48  }
49 
50  Optional<MCFixupKind> getFixupKind(StringRef Name) const override;
51 
52  const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
53  const static MCFixupKindInfo Infos[AArch64::NumTargetFixupKinds] = {
54  // This table *must* be in the order that the fixup_* kinds are defined
55  // in AArch64FixupKinds.h.
56  //
57  // Name Offset (bits) Size (bits) Flags
58  {"fixup_aarch64_pcrel_adr_imm21", 0, 32, PCRelFlagVal},
59  {"fixup_aarch64_pcrel_adrp_imm21", 0, 32, PCRelFlagVal},
60  {"fixup_aarch64_add_imm12", 10, 12, 0},
61  {"fixup_aarch64_ldst_imm12_scale1", 10, 12, 0},
62  {"fixup_aarch64_ldst_imm12_scale2", 10, 12, 0},
63  {"fixup_aarch64_ldst_imm12_scale4", 10, 12, 0},
64  {"fixup_aarch64_ldst_imm12_scale8", 10, 12, 0},
65  {"fixup_aarch64_ldst_imm12_scale16", 10, 12, 0},
66  {"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal},
67  {"fixup_aarch64_movw", 5, 16, 0},
68  {"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal},
69  {"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal},
70  {"fixup_aarch64_pcrel_branch26", 0, 26, PCRelFlagVal},
71  {"fixup_aarch64_pcrel_call26", 0, 26, PCRelFlagVal}};
72 
73  // Fixup kinds from .reloc directive are like R_AARCH64_NONE. They do not
74  // require any extra processing.
77 
80 
81  assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
82  "Invalid kind!");
83  return Infos[Kind - FirstTargetFixupKind];
84  }
85 
86  void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
88  uint64_t Value, bool IsResolved,
89  const MCSubtargetInfo *STI) const override;
90 
91  bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
92  const MCRelaxableFragment *DF,
93  const MCAsmLayout &Layout) const override;
94  void relaxInstruction(MCInst &Inst,
95  const MCSubtargetInfo &STI) const override;
96  bool writeNopData(raw_ostream &OS, uint64_t Count,
97  const MCSubtargetInfo *STI) const override;
98 
99  unsigned getFixupKindContainereSizeInBytes(unsigned Kind) const;
100 
101  bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
102  const MCValue &Target) override;
103 };
104 
105 } // end anonymous namespace
106 
107 /// The number of bytes the fixup may change.
108 static unsigned getFixupKindNumBytes(unsigned Kind) {
109  switch (Kind) {
110  default:
111  llvm_unreachable("Unknown fixup kind!");
112 
113  case FK_Data_1:
114  return 1;
115 
116  case FK_Data_2:
117  case FK_SecRel_2:
118  return 2;
119 
130  return 3;
131 
136  case FK_Data_4:
137  case FK_SecRel_4:
138  return 4;
139 
140  case FK_Data_8:
141  return 8;
142  }
143 }
144 
145 static unsigned AdrImmBits(unsigned Value) {
146  unsigned lo2 = Value & 0x3;
147  unsigned hi19 = (Value & 0x1ffffc) >> 2;
148  return (hi19 << 5) | (lo2 << 29);
149 }
150 
151 static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
152  uint64_t Value, MCContext &Ctx,
153  const Triple &TheTriple, bool IsResolved) {
154  int64_t SignedValue = static_cast<int64_t>(Value);
155  switch (Fixup.getTargetKind()) {
156  default:
157  llvm_unreachable("Unknown fixup kind!");
159  if (SignedValue > 2097151 || SignedValue < -2097152)
160  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
161  return AdrImmBits(Value & 0x1fffffULL);
163  assert(!IsResolved);
164  if (TheTriple.isOSBinFormatCOFF()) {
165  if (!isInt<21>(SignedValue))
166  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
167  return AdrImmBits(Value & 0x1fffffULL);
168  }
169  return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
172  // Signed 21-bit immediate
173  if (SignedValue > 2097151 || SignedValue < -2097152)
174  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
175  if (Value & 0x3)
176  Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
177  // Low two bits are not encoded.
178  return (Value >> 2) & 0x7ffff;
181  if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
182  Value &= 0xfff;
183  // Unsigned 12-bit immediate
184  if (Value >= 0x1000)
185  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
186  return Value;
188  if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
189  Value &= 0xfff;
190  // Unsigned 12-bit immediate which gets multiplied by 2
191  if (Value >= 0x2000)
192  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
193  if (Value & 0x1)
194  Ctx.reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
195  return Value >> 1;
197  if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
198  Value &= 0xfff;
199  // Unsigned 12-bit immediate which gets multiplied by 4
200  if (Value >= 0x4000)
201  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
202  if (Value & 0x3)
203  Ctx.reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
204  return Value >> 2;
206  if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
207  Value &= 0xfff;
208  // Unsigned 12-bit immediate which gets multiplied by 8
209  if (Value >= 0x8000)
210  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
211  if (Value & 0x7)
212  Ctx.reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
213  return Value >> 3;
215  if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
216  Value &= 0xfff;
217  // Unsigned 12-bit immediate which gets multiplied by 16
218  if (Value >= 0x10000)
219  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
220  if (Value & 0xf)
221  Ctx.reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
222  return Value >> 4;
225  static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
228  if (!RefKind) {
229  // The fixup is an expression
230  if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
231  Ctx.reportError(Fixup.getLoc(),
232  "fixup value out of range [-0xFFFF, 0xFFFF]");
233 
234  // Invert the negative immediate because it will feed into a MOVN.
235  if (SignedValue < 0)
236  SignedValue = ~SignedValue;
237  Value = static_cast<uint64_t>(SignedValue);
238  } else
239  // VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
240  // ever be resolved in the assembler.
241  Ctx.reportError(Fixup.getLoc(),
242  "relocation for a thread-local variable points to an "
243  "absolute symbol");
244  return Value;
245  }
246 
247  if (!IsResolved) {
248  // FIXME: Figure out when this can actually happen, and verify our
249  // behavior.
250  Ctx.reportError(Fixup.getLoc(), "unresolved movw fixup not yet "
251  "implemented");
252  return Value;
253  }
254 
256  switch (AArch64MCExpr::getAddressFrag(RefKind)) {
258  break;
260  SignedValue = SignedValue >> 16;
261  break;
263  SignedValue = SignedValue >> 32;
264  break;
266  SignedValue = SignedValue >> 48;
267  break;
268  default:
269  llvm_unreachable("Variant kind doesn't correspond to fixup");
270  }
271 
272  } else {
273  switch (AArch64MCExpr::getAddressFrag(RefKind)) {
275  break;
277  Value = Value >> 16;
278  break;
280  Value = Value >> 32;
281  break;
283  Value = Value >> 48;
284  break;
285  default:
286  llvm_unreachable("Variant kind doesn't correspond to fixup");
287  }
288  }
289 
290  if (RefKind & AArch64MCExpr::VK_NC) {
291  Value &= 0xFFFF;
292  }
294  if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
295  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
296 
297  // Invert the negative immediate because it will feed into a MOVN.
298  if (SignedValue < 0)
299  SignedValue = ~SignedValue;
300  Value = static_cast<uint64_t>(SignedValue);
301  }
302  else if (Value > 0xFFFF) {
303  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
304  }
305  return Value;
306  }
308  // Signed 16-bit immediate
309  if (SignedValue > 32767 || SignedValue < -32768)
310  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
311  // Low two bits are not encoded (4-byte alignment assumed).
312  if (Value & 0x3)
313  Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
314  return (Value >> 2) & 0x3fff;
317  // Signed 28-bit immediate
318  if (SignedValue > 134217727 || SignedValue < -134217728)
319  Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
320  // Low two bits are not encoded (4-byte alignment assumed).
321  if (Value & 0x3)
322  Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
323  return (Value >> 2) & 0x3ffffff;
324  case FK_Data_1:
325  case FK_Data_2:
326  case FK_Data_4:
327  case FK_Data_8:
328  case FK_SecRel_2:
329  case FK_SecRel_4:
330  return Value;
331  }
332 }
333 
334 Optional<MCFixupKind> AArch64AsmBackend::getFixupKind(StringRef Name) const {
335  if (!TheTriple.isOSBinFormatELF())
336  return None;
337 
339 #define ELF_RELOC(X, Y) .Case(#X, Y)
340 #include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
341 #undef ELF_RELOC
342  .Case("BFD_RELOC_NONE", ELF::R_AARCH64_NONE)
343  .Case("BFD_RELOC_16", ELF::R_AARCH64_ABS16)
344  .Case("BFD_RELOC_32", ELF::R_AARCH64_ABS32)
345  .Case("BFD_RELOC_64", ELF::R_AARCH64_ABS64)
346  .Default(-1u);
347  if (Type == -1u)
348  return None;
349  return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
350 }
351 
352 /// getFixupKindContainereSizeInBytes - The number of bytes of the
353 /// container involved in big endian or 0 if the item is little endian
354 unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) const {
355  if (Endian == support::little)
356  return 0;
357 
358  switch (Kind) {
359  default:
360  llvm_unreachable("Unknown fixup kind!");
361 
362  case FK_Data_1:
363  return 1;
364  case FK_Data_2:
365  return 2;
366  case FK_Data_4:
367  return 4;
368  case FK_Data_8:
369  return 8;
370 
385  // Instructions are always little endian
386  return 0;
387  }
388 }
389 
390 void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
391  const MCValue &Target,
393  bool IsResolved,
394  const MCSubtargetInfo *STI) const {
395  if (!Value)
396  return; // Doesn't change encoding.
397  unsigned Kind = Fixup.getKind();
399  return;
400  unsigned NumBytes = getFixupKindNumBytes(Kind);
401  MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
402  MCContext &Ctx = Asm.getContext();
403  int64_t SignedValue = static_cast<int64_t>(Value);
404  // Apply any target-specific value adjustments.
405  Value = adjustFixupValue(Fixup, Target, Value, Ctx, TheTriple, IsResolved);
406 
407  // Shift the value into position.
408  Value <<= Info.TargetOffset;
409 
410  unsigned Offset = Fixup.getOffset();
411  assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
412 
413  // Used to point to big endian bytes.
414  unsigned FulleSizeInBytes = getFixupKindContainereSizeInBytes(Fixup.getKind());
415 
416  // For each byte of the fragment that the fixup touches, mask in the
417  // bits from the fixup value.
418  if (FulleSizeInBytes == 0) {
419  // Handle as little-endian
420  for (unsigned i = 0; i != NumBytes; ++i) {
421  Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
422  }
423  } else {
424  // Handle as big-endian
425  assert((Offset + FulleSizeInBytes) <= Data.size() && "Invalid fixup size!");
426  assert(NumBytes <= FulleSizeInBytes && "Invalid fixup size!");
427  for (unsigned i = 0; i != NumBytes; ++i) {
428  unsigned Idx = FulleSizeInBytes - 1 - i;
429  Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
430  }
431  }
432 
433  // FIXME: getFixupKindInfo() and getFixupKindNumBytes() could be fixed to
434  // handle this more cleanly. This may affect the output of -show-mc-encoding.
436  static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
438  (!RefKind && Fixup.getTargetKind() == AArch64::fixup_aarch64_movw)) {
439  // If the immediate is negative, generate MOVN else MOVZ.
440  // (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
441  if (SignedValue < 0)
442  Data[Offset + 3] &= ~(1 << 6);
443  else
444  Data[Offset + 3] |= (1 << 6);
445  }
446 }
447 
448 bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
449  uint64_t Value,
450  const MCRelaxableFragment *DF,
451  const MCAsmLayout &Layout) const {
452  // FIXME: This isn't correct for AArch64. Just moving the "generic" logic
453  // into the targets for now.
454  //
455  // Relax if the value is too big for a (signed) i8.
456  return int64_t(Value) != int64_t(int8_t(Value));
457 }
458 
459 void AArch64AsmBackend::relaxInstruction(MCInst &Inst,
460  const MCSubtargetInfo &STI) const {
461  llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented");
462 }
463 
464 bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
465  const MCSubtargetInfo *STI) const {
466  // If the count is not 4-byte aligned, we must be writing data into the text
467  // section (otherwise we have unaligned instructions, and thus have far
468  // bigger problems), so just write zeros instead.
469  OS.write_zeros(Count % 4);
470 
471  // We are properly aligned, so write NOPs as requested.
472  Count /= 4;
473  for (uint64_t i = 0; i != Count; ++i)
474  OS.write("\x1f\x20\x03\xd5", 4);
475  return true;
476 }
477 
478 bool AArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm,
479  const MCFixup &Fixup,
480  const MCValue &Target) {
481  unsigned Kind = Fixup.getKind();
483  return true;
484 
485  // The ADRP instruction adds some multiple of 0x1000 to the current PC &
486  // ~0xfff. This means that the required offset to reach a symbol can vary by
487  // up to one step depending on where the ADRP is in memory. For example:
488  //
489  // ADRP x0, there
490  // there:
491  //
492  // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and
493  // we'll need that as an offset. At any other address "there" will be in the
494  // same page as the ADRP and the instruction should encode 0x0. Assuming the
495  // section isn't 0x1000-aligned, we therefore need to delegate this decision
496  // to the linker -- a relocation!
498  return true;
499 
500  return false;
501 }
502 
503 namespace {
504 
505 namespace CU {
506 
507 /// Compact unwind encoding values.
509  /// A "frameless" leaf function, where no non-volatile registers are
510  /// saved. The return remains in LR throughout the function.
511  UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
512 
513  /// No compact unwind encoding available. Instead the low 23-bits of
514  /// the compact unwind encoding is the offset of the DWARF FDE in the
515  /// __eh_frame section. This mode is never used in object files. It is only
516  /// generated by the linker in final linked images, which have only DWARF info
517  /// for a function.
518  UNWIND_ARM64_MODE_DWARF = 0x03000000,
519 
520  /// This is a standard arm64 prologue where FP/LR are immediately
521  /// pushed on the stack, then SP is copied to FP. If there are any
522  /// non-volatile register saved, they are copied into the stack fame in pairs
523  /// in a contiguous ranger right below the saved FP/LR pair. Any subset of the
524  /// five X pairs and four D pairs can be saved, but the memory layout must be
525  /// in register number order.
526  UNWIND_ARM64_MODE_FRAME = 0x04000000,
527 
528  /// Frame register pair encodings.
529  UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
530  UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
531  UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
532  UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
533  UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
534  UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
535  UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
536  UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
537  UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800
538 };
539 
540 } // end CU namespace
541 
542 // FIXME: This should be in a separate file.
543 class DarwinAArch64AsmBackend : public AArch64AsmBackend {
544  const MCRegisterInfo &MRI;
545 
546  /// Encode compact unwind stack adjustment for frameless functions.
547  /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
548  /// The stack size always needs to be 16 byte aligned.
549  uint32_t encodeStackAdjustment(uint32_t StackSize) const {
550  return (StackSize / 16) << 12;
551  }
552 
553 public:
554  DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
555  const MCRegisterInfo &MRI)
556  : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {}
557 
558  std::unique_ptr<MCObjectTargetWriter>
559  createObjectTargetWriter() const override {
561  uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TheTriple));
562  return createAArch64MachObjectWriter(CPUType, CPUSubType,
563  TheTriple.isArch32Bit());
564  }
565 
566  /// Generate the compact unwind encoding from the CFI directives.
567  uint32_t generateCompactUnwindEncoding(
568  ArrayRef<MCCFIInstruction> Instrs) const override {
569  if (Instrs.empty())
570  return CU::UNWIND_ARM64_MODE_FRAMELESS;
571 
572  bool HasFP = false;
573  unsigned StackSize = 0;
574 
575  uint32_t CompactUnwindEncoding = 0;
576  int CurOffset = 0;
577  for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
578  const MCCFIInstruction &Inst = Instrs[i];
579 
580  switch (Inst.getOperation()) {
581  default:
582  // Cannot handle this directive: bail out.
583  return CU::UNWIND_ARM64_MODE_DWARF;
585  // Defines a frame pointer.
586  unsigned XReg =
587  getXRegFromWReg(*MRI.getLLVMRegNum(Inst.getRegister(), true));
588 
589  // Other CFA registers than FP are not supported by compact unwind.
590  // Fallback on DWARF.
591  // FIXME: When opt-remarks are supported in MC, add a remark to notify
592  // the user.
593  if (XReg != AArch64::FP)
594  return CU::UNWIND_ARM64_MODE_DWARF;
595 
596  if (i + 2 >= e)
597  return CU::UNWIND_ARM64_MODE_DWARF;
598 
599  const MCCFIInstruction &LRPush = Instrs[++i];
601  return CU::UNWIND_ARM64_MODE_DWARF;
602  const MCCFIInstruction &FPPush = Instrs[++i];
604  return CU::UNWIND_ARM64_MODE_DWARF;
605 
606  if (FPPush.getOffset() + 8 != LRPush.getOffset())
607  return CU::UNWIND_ARM64_MODE_DWARF;
608  CurOffset = FPPush.getOffset();
609 
610  unsigned LRReg = *MRI.getLLVMRegNum(LRPush.getRegister(), true);
611  unsigned FPReg = *MRI.getLLVMRegNum(FPPush.getRegister(), true);
612 
613  LRReg = getXRegFromWReg(LRReg);
614  FPReg = getXRegFromWReg(FPReg);
615 
616  if (LRReg != AArch64::LR || FPReg != AArch64::FP)
617  return CU::UNWIND_ARM64_MODE_DWARF;
618 
619  // Indicate that the function has a frame.
620  CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAME;
621  HasFP = true;
622  break;
623  }
625  if (StackSize != 0)
626  return CU::UNWIND_ARM64_MODE_DWARF;
627  StackSize = std::abs(Inst.getOffset());
628  break;
629  }
631  // Registers are saved in pairs. We expect there to be two consecutive
632  // `.cfi_offset' instructions with the appropriate registers specified.
633  unsigned Reg1 = *MRI.getLLVMRegNum(Inst.getRegister(), true);
634  if (i + 1 == e)
635  return CU::UNWIND_ARM64_MODE_DWARF;
636 
637  if (CurOffset != 0 && Inst.getOffset() != CurOffset - 8)
638  return CU::UNWIND_ARM64_MODE_DWARF;
639  CurOffset = Inst.getOffset();
640 
641  const MCCFIInstruction &Inst2 = Instrs[++i];
643  return CU::UNWIND_ARM64_MODE_DWARF;
644  unsigned Reg2 = *MRI.getLLVMRegNum(Inst2.getRegister(), true);
645 
646  if (Inst2.getOffset() != CurOffset - 8)
647  return CU::UNWIND_ARM64_MODE_DWARF;
648  CurOffset = Inst2.getOffset();
649 
650  // N.B. The encodings must be in register number order, and the X
651  // registers before the D registers.
652 
653  // X19/X20 pair = 0x00000001,
654  // X21/X22 pair = 0x00000002,
655  // X23/X24 pair = 0x00000004,
656  // X25/X26 pair = 0x00000008,
657  // X27/X28 pair = 0x00000010
658  Reg1 = getXRegFromWReg(Reg1);
659  Reg2 = getXRegFromWReg(Reg2);
660 
661  if (Reg1 == AArch64::X19 && Reg2 == AArch64::X20 &&
662  (CompactUnwindEncoding & 0xF1E) == 0)
663  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X19_X20_PAIR;
664  else if (Reg1 == AArch64::X21 && Reg2 == AArch64::X22 &&
665  (CompactUnwindEncoding & 0xF1C) == 0)
666  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X21_X22_PAIR;
667  else if (Reg1 == AArch64::X23 && Reg2 == AArch64::X24 &&
668  (CompactUnwindEncoding & 0xF18) == 0)
669  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X23_X24_PAIR;
670  else if (Reg1 == AArch64::X25 && Reg2 == AArch64::X26 &&
671  (CompactUnwindEncoding & 0xF10) == 0)
672  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X25_X26_PAIR;
673  else if (Reg1 == AArch64::X27 && Reg2 == AArch64::X28 &&
674  (CompactUnwindEncoding & 0xF00) == 0)
675  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X27_X28_PAIR;
676  else {
677  Reg1 = getDRegFromBReg(Reg1);
678  Reg2 = getDRegFromBReg(Reg2);
679 
680  // D8/D9 pair = 0x00000100,
681  // D10/D11 pair = 0x00000200,
682  // D12/D13 pair = 0x00000400,
683  // D14/D15 pair = 0x00000800
684  if (Reg1 == AArch64::D8 && Reg2 == AArch64::D9 &&
685  (CompactUnwindEncoding & 0xE00) == 0)
686  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D8_D9_PAIR;
687  else if (Reg1 == AArch64::D10 && Reg2 == AArch64::D11 &&
688  (CompactUnwindEncoding & 0xC00) == 0)
689  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D10_D11_PAIR;
690  else if (Reg1 == AArch64::D12 && Reg2 == AArch64::D13 &&
691  (CompactUnwindEncoding & 0x800) == 0)
692  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D12_D13_PAIR;
693  else if (Reg1 == AArch64::D14 && Reg2 == AArch64::D15)
694  CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D14_D15_PAIR;
695  else
696  // A pair was pushed which we cannot handle.
697  return CU::UNWIND_ARM64_MODE_DWARF;
698  }
699 
700  break;
701  }
702  }
703  }
704 
705  if (!HasFP) {
706  // With compact unwind info we can only represent stack adjustments of up
707  // to 65520 bytes.
708  if (StackSize > 65520)
709  return CU::UNWIND_ARM64_MODE_DWARF;
710 
711  CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAMELESS;
712  CompactUnwindEncoding |= encodeStackAdjustment(StackSize);
713  }
714 
715  return CompactUnwindEncoding;
716  }
717 };
718 
719 } // end anonymous namespace
720 
721 namespace {
722 
723 class ELFAArch64AsmBackend : public AArch64AsmBackend {
724 public:
725  uint8_t OSABI;
726  bool IsILP32;
727 
728  ELFAArch64AsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
729  bool IsLittleEndian, bool IsILP32)
730  : AArch64AsmBackend(T, TT, IsLittleEndian), OSABI(OSABI),
731  IsILP32(IsILP32) {}
732 
733  std::unique_ptr<MCObjectTargetWriter>
734  createObjectTargetWriter() const override {
735  return createAArch64ELFObjectWriter(OSABI, IsILP32);
736  }
737 };
738 
739 }
740 
741 namespace {
742 class COFFAArch64AsmBackend : public AArch64AsmBackend {
743 public:
744  COFFAArch64AsmBackend(const Target &T, const Triple &TheTriple)
745  : AArch64AsmBackend(T, TheTriple, /*IsLittleEndian*/ true) {}
746 
747  std::unique_ptr<MCObjectTargetWriter>
748  createObjectTargetWriter() const override {
750  }
751 };
752 }
753 
755  const MCSubtargetInfo &STI,
756  const MCRegisterInfo &MRI,
757  const MCTargetOptions &Options) {
758  const Triple &TheTriple = STI.getTargetTriple();
759  if (TheTriple.isOSBinFormatMachO()) {
760  return new DarwinAArch64AsmBackend(T, TheTriple, MRI);
761  }
762 
763  if (TheTriple.isOSBinFormatCOFF())
764  return new COFFAArch64AsmBackend(T, TheTriple);
765 
766  assert(TheTriple.isOSBinFormatELF() && "Invalid target");
767 
768  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
769  bool IsILP32 = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32;
770  return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/true,
771  IsILP32);
772 }
773 
775  const MCSubtargetInfo &STI,
776  const MCRegisterInfo &MRI,
777  const MCTargetOptions &Options) {
778  const Triple &TheTriple = STI.getTargetTriple();
779  assert(TheTriple.isOSBinFormatELF() &&
780  "Big endian is only supported for ELF targets!");
781  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
782  bool IsILP32 = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32;
783  return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/false,
784  IsILP32);
785 }
llvm::StringSwitch::Case
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
i
i
Definition: README.txt:29
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::MCRelaxableFragment
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
Definition: MCFragment.h:270
llvm::Triple::GNUILP32
@ GNUILP32
Definition: Triple.h:233
llvm::ARM::PredBlockMask::TT
@ TT
llvm::MCAsmBackend::getFixupKindInfo
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
Definition: MCAsmBackend.cpp:78
llvm::AArch64MCExpr::VK_ABS
@ VK_ABS
Definition: AArch64MCExpr.h:28
MCTargetOptions.h
llvm::Triple::isOSBinFormatCOFF
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Definition: Triple.h:661
T
llvm::raw_ostream::write_zeros
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
Definition: raw_ostream.cpp:501
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:74
llvm::AArch64::fixup_aarch64_pcrel_branch26
@ fixup_aarch64_pcrel_branch26
Definition: AArch64FixupKinds.h:52
llvm::AArch64::fixup_aarch64_add_imm12
@ fixup_aarch64_add_imm12
Definition: AArch64FixupKinds.h:26
llvm::MCCFIInstruction::OpOffset
@ OpOffset
Definition: MCDwarf.h:478
llvm::StringSwitch::Default
LLVM_NODISCARD R Default(T Value)
Definition: StringSwitch.h:183
MCDirectives.h
llvm::AArch64::fixup_aarch64_ldr_pcrel_imm19
@ fixup_aarch64_ldr_pcrel_imm19
Definition: AArch64FixupKinds.h:38
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:140
MCSectionELF.h
llvm::FirstTargetFixupKind
@ FirstTargetFixupKind
Definition: MCFixup.h:45
llvm::AArch64::fixup_aarch64_ldst_imm12_scale2
@ fixup_aarch64_ldst_imm12_scale2
Definition: AArch64FixupKinds.h:30
AArch64MCExpr.h
ErrorHandling.h
llvm::AArch64MCExpr::VK_NC
@ VK_NC
Definition: AArch64MCExpr.h:57
AArch64BaseInfo.h
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
MCAssembler.h
true
basic Basic Alias true
Definition: BasicAliasAnalysis.cpp:1909
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::MachO::CPUType
CPUType
Definition: MachO.h:1441
llvm::Optional
Definition: APInt.h:33
MCFixupKindInfo.h
llvm::AArch64::NumTargetFixupKinds
@ NumTargetFixupKinds
Definition: AArch64FixupKinds.h:60
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::createAArch64WinCOFFObjectWriter
std::unique_ptr< MCObjectTargetWriter > createAArch64WinCOFFObjectWriter()
Definition: AArch64WinCOFFObjectWriter.cpp:162
llvm::MCFixupKindInfo::FKF_IsAlignedDownTo32Bits
@ FKF_IsAlignedDownTo32Bits
Should this fixup kind force a 4-byte aligned effective PC value?
Definition: MCFixupKindInfo.h:22
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::ArrayRef::empty
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:159
llvm::MachO::getCPUType
Expected< uint32_t > getCPUType(const Triple &T)
Definition: MachO.cpp:77
llvm::MCCFIInstruction::OpDefCfa
@ OpDefCfa
Definition: MCDwarf.h:482
llvm::FirstLiteralRelocationKind
@ FirstLiteralRelocationKind
The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....
Definition: MCFixup.h:50
x3
In x86 we generate this spiffy xmm0 xmm0 ret in x86 we generate this which could be xmm1 movss xmm1 xmm0 ret In sse4 we could use insertps to make both better Here s another testcase that could use x3
Definition: README-SSE.txt:547
llvm::FK_Data_4
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
llvm::Triple::isOSBinFormatELF
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition: Triple.h:656
llvm::createAArch64ELFObjectWriter
std::unique_ptr< MCObjectTargetWriter > createAArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32)
Definition: AArch64ELFObjectWriter.cpp:457
llvm::createAArch64MachObjectWriter
std::unique_ptr< MCObjectTargetWriter > createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype, bool IsILP32)
Definition: AArch64MachObjectWriter.cpp:411
llvm::MCAsmBackend
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:42
CompactUnwindEncodings
CompactUnwindEncodings
Compact unwind encoding values.
Definition: AArch64AsmBackend.cpp:508
MCAsmBackend.h
llvm::MutableArrayRef< char >
llvm::FK_SecRel_4
@ FK_SecRel_4
A four-byte section relative fixup.
Definition: MCFixup.h:42
llvm::support::little
@ little
Definition: Endian.h:27
llvm::MCSubtargetInfo::getTargetTriple
const Triple & getTargetTriple() const
Definition: MCSubtargetInfo.h:108
MCContext.h
MCSectionMachO.h
llvm::MCCFIInstruction::getOffset
int getOffset() const
Definition: MCDwarf.h:657
llvm::FK_SecRel_2
@ FK_SecRel_2
A two-byte section relative fixup.
Definition: MCFixup.h:41
MCSubtargetInfo.h
llvm::AArch64MCExpr::VK_G1
@ VK_G1
Definition: AArch64MCExpr.h:46
llvm::codeview::ProcSymFlags::HasFP
@ HasFP
llvm::Triple::isOSBinFormatMachO
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition: Triple.h:669
AArch64FixupKinds.h
llvm::AArch64::fixup_aarch64_pcrel_branch19
@ fixup_aarch64_pcrel_branch19
Definition: AArch64FixupKinds.h:49
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:219
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::MCCFIInstruction::getOperation
OpType getOperation() const
Definition: MCDwarf.h:635
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::MachO::getCPUSubType
Expected< uint32_t > getCPUSubType(const Triple &T)
Definition: MachO.cpp:95
llvm::MCCFIInstruction::getRegister
unsigned getRegister() const
Definition: MCDwarf.h:638
llvm::None
const NoneType None
Definition: None.h:24
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::MCCFIInstruction
Definition: MCDwarf.h:472
DF
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
llvm::AArch64::fixup_aarch64_ldst_imm12_scale8
@ fixup_aarch64_ldst_imm12_scale8
Definition: AArch64FixupKinds.h:32
getFixupKindNumBytes
static unsigned getFixupKindNumBytes(unsigned Kind)
The number of bytes the fixup may change.
Definition: AArch64AsmBackend.cpp:108
llvm::MCAssembler
Definition: MCAssembler.h:73
llvm::AMDGPU::Hwreg::Offset
Offset
Definition: SIDefines.h:409
llvm::MCCFIInstruction::OpDefCfaOffset
@ OpDefCfaOffset
Definition: MCDwarf.h:481
uint64_t
AdrImmBits
static unsigned AdrImmBits(unsigned Value)
Definition: AArch64AsmBackend.cpp:145
llvm::Triple::getOS
OSType getOS() const
Get the parsed operating system type of this triple.
Definition: Triple.h:354
MCELFObjectWriter.h
llvm::Triple::isArch32Bit
bool isArch32Bit() const
Test whether the architecture is 32-bit.
Definition: Triple.cpp:1448
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
llvm::MCFixupKindInfo::FKF_IsPCRel
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
Definition: MCFixupKindInfo.h:19
adjustFixupValue
static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)
Definition: AArch64AsmBackend.cpp:151
MCRegisterInfo.h
llvm::AArch64MCExpr::getAddressFrag
static VariantKind getAddressFrag(VariantKind Kind)
Definition: AArch64MCExpr.h:147
llvm::AArch64::fixup_aarch64_ldst_imm12_scale4
@ fixup_aarch64_ldst_imm12_scale4
Definition: AArch64FixupKinds.h:31
llvm::AArch64::fixup_aarch64_pcrel_call26
@ fixup_aarch64_pcrel_call26
Definition: AArch64FixupKinds.h:56
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MCFixupKindInfo
Target independent information on a fixup kind.
Definition: MCFixupKindInfo.h:15
llvm::MCContext::reportError
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1005
llvm::createAArch64beAsmBackend
MCAsmBackend * createAArch64beAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
Definition: AArch64AsmBackend.cpp:774
llvm::FK_Data_1
@ FK_Data_1
A one-byte fixup.
Definition: MCFixup.h:23
llvm::MCTargetOptions
Definition: MCTargetOptions.h:36
llvm::FK_NONE
@ FK_NONE
A no-op fixup.
Definition: MCFixup.h:22
Triple.h
llvm::AArch64::fixup_aarch64_ldst_imm12_scale1
@ fixup_aarch64_ldst_imm12_scale1
Definition: AArch64FixupKinds.h:29
llvm::MCELFObjectTargetWriter::getOSABI
uint8_t getOSABI() const
Definition: MCELFObjectWriter.h:101
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
Fixup
PowerPC TLS Dynamic Call Fixup
Definition: PPCTLSDynamicCall.cpp:233
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:745
uint32_t
llvm::MCRegisterInfo
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Definition: MCRegisterInfo.h:135
llvm::AArch64::fixup_aarch64_pcrel_branch14
@ fixup_aarch64_pcrel_branch14
Definition: AArch64FixupKinds.h:44
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::getXRegFromWReg
static unsigned getXRegFromWReg(unsigned Reg)
Definition: AArch64BaseInfo.h:69
MCObjectWriter.h
llvm::AArch64::fixup_aarch64_movw
@ fixup_aarch64_movw
Definition: AArch64FixupKinds.h:41
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
EndianStream.h
llvm::MCAsmLayout
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
llvm::AArch64::fixup_aarch64_ldst_imm12_scale16
@ fixup_aarch64_ldst_imm12_scale16
Definition: AArch64FixupKinds.h:33
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::AArch64MCExpr::VK_G3
@ VK_G3
Definition: AArch64MCExpr.h:48
AArch64MCTargetDesc.h
MCValue.h
llvm::MCFixupKind
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
llvm::FK_Data_8
@ FK_Data_8
A eight-byte fixup.
Definition: MCFixup.h:26
llvm::AArch64MCExpr::VariantKind
VariantKind
Definition: AArch64MCExpr.h:24
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
support
Reimplement select in terms of SEL *We would really like to support but we need to prove that the add doesn t need to overflow between the two bit chunks *Implement pre post increment support(e.g. PR935) *Implement smarter const ant generation for binops with large immediates. A few ARMv6T2 ops should be pattern matched
Definition: README.txt:10
llvm::AArch64::fixup_aarch64_pcrel_adrp_imm21
@ fixup_aarch64_pcrel_adrp_imm21
Definition: AArch64FixupKinds.h:22
llvm::Triple::getEnvironment
EnvironmentType getEnvironment() const
Get the parsed environment type of this triple.
Definition: Triple.h:362
llvm::getDRegFromBReg
static unsigned getDRegFromBReg(unsigned Reg)
Definition: AArch64BaseInfo.h:168
llvm::StringSwitch
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
llvm::HexStyle::Asm
@ Asm
0ffh
Definition: MCInstPrinter.h:34
llvm::MCValue
This represents an "assembler immediate".
Definition: MCValue.h:36
MachO.h
llvm::AArch64MCExpr::getSymbolLoc
static VariantKind getSymbolLoc(VariantKind Kind)
Definition: AArch64MCExpr.h:143
llvm::FK_Data_2
@ FK_Data_2
A two-byte fixup.
Definition: MCFixup.h:24
TargetRegistry.h
llvm::abs
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition: APFloat.h:1281
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:76
CU
Definition: AArch64AsmBackend.cpp:505
llvm::MCFixup
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
llvm::AArch64MCExpr::VK_G2
@ VK_G2
Definition: AArch64MCExpr.h:47
llvm::createAArch64leAsmBackend
MCAsmBackend * createAArch64leAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
Definition: AArch64AsmBackend.cpp:754
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::AArch64MCExpr::VK_G0
@ VK_G0
Definition: AArch64MCExpr.h:45
llvm::AArch64MCExpr::VK_SABS
@ VK_SABS
Definition: AArch64MCExpr.h:29
llvm::support::big
@ big
Definition: Endian.h:27
llvm::AArch64::fixup_aarch64_pcrel_adr_imm21
@ fixup_aarch64_pcrel_adr_imm21
Definition: AArch64FixupKinds.h:19