//===-- AArch64AsmBackend.cpp - AArch64 Assembler Backend -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "AArch64.h"
#include "AArch64RegisterInfo.h"
#include "MCTargetDesc/AArch64FixupKinds.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MachO.h"
using namespace llvm;

namespace {

class AArch64AsmBackend : public MCAsmBackend {
  static const unsigned PCRelFlagVal =
      MCFixupKindInfo::FKF_IsAlignedDownTo32Bits | MCFixupKindInfo::FKF_IsPCRel;

public:
  AArch64AsmBackend(const Target &T) : MCAsmBackend() {}

  unsigned getNumFixupKinds() const override {
    return AArch64::NumTargetFixupKinds;
  }

  const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
    const static MCFixupKindInfo Infos[AArch64::NumTargetFixupKinds] = {
      // This table *must* be in the order that the fixup_* kinds are defined in
      // AArch64FixupKinds.h.
      //
      // Name                           Offset (bits) Size (bits)     Flags
      { "fixup_aarch64_pcrel_adr_imm21", 0, 32, PCRelFlagVal },
      { "fixup_aarch64_pcrel_adrp_imm21", 0, 32, PCRelFlagVal },
      { "fixup_aarch64_add_imm12", 10, 12, 0 },
      { "fixup_aarch64_ldst_imm12_scale1", 10, 12, 0 },
      { "fixup_aarch64_ldst_imm12_scale2", 10, 12, 0 },
      { "fixup_aarch64_ldst_imm12_scale4", 10, 12, 0 },
      { "fixup_aarch64_ldst_imm12_scale8", 10, 12, 0 },
      { "fixup_aarch64_ldst_imm12_scale16", 10, 12, 0 },
      { "fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal },
      { "fixup_aarch64_movw", 5, 16, 0 },
      { "fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal },
      { "fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal },
      { "fixup_aarch64_pcrel_branch26", 0, 26, PCRelFlagVal },
      { "fixup_aarch64_pcrel_call26", 0, 26, PCRelFlagVal },
      { "fixup_aarch64_tlsdesc_call", 0, 0, 0 }
    };

    if (Kind < FirstTargetFixupKind)
      return MCAsmBackend::getFixupKindInfo(Kind);

    assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
           "Invalid kind!");
    return Infos[Kind - FirstTargetFixupKind];
  }

  void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
                  uint64_t Value, bool IsPCRel) const override;

  bool mayNeedRelaxation(const MCInst &Inst) const override;
  bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
                            const MCRelaxableFragment *DF,
                            const MCAsmLayout &Layout) const override;
  void relaxInstruction(const MCInst &Inst, MCInst &Res) const override;
  bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;

  void HandleAssemblerFlag(MCAssemblerFlag Flag) {}

  unsigned getPointerSize() const { return 8; }
};

} // end anonymous namespace

/// \brief The number of bytes the fixup may change.
static unsigned getFixupKindNumBytes(unsigned Kind) {
  switch (Kind) {
  default:
    llvm_unreachable("Unknown fixup kind!");

  case AArch64::fixup_aarch64_tlsdesc_call:
    return 0;

  case FK_Data_1:
    return 1;

  case FK_Data_2:
  case AArch64::fixup_aarch64_movw:
    return 2;

  case AArch64::fixup_aarch64_pcrel_branch14:
  case AArch64::fixup_aarch64_add_imm12:
  case AArch64::fixup_aarch64_ldst_imm12_scale1:
  case AArch64::fixup_aarch64_ldst_imm12_scale2:
  case AArch64::fixup_aarch64_ldst_imm12_scale4:
  case AArch64::fixup_aarch64_ldst_imm12_scale8:
  case AArch64::fixup_aarch64_ldst_imm12_scale16:
  case AArch64::fixup_aarch64_ldr_pcrel_imm19:
  case AArch64::fixup_aarch64_pcrel_branch19:
    return 3;

  case AArch64::fixup_aarch64_pcrel_adr_imm21:
  case AArch64::fixup_aarch64_pcrel_adrp_imm21:
  case AArch64::fixup_aarch64_pcrel_branch26:
  case AArch64::fixup_aarch64_pcrel_call26:
  case FK_Data_4:
    return 4;

  case FK_Data_8:
    return 8;
  }
}

static unsigned AdrImmBits(unsigned Value) {
  unsigned lo2 = Value & 0x3;
  unsigned hi19 = (Value & 0x1ffffc) >> 2;
  return (hi19 << 5) | (lo2 << 29);
}

static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
  int64_t SignedValue = static_cast<int64_t>(Value);
  switch (Kind) {
  default:
    llvm_unreachable("Unknown fixup kind!");
  case AArch64::fixup_aarch64_pcrel_adr_imm21:
    if (SignedValue > 2097151 || SignedValue < -2097152)
      report_fatal_error("fixup value out of range");
    return AdrImmBits(Value & 0x1fffffULL);
  case AArch64::fixup_aarch64_pcrel_adrp_imm21:
    return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
  case AArch64::fixup_aarch64_ldr_pcrel_imm19:
  case AArch64::fixup_aarch64_pcrel_branch19:
    // Signed 21-bit immediate
    if (SignedValue > 2097151 || SignedValue < -2097152)
      report_fatal_error("fixup value out of range");
    // Low two bits are not encoded.
    return (Value >> 2) & 0x7ffff;
  case AArch64::fixup_aarch64_add_imm12:
  case AArch64::fixup_aarch64_ldst_imm12_scale1:
    // Unsigned 12-bit immediate
    if (Value >= 0x1000)
      report_fatal_error("invalid imm12 fixup value");
    return Value;
  case AArch64::fixup_aarch64_ldst_imm12_scale2:
    // Unsigned 12-bit immediate which gets multiplied by 2
    if (Value & 1 || Value >= 0x2000)
      report_fatal_error("invalid imm12 fixup value");
    return Value >> 1;
  case AArch64::fixup_aarch64_ldst_imm12_scale4:
    // Unsigned 12-bit immediate which gets multiplied by 4
    if (Value & 3 || Value >= 0x4000)
      report_fatal_error("invalid imm12 fixup value");
    return Value >> 2;
  case AArch64::fixup_aarch64_ldst_imm12_scale8:
    // Unsigned 12-bit immediate which gets multiplied by 8
    if (Value & 7 || Value >= 0x8000)
      report_fatal_error("invalid imm12 fixup value");
    return Value >> 3;
  case AArch64::fixup_aarch64_ldst_imm12_scale16:
    // Unsigned 12-bit immediate which gets multiplied by 16
    if (Value & 15 || Value >= 0x10000)
      report_fatal_error("invalid imm12 fixup value");
    return Value >> 4;
  case AArch64::fixup_aarch64_movw:
    report_fatal_error("no resolvable MOVZ/MOVK fixups supported yet");
    return Value;
  case AArch64::fixup_aarch64_pcrel_branch14:
    // Signed 16-bit immediate
    if (SignedValue > 32767 || SignedValue < -32768)
      report_fatal_error("fixup value out of range");
    // Low two bits are not encoded (4-byte alignment assumed).
    if (Value & 0x3)
      report_fatal_error("fixup not sufficiently aligned");
    return (Value >> 2) & 0x3fff;
  case AArch64::fixup_aarch64_pcrel_branch26:
  case AArch64::fixup_aarch64_pcrel_call26:
    // Signed 28-bit immediate
    if (SignedValue > 134217727 || SignedValue < -134217728)
      report_fatal_error("fixup value out of range");
    // Low two bits are not encoded (4-byte alignment assumed).
    if (Value & 0x3)
      report_fatal_error("fixup not sufficiently aligned");
    return (Value >> 2) & 0x3ffffff;
  case FK_Data_1:
  case FK_Data_2:
  case FK_Data_4:
  case FK_Data_8:
    return Value;
  }
}

void AArch64AsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
                                   unsigned DataSize, uint64_t Value,
                                   bool IsPCRel) const {
  unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
  if (!Value)
    return; // Doesn't change encoding.
  MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
  // Apply any target-specific value adjustments.
  Value = adjustFixupValue(Fixup.getKind(), Value);

  // Shift the value into position.
  Value <<= Info.TargetOffset;

  unsigned Offset = Fixup.getOffset();
  assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!");

  // For each byte of the fragment that the fixup touches, mask in the
  // bits from the fixup value.
  for (unsigned i = 0; i != NumBytes; ++i)
    Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
}

bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
  return false;
}

bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
                                             uint64_t Value,
                                             const MCRelaxableFragment *DF,
                                             const MCAsmLayout &Layout) const {
  // FIXME:  This isn't correct for AArch64. Just moving the "generic" logic
  // into the targets for now.
  //
  // Relax if the value is too big for a (signed) i8.
  return int64_t(Value) != int64_t(int8_t(Value));
}

void AArch64AsmBackend::relaxInstruction(const MCInst &Inst,
                                         MCInst &Res) const {
  llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented");
}

bool AArch64AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
  // If the count is not 4-byte aligned, we must be writing data into the text
  // section (otherwise we have unaligned instructions, and thus have far
  // bigger problems), so just write zeros instead.
  if ((Count & 3) != 0) {
    for (uint64_t i = 0, e = (Count & 3); i != e; ++i)
      OW->Write8(0);
  }

  // We are properly aligned, so write NOPs as requested.
  Count /= 4;
  for (uint64_t i = 0; i != Count; ++i)
    OW->Write32(0xd503201f);
  return true;
}

namespace {

namespace CU {

/// \brief Compact unwind encoding values.
enum CompactUnwindEncodings {
  /// \brief A "frameless" leaf function, where no non-volatile registers are
  /// saved. The return remains in LR throughout the function.
  UNWIND_AArch64_MODE_FRAMELESS = 0x02000000,

  /// \brief No compact unwind encoding available. Instead the low 23-bits of
  /// the compact unwind encoding is the offset of the DWARF FDE in the
  /// __eh_frame section. This mode is never used in object files. It is only
  /// generated by the linker in final linked images, which have only DWARF info
  /// for a function.
  UNWIND_AArch64_MODE_DWARF = 0x03000000,

  /// \brief This is a standard arm64 prologue where FP/LR are immediately
  /// pushed on the stack, then SP is copied to FP. If there are any
  /// non-volatile register saved, they are copied into the stack fame in pairs
  /// in a contiguous ranger right below the saved FP/LR pair. Any subset of the
  /// five X pairs and four D pairs can be saved, but the memory layout must be
  /// in register number order.
  UNWIND_AArch64_MODE_FRAME = 0x04000000,

  /// \brief Frame register pair encodings.
  UNWIND_AArch64_FRAME_X19_X20_PAIR = 0x00000001,
  UNWIND_AArch64_FRAME_X21_X22_PAIR = 0x00000002,
  UNWIND_AArch64_FRAME_X23_X24_PAIR = 0x00000004,
  UNWIND_AArch64_FRAME_X25_X26_PAIR = 0x00000008,
  UNWIND_AArch64_FRAME_X27_X28_PAIR = 0x00000010,
  UNWIND_AArch64_FRAME_D8_D9_PAIR = 0x00000100,
  UNWIND_AArch64_FRAME_D10_D11_PAIR = 0x00000200,
  UNWIND_AArch64_FRAME_D12_D13_PAIR = 0x00000400,
  UNWIND_AArch64_FRAME_D14_D15_PAIR = 0x00000800
};

} // end CU namespace

// FIXME: This should be in a separate file.
class DarwinAArch64AsmBackend : public AArch64AsmBackend {
  const MCRegisterInfo &MRI;

  /// \brief Encode compact unwind stack adjustment for frameless functions.
  /// See UNWIND_AArch64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
  /// The stack size always needs to be 16 byte aligned.
  uint32_t encodeStackAdjustment(uint32_t StackSize) const {
    return (StackSize / 16) << 12;
  }

public:
  DarwinAArch64AsmBackend(const Target &T, const MCRegisterInfo &MRI)
      : AArch64AsmBackend(T), MRI(MRI) {}

  MCObjectWriter *createObjectWriter(raw_ostream &OS) const override {
    return createAArch64MachObjectWriter(OS, MachO::CPU_TYPE_ARM64,
                                         MachO::CPU_SUBTYPE_ARM64_ALL);
  }

  bool doesSectionRequireSymbols(const MCSection &Section) const override {
    // Any section for which the linker breaks things into atoms needs to
    // preserve symbols, including assembler local symbols, to identify
    // those atoms. These sections are:
    // Sections of type:
    //
    //    S_CSTRING_LITERALS  (e.g. __cstring)
    //    S_LITERAL_POINTERS  (e.g.  objc selector pointers)
    //    S_16BYTE_LITERALS, S_8BYTE_LITERALS, S_4BYTE_LITERALS
    //
    // Sections named:
    //
    //    __TEXT,__eh_frame
    //    __TEXT,__ustring
    //    __DATA,__cfstring
    //    __DATA,__objc_classrefs
    //    __DATA,__objc_catlist
    //
    // FIXME: It would be better if the compiler used actual linker local
    // symbols for each of these sections rather than preserving what
    // are ostensibly assembler local symbols.
    const MCSectionMachO &SMO = static_cast<const MCSectionMachO &>(Section);
    return (SMO.getType() == MachO::S_CSTRING_LITERALS ||
            SMO.getType() == MachO::S_4BYTE_LITERALS ||
            SMO.getType() == MachO::S_8BYTE_LITERALS ||
            SMO.getType() == MachO::S_16BYTE_LITERALS ||
            SMO.getType() == MachO::S_LITERAL_POINTERS ||
            (SMO.getSegmentName() == "__TEXT" &&
             (SMO.getSectionName() == "__eh_frame" ||
              SMO.getSectionName() == "__ustring")) ||
            (SMO.getSegmentName() == "__DATA" &&
             (SMO.getSectionName() == "__cfstring" ||
              SMO.getSectionName() == "__objc_classrefs" ||
              SMO.getSectionName() == "__objc_catlist")));
  }

  /// \brief Generate the compact unwind encoding from the CFI directives.
  uint32_t generateCompactUnwindEncoding(
                             ArrayRef<MCCFIInstruction> Instrs) const override {
    if (Instrs.empty())
      return CU::UNWIND_AArch64_MODE_FRAMELESS;

    bool HasFP = false;
    unsigned StackSize = 0;

    uint32_t CompactUnwindEncoding = 0;
    for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
      const MCCFIInstruction &Inst = Instrs[i];

      switch (Inst.getOperation()) {
      default:
        // Cannot handle this directive:  bail out.
        return CU::UNWIND_AArch64_MODE_DWARF;
      case MCCFIInstruction::OpDefCfa: {
        // Defines a frame pointer.
        assert(getXRegFromWReg(MRI.getLLVMRegNum(Inst.getRegister(), true)) ==
                   AArch64::FP &&
               "Invalid frame pointer!");
        assert(i + 2 < e && "Insufficient CFI instructions to define a frame!");

        const MCCFIInstruction &LRPush = Instrs[++i];
        assert(LRPush.getOperation() == MCCFIInstruction::OpOffset &&
               "Link register not pushed!");
        const MCCFIInstruction &FPPush = Instrs[++i];
        assert(FPPush.getOperation() == MCCFIInstruction::OpOffset &&
               "Frame pointer not pushed!");

        unsigned LRReg = MRI.getLLVMRegNum(LRPush.getRegister(), true);
        unsigned FPReg = MRI.getLLVMRegNum(FPPush.getRegister(), true);

        LRReg = getXRegFromWReg(LRReg);
        FPReg = getXRegFromWReg(FPReg);

        assert(LRReg == AArch64::LR && FPReg == AArch64::FP &&
               "Pushing invalid registers for frame!");

        // Indicate that the function has a frame.
        CompactUnwindEncoding |= CU::UNWIND_AArch64_MODE_FRAME;
        HasFP = true;
        break;
      }
      case MCCFIInstruction::OpDefCfaOffset: {
        assert(StackSize == 0 && "We already have the CFA offset!");
        StackSize = std::abs(Inst.getOffset());
        break;
      }
      case MCCFIInstruction::OpOffset: {
        // Registers are saved in pairs. We expect there to be two consecutive
        // `.cfi_offset' instructions with the appropriate registers specified.
        unsigned Reg1 = MRI.getLLVMRegNum(Inst.getRegister(), true);
        if (i + 1 == e)
          return CU::UNWIND_AArch64_MODE_DWARF;

        const MCCFIInstruction &Inst2 = Instrs[++i];
        if (Inst2.getOperation() != MCCFIInstruction::OpOffset)
          return CU::UNWIND_AArch64_MODE_DWARF;
        unsigned Reg2 = MRI.getLLVMRegNum(Inst2.getRegister(), true);

        // N.B. The encodings must be in register number order, and the X
        // registers before the D registers.

        // X19/X20 pair = 0x00000001,
        // X21/X22 pair = 0x00000002,
        // X23/X24 pair = 0x00000004,
        // X25/X26 pair = 0x00000008,
        // X27/X28 pair = 0x00000010
        Reg1 = getXRegFromWReg(Reg1);
        Reg2 = getXRegFromWReg(Reg2);

        if (Reg1 == AArch64::X19 && Reg2 == AArch64::X20 &&
            (CompactUnwindEncoding & 0xF1E) == 0)
          CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_X19_X20_PAIR;
        else if (Reg1 == AArch64::X21 && Reg2 == AArch64::X22 &&
                 (CompactUnwindEncoding & 0xF1C) == 0)
          CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_X21_X22_PAIR;
        else if (Reg1 == AArch64::X23 && Reg2 == AArch64::X24 &&
                 (CompactUnwindEncoding & 0xF18) == 0)
          CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_X23_X24_PAIR;
        else if (Reg1 == AArch64::X25 && Reg2 == AArch64::X26 &&
                 (CompactUnwindEncoding & 0xF10) == 0)
          CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_X25_X26_PAIR;
        else if (Reg1 == AArch64::X27 && Reg2 == AArch64::X28 &&
                 (CompactUnwindEncoding & 0xF00) == 0)
          CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_X27_X28_PAIR;
        else {
          Reg1 = getDRegFromBReg(Reg1);
          Reg2 = getDRegFromBReg(Reg2);

          // D8/D9 pair   = 0x00000100,
          // D10/D11 pair = 0x00000200,
          // D12/D13 pair = 0x00000400,
          // D14/D15 pair = 0x00000800
          if (Reg1 == AArch64::D8 && Reg2 == AArch64::D9 &&
              (CompactUnwindEncoding & 0xE00) == 0)
            CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_D8_D9_PAIR;
          else if (Reg1 == AArch64::D10 && Reg2 == AArch64::D11 &&
                   (CompactUnwindEncoding & 0xC00) == 0)
            CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_D10_D11_PAIR;
          else if (Reg1 == AArch64::D12 && Reg2 == AArch64::D13 &&
                   (CompactUnwindEncoding & 0x800) == 0)
            CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_D12_D13_PAIR;
          else if (Reg1 == AArch64::D14 && Reg2 == AArch64::D15)
            CompactUnwindEncoding |= CU::UNWIND_AArch64_FRAME_D14_D15_PAIR;
          else
            // A pair was pushed which we cannot handle.
            return CU::UNWIND_AArch64_MODE_DWARF;
        }

        break;
      }
      }
    }

    if (!HasFP) {
      // With compact unwind info we can only represent stack adjustments of up
      // to 65520 bytes.
      if (StackSize > 65520)
        return CU::UNWIND_AArch64_MODE_DWARF;

      CompactUnwindEncoding |= CU::UNWIND_AArch64_MODE_FRAMELESS;
      CompactUnwindEncoding |= encodeStackAdjustment(StackSize);
    }

    return CompactUnwindEncoding;
  }
};

} // end anonymous namespace

namespace {

class ELFAArch64AsmBackend : public AArch64AsmBackend {
public:
  uint8_t OSABI;
  bool IsLittleEndian;

  ELFAArch64AsmBackend(const Target &T, uint8_t OSABI, bool IsLittleEndian)
    : AArch64AsmBackend(T), OSABI(OSABI), IsLittleEndian(IsLittleEndian) {}

  MCObjectWriter *createObjectWriter(raw_ostream &OS) const override {
    return createAArch64ELFObjectWriter(OS, OSABI, IsLittleEndian);
  }

  void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
                         const MCFixup &Fixup, const MCFragment *DF,
                         const MCValue &Target, uint64_t &Value,
                         bool &IsResolved) override;

  void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
                  uint64_t Value, bool IsPCRel) const override;
};

void ELFAArch64AsmBackend::processFixupValue(
    const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup,
    const MCFragment *DF, const MCValue &Target, uint64_t &Value,
    bool &IsResolved) {
  // The ADRP instruction adds some multiple of 0x1000 to the current PC &
  // ~0xfff. This means that the required offset to reach a symbol can vary by
  // up to one step depending on where the ADRP is in memory. For example:
  //
  //     ADRP x0, there
  //  there:
  //
  // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and
  // we'll need that as an offset. At any other address "there" will be in the
  // same page as the ADRP and the instruction should encode 0x0. Assuming the
  // section isn't 0x1000-aligned, we therefore need to delegate this decision
  // to the linker -- a relocation!
  if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21)
    IsResolved = false;
}

void ELFAArch64AsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
                                      unsigned DataSize, uint64_t Value,
                                      bool IsPCRel) const {
  // store fixups in .eh_frame section in big endian order
  if (!IsLittleEndian && Fixup.getKind() == FK_Data_4) {
    const MCSection *Sec = Fixup.getValue()->FindAssociatedSection();
    const MCSectionELF *SecELF = dyn_cast_or_null<const MCSectionELF>(Sec);
    if (SecELF && SecELF->getSectionName() == ".eh_frame")
      Value = ByteSwap_32(unsigned(Value));
  }
  AArch64AsmBackend::applyFixup (Fixup, Data, DataSize, Value, IsPCRel);
}
}

MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T,
                                            const MCRegisterInfo &MRI,
                                            StringRef TT, StringRef CPU) {
  Triple TheTriple(TT);

  if (TheTriple.isOSDarwin())
    return new DarwinAArch64AsmBackend(T, MRI);

  assert(TheTriple.isOSBinFormatELF() && "Expect either MachO or ELF target");
  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
  return new ELFAArch64AsmBackend(T, OSABI, /*IsLittleEndian=*/true);
}

MCAsmBackend *llvm::createAArch64beAsmBackend(const Target &T,
                                            const MCRegisterInfo &MRI,
                                            StringRef TT, StringRef CPU) {
  Triple TheTriple(TT);

  assert(TheTriple.isOSBinFormatELF() &&
         "Big endian is only supported for ELF targets!");
  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
  return new ELFAArch64AsmBackend(T, OSABI,
                                  /*IsLittleEndian=*/false);
}
