LCOV - code coverage report
Current view: top level - lib/Target/AArch64/MCTargetDesc - AArch64AsmBackend.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 178 203 87.7 %
Date: 2018-07-13 00:08:38 Functions: 17 23 73.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- AArch64AsmBackend.cpp - AArch64 Assembler Backend -----------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "AArch64.h"
      11             : #include "AArch64RegisterInfo.h"
      12             : #include "MCTargetDesc/AArch64FixupKinds.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/MCSectionELF.h"
      23             : #include "llvm/MC/MCSectionMachO.h"
      24             : #include "llvm/MC/MCValue.h"
      25             : #include "llvm/Support/ErrorHandling.h"
      26             : using namespace llvm;
      27             : 
      28             : namespace {
      29             : 
      30        5418 : class AArch64AsmBackend : public MCAsmBackend {
      31             :   static const unsigned PCRelFlagVal =
      32             :       MCFixupKindInfo::FKF_IsAlignedDownTo32Bits | MCFixupKindInfo::FKF_IsPCRel;
      33             :   Triple TheTriple;
      34             : 
      35             : public:
      36             :   AArch64AsmBackend(const Target &T, const Triple &TT, bool IsLittleEndian)
      37        2718 :       : MCAsmBackend(IsLittleEndian ? support::little : support::big),
      38        2718 :         TheTriple(TT) {}
      39             : 
      40           0 :   unsigned getNumFixupKinds() const override {
      41           0 :     return AArch64::NumTargetFixupKinds;
      42             :   }
      43             : 
      44        5464 :   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
      45             :     const static MCFixupKindInfo Infos[AArch64::NumTargetFixupKinds] = {
      46             :         // This table *must* be in the order that the fixup_* kinds are defined
      47             :         // in AArch64FixupKinds.h.
      48             :         //
      49             :         // Name                           Offset (bits) Size (bits)     Flags
      50             :         {"fixup_aarch64_pcrel_adr_imm21", 0, 32, PCRelFlagVal},
      51             :         {"fixup_aarch64_pcrel_adrp_imm21", 0, 32, PCRelFlagVal},
      52             :         {"fixup_aarch64_add_imm12", 10, 12, 0},
      53             :         {"fixup_aarch64_ldst_imm12_scale1", 10, 12, 0},
      54             :         {"fixup_aarch64_ldst_imm12_scale2", 10, 12, 0},
      55             :         {"fixup_aarch64_ldst_imm12_scale4", 10, 12, 0},
      56             :         {"fixup_aarch64_ldst_imm12_scale8", 10, 12, 0},
      57             :         {"fixup_aarch64_ldst_imm12_scale16", 10, 12, 0},
      58             :         {"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal},
      59             :         {"fixup_aarch64_movw", 5, 16, 0},
      60             :         {"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal},
      61             :         {"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal},
      62             :         {"fixup_aarch64_pcrel_branch26", 0, 26, PCRelFlagVal},
      63             :         {"fixup_aarch64_pcrel_call26", 0, 26, PCRelFlagVal},
      64             :         {"fixup_aarch64_tlsdesc_call", 0, 0, 0}};
      65             : 
      66        5953 :     if (Kind < FirstTargetFixupKind)
      67        1947 :       return MCAsmBackend::getFixupKindInfo(Kind);
      68             : 
      69             :     assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
      70             :            "Invalid kind!");
      71        4006 :     return Infos[Kind - FirstTargetFixupKind];
      72             :   }
      73             : 
      74             :   void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
      75             :                   const MCValue &Target, MutableArrayRef<char> Data,
      76             :                   uint64_t Value, bool IsResolved,
      77             :                   const MCSubtargetInfo *STI) const override;
      78             : 
      79             :   bool mayNeedRelaxation(const MCInst &Inst,
      80             :                          const MCSubtargetInfo &STI) const override;
      81             :   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
      82             :                             const MCRelaxableFragment *DF,
      83             :                             const MCAsmLayout &Layout) const override;
      84             :   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
      85             :                         MCInst &Res) const override;
      86             :   bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
      87             : 
      88             :   void HandleAssemblerFlag(MCAssemblerFlag Flag) {}
      89             : 
      90             :   unsigned getPointerSize() const { return 8; }
      91             : 
      92             :   unsigned getFixupKindContainereSizeInBytes(unsigned Kind) const;
      93             : 
      94             :   bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
      95             :                              const MCValue &Target) override;
      96             : };
      97             : 
      98             : } // end anonymous namespace
      99             : 
     100             : /// The number of bytes the fixup may change.
     101        1701 : static unsigned getFixupKindNumBytes(unsigned Kind) {
     102        1701 :   switch (Kind) {
     103           0 :   default:
     104           0 :     llvm_unreachable("Unknown fixup kind!");
     105             : 
     106             :   case AArch64::fixup_aarch64_tlsdesc_call:
     107             :     return 0;
     108             : 
     109           3 :   case FK_Data_1:
     110           3 :     return 1;
     111             : 
     112         124 :   case AArch64::fixup_aarch64_movw:
     113             :   case FK_Data_2:
     114             :   case FK_SecRel_2:
     115         124 :     return 2;
     116             : 
     117         642 :   case AArch64::fixup_aarch64_pcrel_branch14:
     118             :   case AArch64::fixup_aarch64_add_imm12:
     119             :   case AArch64::fixup_aarch64_ldst_imm12_scale1:
     120             :   case AArch64::fixup_aarch64_ldst_imm12_scale2:
     121             :   case AArch64::fixup_aarch64_ldst_imm12_scale4:
     122             :   case AArch64::fixup_aarch64_ldst_imm12_scale8:
     123             :   case AArch64::fixup_aarch64_ldst_imm12_scale16:
     124             :   case AArch64::fixup_aarch64_ldr_pcrel_imm19:
     125             :   case AArch64::fixup_aarch64_pcrel_branch19:
     126         642 :     return 3;
     127             : 
     128         706 :   case AArch64::fixup_aarch64_pcrel_adr_imm21:
     129             :   case AArch64::fixup_aarch64_pcrel_adrp_imm21:
     130             :   case AArch64::fixup_aarch64_pcrel_branch26:
     131             :   case AArch64::fixup_aarch64_pcrel_call26:
     132             :   case FK_Data_4:
     133             :   case FK_SecRel_4:
     134         706 :     return 4;
     135             : 
     136         207 :   case FK_Data_8:
     137         207 :     return 8;
     138             :   }
     139             : }
     140             : 
     141             : static unsigned AdrImmBits(unsigned Value) {
     142             :   unsigned lo2 = Value & 0x3;
     143           7 :   unsigned hi19 = (Value & 0x1ffffc) >> 2;
     144           7 :   return (hi19 << 5) | (lo2 << 29);
     145             : }
     146             : 
     147         489 : static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
     148             :                                  MCContext &Ctx, const Triple &TheTriple,
     149             :                                  bool IsResolved) {
     150         489 :   unsigned Kind = Fixup.getKind();
     151             :   int64_t SignedValue = static_cast<int64_t>(Value);
     152         489 :   switch (Kind) {
     153           0 :   default:
     154           0 :     llvm_unreachable("Unknown fixup kind!");
     155           6 :   case AArch64::fixup_aarch64_pcrel_adr_imm21:
     156           6 :     if (SignedValue > 2097151 || SignedValue < -2097152)
     157           2 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     158          12 :     return AdrImmBits(Value & 0x1fffffULL);
     159             :   case AArch64::fixup_aarch64_pcrel_adrp_imm21:
     160             :     assert(!IsResolved);
     161           1 :     if (TheTriple.isOSBinFormatCOFF())
     162           2 :       return AdrImmBits(Value & 0x1fffffULL);
     163           0 :     return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
     164          34 :   case AArch64::fixup_aarch64_ldr_pcrel_imm19:
     165             :   case AArch64::fixup_aarch64_pcrel_branch19:
     166             :     // Signed 21-bit immediate
     167          34 :     if (SignedValue > 2097151 || SignedValue < -2097152)
     168           5 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     169          34 :     if (Value & 0x3)
     170           4 :       Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
     171             :     // Low two bits are not encoded.
     172          34 :     return (Value >> 2) & 0x7ffff;
     173             :   case AArch64::fixup_aarch64_add_imm12:
     174             :   case AArch64::fixup_aarch64_ldst_imm12_scale1:
     175          96 :     if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
     176           2 :       Value &= 0xfff;
     177             :     // Unsigned 12-bit immediate
     178          96 :     if (Value >= 0x1000)
     179          20 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     180             :     return Value;
     181             :   case AArch64::fixup_aarch64_ldst_imm12_scale2:
     182           4 :     if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
     183           0 :       Value &= 0xfff;
     184             :     // Unsigned 12-bit immediate which gets multiplied by 2
     185           4 :     if (Value >= 0x2000)
     186           2 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     187           4 :     if (Value & 0x1)
     188           2 :       Ctx.reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
     189           4 :     return Value >> 1;
     190             :   case AArch64::fixup_aarch64_ldst_imm12_scale4:
     191           4 :     if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
     192           0 :       Value &= 0xfff;
     193             :     // Unsigned 12-bit immediate which gets multiplied by 4
     194           4 :     if (Value >= 0x4000)
     195           2 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     196           4 :     if (Value & 0x3)
     197           2 :       Ctx.reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
     198           4 :     return Value >> 2;
     199             :   case AArch64::fixup_aarch64_ldst_imm12_scale8:
     200           5 :     if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
     201           1 :       Value &= 0xfff;
     202             :     // Unsigned 12-bit immediate which gets multiplied by 8
     203           5 :     if (Value >= 0x8000)
     204           2 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     205           5 :     if (Value & 0x7)
     206           4 :       Ctx.reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
     207           5 :     return Value >> 3;
     208             :   case AArch64::fixup_aarch64_ldst_imm12_scale16:
     209           4 :     if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
     210           0 :       Value &= 0xfff;
     211             :     // Unsigned 12-bit immediate which gets multiplied by 16
     212           4 :     if (Value >= 0x10000)
     213           2 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     214           4 :     if (Value & 0xf)
     215           2 :       Ctx.reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
     216           4 :     return Value >> 4;
     217             :   case AArch64::fixup_aarch64_movw:
     218           0 :     Ctx.reportError(Fixup.getLoc(),
     219             :                     "no resolvable MOVZ/MOVK fixups supported yet");
     220           0 :     return Value;
     221           4 :   case AArch64::fixup_aarch64_pcrel_branch14:
     222             :     // Signed 16-bit immediate
     223           4 :     if (SignedValue > 32767 || SignedValue < -32768)
     224           2 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     225             :     // Low two bits are not encoded (4-byte alignment assumed).
     226           4 :     if (Value & 0x3)
     227           2 :       Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
     228           4 :     return (Value >> 2) & 0x3fff;
     229          14 :   case AArch64::fixup_aarch64_pcrel_branch26:
     230             :   case AArch64::fixup_aarch64_pcrel_call26:
     231             :     // Signed 28-bit immediate
     232          14 :     if (SignedValue > 134217727 || SignedValue < -134217728)
     233           2 :       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
     234             :     // Low two bits are not encoded (4-byte alignment assumed).
     235          14 :     if (Value & 0x3)
     236           2 :       Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
     237          14 :     return (Value >> 2) & 0x3ffffff;
     238             :   case FK_Data_1:
     239             :   case FK_Data_2:
     240             :   case FK_Data_4:
     241             :   case FK_Data_8:
     242             :   case FK_SecRel_2:
     243             :   case FK_SecRel_4:
     244             :     return Value;
     245             :   }
     246             : }
     247             : 
     248             : /// getFixupKindContainereSizeInBytes - The number of bytes of the
     249             : /// container involved in big endian or 0 if the item is little endian
     250             : unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) const {
     251         489 :   if (Endian == support::little)
     252             :     return 0;
     253             : 
     254          19 :   switch (Kind) {
     255           0 :   default:
     256           0 :     llvm_unreachable("Unknown fixup kind!");
     257             : 
     258             :   case FK_Data_1:
     259             :     return 1;
     260             :   case FK_Data_2:
     261             :     return 2;
     262             :   case FK_Data_4:
     263             :     return 4;
     264             :   case FK_Data_8:
     265             :     return 8;
     266             : 
     267             :   case AArch64::fixup_aarch64_tlsdesc_call:
     268             :   case AArch64::fixup_aarch64_movw:
     269             :   case AArch64::fixup_aarch64_pcrel_branch14:
     270             :   case AArch64::fixup_aarch64_add_imm12:
     271             :   case AArch64::fixup_aarch64_ldst_imm12_scale1:
     272             :   case AArch64::fixup_aarch64_ldst_imm12_scale2:
     273             :   case AArch64::fixup_aarch64_ldst_imm12_scale4:
     274             :   case AArch64::fixup_aarch64_ldst_imm12_scale8:
     275             :   case AArch64::fixup_aarch64_ldst_imm12_scale16:
     276             :   case AArch64::fixup_aarch64_ldr_pcrel_imm19:
     277             :   case AArch64::fixup_aarch64_pcrel_branch19:
     278             :   case AArch64::fixup_aarch64_pcrel_adr_imm21:
     279             :   case AArch64::fixup_aarch64_pcrel_adrp_imm21:
     280             :   case AArch64::fixup_aarch64_pcrel_branch26:
     281             :   case AArch64::fixup_aarch64_pcrel_call26:
     282             :     // Instructions are always little endian
     283             :     return 0;
     284             :   }
     285             : }
     286             : 
     287        1701 : void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
     288             :                                    const MCValue &Target,
     289             :                                    MutableArrayRef<char> Data, uint64_t Value,
     290             :                                    bool IsResolved,
     291             :                                    const MCSubtargetInfo *STI) const {
     292        1701 :   unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
     293        1701 :   if (!Value)
     294             :     return; // Doesn't change encoding.
     295         489 :   MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
     296         489 :   MCContext &Ctx = Asm.getContext();
     297             :   // Apply any target-specific value adjustments.
     298         489 :   Value = adjustFixupValue(Fixup, Value, Ctx, TheTriple, IsResolved);
     299             : 
     300             :   // Shift the value into position.
     301         489 :   Value <<= Info.TargetOffset;
     302             : 
     303         489 :   unsigned Offset = Fixup.getOffset();
     304             :   assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
     305             : 
     306             :   // Used to point to big endian bytes.
     307         489 :   unsigned FulleSizeInBytes = getFixupKindContainereSizeInBytes(Fixup.getKind());
     308             : 
     309             :   // For each byte of the fragment that the fixup touches, mask in the
     310             :   // bits from the fixup value.
     311             :   if (FulleSizeInBytes == 0) {
     312             :     // Handle as little-endian
     313        4425 :     for (unsigned i = 0; i != NumBytes; ++i) {
     314        3954 :       Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
     315             :     }
     316             :   } else {
     317             :     // Handle as big-endian
     318             :     assert((Offset + FulleSizeInBytes) <= Data.size() && "Invalid fixup size!");
     319             :     assert(NumBytes <= FulleSizeInBytes && "Invalid fixup size!");
     320         162 :     for (unsigned i = 0; i != NumBytes; ++i) {
     321          72 :       unsigned Idx = FulleSizeInBytes - 1 - i;
     322         144 :       Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
     323             :     }
     324             :   }
     325             : }
     326             : 
     327        9613 : bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst,
     328             :                                           const MCSubtargetInfo &STI) const {
     329        9613 :   return false;
     330             : }
     331             : 
     332           0 : bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
     333             :                                              uint64_t Value,
     334             :                                              const MCRelaxableFragment *DF,
     335             :                                              const MCAsmLayout &Layout) const {
     336             :   // FIXME:  This isn't correct for AArch64. Just moving the "generic" logic
     337             :   // into the targets for now.
     338             :   //
     339             :   // Relax if the value is too big for a (signed) i8.
     340           0 :   return int64_t(Value) != int64_t(int8_t(Value));
     341             : }
     342             : 
     343           0 : void AArch64AsmBackend::relaxInstruction(const MCInst &Inst,
     344             :                                          const MCSubtargetInfo &STI,
     345             :                                          MCInst &Res) const {
     346           0 :   llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented");
     347             : }
     348             : 
     349         777 : bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
     350             :   // If the count is not 4-byte aligned, we must be writing data into the text
     351             :   // section (otherwise we have unaligned instructions, and thus have far
     352             :   // bigger problems), so just write zeros instead.
     353         777 :   OS.write_zeros(Count % 4);
     354             : 
     355             :   // We are properly aligned, so write NOPs as requested.
     356         777 :   Count /= 4;
     357        4899 :   for (uint64_t i = 0; i != Count; ++i)
     358        2061 :     support::endian::write<uint32_t>(OS, 0xd503201f, Endian);
     359         777 :   return true;
     360             : }
     361             : 
     362         446 : bool AArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm,
     363             :                                               const MCFixup &Fixup,
     364             :                                               const MCValue &Target) {
     365             :   // The ADRP instruction adds some multiple of 0x1000 to the current PC &
     366             :   // ~0xfff. This means that the required offset to reach a symbol can vary by
     367             :   // up to one step depending on where the ADRP is in memory. For example:
     368             :   //
     369             :   //     ADRP x0, there
     370             :   //  there:
     371             :   //
     372             :   // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and
     373             :   // we'll need that as an offset. At any other address "there" will be in the
     374             :   // same page as the ADRP and the instruction should encode 0x0. Assuming the
     375             :   // section isn't 0x1000-aligned, we therefore need to delegate this decision
     376             :   // to the linker -- a relocation!
     377         446 :   if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21)
     378             :     return true;
     379         428 :   return false;
     380             : }
     381             : 
     382             : namespace {
     383             : 
     384             : namespace CU {
     385             : 
     386             : /// Compact unwind encoding values.
     387             : enum CompactUnwindEncodings {
     388             :   /// A "frameless" leaf function, where no non-volatile registers are
     389             :   /// saved. The return remains in LR throughout the function.
     390             :   UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
     391             : 
     392             :   /// No compact unwind encoding available. Instead the low 23-bits of
     393             :   /// the compact unwind encoding is the offset of the DWARF FDE in the
     394             :   /// __eh_frame section. This mode is never used in object files. It is only
     395             :   /// generated by the linker in final linked images, which have only DWARF info
     396             :   /// for a function.
     397             :   UNWIND_ARM64_MODE_DWARF = 0x03000000,
     398             : 
     399             :   /// This is a standard arm64 prologue where FP/LR are immediately
     400             :   /// pushed on the stack, then SP is copied to FP. If there are any
     401             :   /// non-volatile register saved, they are copied into the stack fame in pairs
     402             :   /// in a contiguous ranger right below the saved FP/LR pair. Any subset of the
     403             :   /// five X pairs and four D pairs can be saved, but the memory layout must be
     404             :   /// in register number order.
     405             :   UNWIND_ARM64_MODE_FRAME = 0x04000000,
     406             : 
     407             :   /// Frame register pair encodings.
     408             :   UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
     409             :   UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
     410             :   UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
     411             :   UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
     412             :   UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
     413             :   UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
     414             :   UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
     415             :   UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
     416             :   UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800
     417             : };
     418             : 
     419             : } // end CU namespace
     420             : 
     421             : // FIXME: This should be in a separate file.
     422         363 : class DarwinAArch64AsmBackend : public AArch64AsmBackend {
     423             :   const MCRegisterInfo &MRI;
     424             : 
     425             :   /// Encode compact unwind stack adjustment for frameless functions.
     426             :   /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
     427             :   /// The stack size always needs to be 16 byte aligned.
     428             :   uint32_t encodeStackAdjustment(uint32_t StackSize) const {
     429           3 :     return (StackSize / 16) << 12;
     430             :   }
     431             : 
     432             : public:
     433             :   DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
     434             :                           const MCRegisterInfo &MRI)
     435         734 :       : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {}
     436             : 
     437             :   std::unique_ptr<MCObjectTargetWriter>
     438         367 :   createObjectTargetWriter() const override {
     439             :     return createAArch64MachObjectWriter(MachO::CPU_TYPE_ARM64,
     440         367 :                                          MachO::CPU_SUBTYPE_ARM64_ALL);
     441             :   }
     442             : 
     443             :   /// Generate the compact unwind encoding from the CFI directives.
     444          20 :   uint32_t generateCompactUnwindEncoding(
     445             :                              ArrayRef<MCCFIInstruction> Instrs) const override {
     446          20 :     if (Instrs.empty())
     447             :       return CU::UNWIND_ARM64_MODE_FRAMELESS;
     448             : 
     449             :     bool HasFP = false;
     450             :     unsigned StackSize = 0;
     451             : 
     452             :     uint32_t CompactUnwindEncoding = 0;
     453          51 :     for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
     454             :       const MCCFIInstruction &Inst = Instrs[i];
     455             : 
     456          22 :       switch (Inst.getOperation()) {
     457             :       default:
     458             :         // Cannot handle this directive:  bail out.
     459             :         return CU::UNWIND_ARM64_MODE_DWARF;
     460           8 :       case MCCFIInstruction::OpDefCfa: {
     461             :         // Defines a frame pointer.
     462             :         unsigned XReg =
     463           8 :             getXRegFromWReg(MRI.getLLVMRegNum(Inst.getRegister(), true));
     464             : 
     465             :         // Other CFA registers than FP are not supported by compact unwind.
     466             :         // Fallback on DWARF.
     467             :         // FIXME: When opt-remarks are supported in MC, add a remark to notify
     468             :         // the user.
     469           8 :         if (XReg != AArch64::FP)
     470             :           return CU::UNWIND_ARM64_MODE_DWARF;
     471             : 
     472             :         assert(XReg == AArch64::FP && "Invalid frame pointer!");
     473             :         assert(i + 2 < e && "Insufficient CFI instructions to define a frame!");
     474             : 
     475           7 :         const MCCFIInstruction &LRPush = Instrs[++i];
     476             :         assert(LRPush.getOperation() == MCCFIInstruction::OpOffset &&
     477             :                "Link register not pushed!");
     478           7 :         const MCCFIInstruction &FPPush = Instrs[++i];
     479             :         assert(FPPush.getOperation() == MCCFIInstruction::OpOffset &&
     480             :                "Frame pointer not pushed!");
     481             : 
     482           7 :         unsigned LRReg = MRI.getLLVMRegNum(LRPush.getRegister(), true);
     483           7 :         unsigned FPReg = MRI.getLLVMRegNum(FPPush.getRegister(), true);
     484             : 
     485             :         LRReg = getXRegFromWReg(LRReg);
     486             :         FPReg = getXRegFromWReg(FPReg);
     487             : 
     488             :         assert(LRReg == AArch64::LR && FPReg == AArch64::FP &&
     489             :                "Pushing invalid registers for frame!");
     490             : 
     491             :         // Indicate that the function has a frame.
     492           7 :         CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAME;
     493             :         HasFP = true;
     494           7 :         break;
     495             :       }
     496           5 :       case MCCFIInstruction::OpDefCfaOffset: {
     497             :         assert(StackSize == 0 && "We already have the CFA offset!");
     498           5 :         StackSize = std::abs(Inst.getOffset());
     499           5 :         break;
     500             :       }
     501           9 :       case MCCFIInstruction::OpOffset: {
     502             :         // Registers are saved in pairs. We expect there to be two consecutive
     503             :         // `.cfi_offset' instructions with the appropriate registers specified.
     504           9 :         unsigned Reg1 = MRI.getLLVMRegNum(Inst.getRegister(), true);
     505           9 :         if (i + 1 == e)
     506             :           return CU::UNWIND_ARM64_MODE_DWARF;
     507             : 
     508             :         const MCCFIInstruction &Inst2 = Instrs[++i];
     509           9 :         if (Inst2.getOperation() != MCCFIInstruction::OpOffset)
     510             :           return CU::UNWIND_ARM64_MODE_DWARF;
     511           9 :         unsigned Reg2 = MRI.getLLVMRegNum(Inst2.getRegister(), true);
     512             : 
     513             :         // N.B. The encodings must be in register number order, and the X
     514             :         // registers before the D registers.
     515             : 
     516             :         // X19/X20 pair = 0x00000001,
     517             :         // X21/X22 pair = 0x00000002,
     518             :         // X23/X24 pair = 0x00000004,
     519             :         // X25/X26 pair = 0x00000008,
     520             :         // X27/X28 pair = 0x00000010
     521           9 :         Reg1 = getXRegFromWReg(Reg1);
     522           9 :         Reg2 = getXRegFromWReg(Reg2);
     523             : 
     524          11 :         if (Reg1 == AArch64::X19 && Reg2 == AArch64::X20 &&
     525           2 :             (CompactUnwindEncoding & 0xF1E) == 0)
     526           2 :           CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X19_X20_PAIR;
     527           8 :         else if (Reg1 == AArch64::X21 && Reg2 == AArch64::X22 &&
     528           1 :                  (CompactUnwindEncoding & 0xF1C) == 0)
     529           1 :           CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X21_X22_PAIR;
     530           7 :         else if (Reg1 == AArch64::X23 && Reg2 == AArch64::X24 &&
     531           1 :                  (CompactUnwindEncoding & 0xF18) == 0)
     532           1 :           CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X23_X24_PAIR;
     533           6 :         else if (Reg1 == AArch64::X25 && Reg2 == AArch64::X26 &&
     534           1 :                  (CompactUnwindEncoding & 0xF10) == 0)
     535           1 :           CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X25_X26_PAIR;
     536           6 :         else if (Reg1 == AArch64::X27 && Reg2 == AArch64::X28 &&
     537           2 :                  (CompactUnwindEncoding & 0xF00) == 0)
     538           2 :           CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X27_X28_PAIR;
     539             :         else {
     540           2 :           Reg1 = getDRegFromBReg(Reg1);
     541           2 :           Reg2 = getDRegFromBReg(Reg2);
     542             : 
     543             :           // D8/D9 pair   = 0x00000100,
     544             :           // D10/D11 pair = 0x00000200,
     545             :           // D12/D13 pair = 0x00000400,
     546             :           // D14/D15 pair = 0x00000800
     547           2 :           if (Reg1 == AArch64::D8 && Reg2 == AArch64::D9 &&
     548           0 :               (CompactUnwindEncoding & 0xE00) == 0)
     549           0 :             CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D8_D9_PAIR;
     550           2 :           else if (Reg1 == AArch64::D10 && Reg2 == AArch64::D11 &&
     551           0 :                    (CompactUnwindEncoding & 0xC00) == 0)
     552           0 :             CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D10_D11_PAIR;
     553           2 :           else if (Reg1 == AArch64::D12 && Reg2 == AArch64::D13 &&
     554           0 :                    (CompactUnwindEncoding & 0x800) == 0)
     555           0 :             CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D12_D13_PAIR;
     556           2 :           else if (Reg1 == AArch64::D14 && Reg2 == AArch64::D15)
     557           0 :             CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D14_D15_PAIR;
     558             :           else
     559             :             // A pair was pushed which we cannot handle.
     560             :             return CU::UNWIND_ARM64_MODE_DWARF;
     561             :         }
     562             : 
     563             :         break;
     564             :       }
     565             :       }
     566             :     }
     567             : 
     568          10 :     if (!HasFP) {
     569             :       // With compact unwind info we can only represent stack adjustments of up
     570             :       // to 65520 bytes.
     571           3 :       if (StackSize > 65520)
     572             :         return CU::UNWIND_ARM64_MODE_DWARF;
     573             : 
     574           3 :       CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAMELESS;
     575           3 :       CompactUnwindEncoding |= encodeStackAdjustment(StackSize);
     576             :     }
     577             : 
     578             :     return CompactUnwindEncoding;
     579             :   }
     580             : };
     581             : 
     582             : } // end anonymous namespace
     583             : 
     584             : namespace {
     585             : 
     586        2318 : class ELFAArch64AsmBackend : public AArch64AsmBackend {
     587             : public:
     588             :   uint8_t OSABI;
     589             :   bool IsILP32;
     590             : 
     591             :   ELFAArch64AsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
     592             :                        bool IsLittleEndian, bool IsILP32)
     593        2323 :       : AArch64AsmBackend(T, TT, IsLittleEndian), OSABI(OSABI),
     594        2323 :         IsILP32(IsILP32) {}
     595             : 
     596             :   std::unique_ptr<MCObjectTargetWriter>
     597        2323 :   createObjectTargetWriter() const override {
     598        2323 :     return createAArch64ELFObjectWriter(OSABI, IsILP32);
     599             :   }
     600             : };
     601             : 
     602             : }
     603             : 
     604             : namespace {
     605          28 : class COFFAArch64AsmBackend : public AArch64AsmBackend {
     606             : public:
     607             :   COFFAArch64AsmBackend(const Target &T, const Triple &TheTriple)
     608          28 :       : AArch64AsmBackend(T, TheTriple, /*IsLittleEndian*/ true) {}
     609             : 
     610             :   std::unique_ptr<MCObjectTargetWriter>
     611          28 :   createObjectTargetWriter() const override {
     612          28 :     return createAArch64WinCOFFObjectWriter();
     613             :   }
     614             : };
     615             : }
     616             : 
     617        2687 : MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T,
     618             :                                               const MCSubtargetInfo &STI,
     619             :                                               const MCRegisterInfo &MRI,
     620             :                                               const MCTargetOptions &Options) {
     621             :   const Triple &TheTriple = STI.getTargetTriple();
     622        2687 :   if (TheTriple.isOSBinFormatMachO())
     623         734 :     return new DarwinAArch64AsmBackend(T, TheTriple, MRI);
     624             : 
     625        2320 :   if (TheTriple.isOSBinFormatCOFF())
     626          56 :     return new COFFAArch64AsmBackend(T, TheTriple);
     627             : 
     628             :   assert(TheTriple.isOSBinFormatELF() && "Invalid target");
     629             : 
     630        2292 :   uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
     631        2292 :   bool IsILP32 = Options.getABIName() == "ilp32";
     632             :   return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/true,
     633        4584 :                                   IsILP32);
     634             : }
     635             : 
     636          31 : MCAsmBackend *llvm::createAArch64beAsmBackend(const Target &T,
     637             :                                               const MCSubtargetInfo &STI,
     638             :                                               const MCRegisterInfo &MRI,
     639             :                                               const MCTargetOptions &Options) {
     640             :   const Triple &TheTriple = STI.getTargetTriple();
     641             :   assert(TheTriple.isOSBinFormatELF() &&
     642             :          "Big endian is only supported for ELF targets!");
     643          31 :   uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
     644          31 :   bool IsILP32 = Options.getABIName() == "ilp32";
     645             :   return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/false,
     646          62 :                                   IsILP32);
     647             : }

Generated by: LCOV version 1.13