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