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