1dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines//===-- AArch64MachObjectWriter.cpp - ARM Mach Object Writer --------------===//
236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//                     The LLVM Compiler Infrastructure
436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file is distributed under the University of Illinois Open Source
636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// License. See LICENSE.TXT for details.
736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//
836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===//
936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
10dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "MCTargetDesc/AArch64FixupKinds.h"
11dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "MCTargetDesc/AArch64MCTargetDesc.h"
1236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCAssembler.h"
1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCAsmLayout.h"
1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCContext.h"
1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCExpr.h"
1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCFixup.h"
1736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCMachObjectWriter.h"
1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCSectionMachO.h"
1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/MC/MCValue.h"
2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/ADT/Twine.h"
2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/ErrorHandling.h"
2236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/MachO.h"
2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesusing namespace llvm;
2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesnamespace {
26dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesclass AArch64MachObjectWriter : public MCMachObjectTargetWriter {
27dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  bool getAArch64FixupKindMachOInfo(const MCFixup &Fixup, unsigned &RelocType,
2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  const MCSymbolRefExpr *Sym,
2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  unsigned &Log2Size, const MCAssembler &Asm);
3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinespublic:
32dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  AArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype)
3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : MCMachObjectTargetWriter(true /* is64Bit */, CPUType, CPUSubtype,
3436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                 /*UseAggressiveSymbolFolding=*/true) {}
3536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                        const MCAsmLayout &Layout, const MCFragment *Fragment,
3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                        const MCFixup &Fixup, MCValue Target,
39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        uint64_t &FixedValue) override;
4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines};
4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool AArch64MachObjectWriter::getAArch64FixupKindMachOInfo(
4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCFixup &Fixup, unsigned &RelocType, const MCSymbolRefExpr *Sym,
4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned &Log2Size, const MCAssembler &Asm) {
4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  RelocType = unsigned(MachO::ARM64_RELOC_UNSIGNED);
4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  Log2Size = ~0U;
4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  switch ((unsigned)Fixup.getKind()) {
5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  default:
5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return false;
5236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
5336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case FK_Data_1:
5436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Log2Size = llvm::Log2_32(1);
5536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case FK_Data_2:
5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Log2Size = llvm::Log2_32(2);
5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case FK_Data_4:
6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Log2Size = llvm::Log2_32(4);
6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case FK_Data_8:
6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Log2Size = llvm::Log2_32(8);
6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
69dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_add_imm12:
70dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_ldst_imm12_scale1:
71dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_ldst_imm12_scale2:
72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_ldst_imm12_scale4:
73dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_ldst_imm12_scale8:
74dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_ldst_imm12_scale16:
7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Log2Size = llvm::Log2_32(4);
7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    switch (Sym->getKind()) {
7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    default:
78cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      llvm_unreachable("Unexpected symbol reference variant kind!");
7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case MCSymbolRefExpr::VK_PAGEOFF:
8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      RelocType = unsigned(MachO::ARM64_RELOC_PAGEOFF12);
8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case MCSymbolRefExpr::VK_GOTPAGEOFF:
8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case MCSymbolRefExpr::VK_TLVPPAGEOFF:
8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
89dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_pcrel_adrp_imm21:
9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Log2Size = llvm::Log2_32(4);
9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // This encompasses the relocation for the whole 21-bit value.
9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    switch (Sym->getKind()) {
9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    default:
9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Asm.getContext().FatalError(Fixup.getLoc(),
9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  "ADR/ADRP relocations must be GOT relative");
9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case MCSymbolRefExpr::VK_PAGE:
9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      RelocType = unsigned(MachO::ARM64_RELOC_PAGE21);
9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case MCSymbolRefExpr::VK_GOTPAGE:
10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    case MCSymbolRefExpr::VK_TLVPPAGE:
10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return true;
10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
107dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_pcrel_branch26:
108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case AArch64::fixup_aarch64_pcrel_call26:
10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Log2Size = llvm::Log2_32(4);
11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    RelocType = unsigned(MachO::ARM64_RELOC_BRANCH26);
11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
115dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid AArch64MachObjectWriter::RecordRelocation(
11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint64_t &FixedValue) {
11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // See <reloc.h>.
12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment);
12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned Log2Size = 0;
12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  int64_t Value = 0;
12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned Index = 0;
12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned IsExtern = 0;
12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned Type = 0;
12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  unsigned Kind = Fixup.getKind();
12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  FixupOffset += Fixup.getOffset();
13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
132dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // AArch64 pcrel relocation addends do not include the section offset.
13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (IsPCRel)
13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    FixedValue += FixupOffset;
13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // ADRP fixups use relocations for the whole symbol value and only
13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // put the addend in the instruction itself. Clear out any value the
13836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // generic code figured out from the sybmol definition.
139dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (Kind == AArch64::fixup_aarch64_pcrel_adrp_imm21)
14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    FixedValue = 0;
14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // imm19 relocations are for conditional branches, which require
14336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // assembler local symbols. If we got here, that's not what we have,
14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // so complain loudly.
145dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (Kind == AArch64::fixup_aarch64_pcrel_branch19) {
14636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Asm.getContext().FatalError(Fixup.getLoc(),
14736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                "conditional branch requires assembler-local"
14836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                " label. '" +
14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                    Target.getSymA()->getSymbol().getName() +
15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                    "' is external.");
15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
15436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // 14-bit branch relocations should only target internal labels, and so
15536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // should never get here.
156dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (Kind == AArch64::fixup_aarch64_pcrel_branch14) {
15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Asm.getContext().FatalError(Fixup.getLoc(),
15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                "Invalid relocation on conditional branch!");
15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (!getAArch64FixupKindMachOInfo(Fixup, Type, Target.getSymA(), Log2Size,
16336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  Asm)) {
164dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Asm.getContext().FatalError(Fixup.getLoc(), "unknown AArch64 fixup kind!");
16536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  Value = Target.getConstant();
16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (Target.isAbsolute()) { // constant
17136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // FIXME: Should this always be extern?
17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // SymbolNum of 0 indicates the absolute section.
17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type = MachO::ARM64_RELOC_UNSIGNED;
17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Index = 0;
17536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
17636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (IsPCRel) {
17736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      IsExtern = 1;
17836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Asm.getContext().FatalError(Fixup.getLoc(),
17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  "PC relative absolute relocation!");
18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // FIXME: x86_64 sets the type to a branch reloc here. Should we do
18236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // something similar?
18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
18436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  } else if (Target.getSymB()) { // A - B + constant
18536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCSymbol *A = &Target.getSymA()->getSymbol();
186dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const MCSymbolData &A_SD = Asm.getSymbolData(*A);
18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCSymbolData *A_Base = Asm.getAtom(&A_SD);
18836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
18936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCSymbol *B = &Target.getSymB()->getSymbol();
190dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const MCSymbolData &B_SD = Asm.getSymbolData(*B);
19136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCSymbolData *B_Base = Asm.getAtom(&B_SD);
19236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
19336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Check for "_foo@got - .", which comes through here as:
19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Ltmp0:
19536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    //    ... _foo@got - Ltmp0
19636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOT &&
19736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None &&
19836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Layout.getSymbolOffset(&B_SD) ==
19936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            Layout.getFragmentOffset(Fragment) + Fixup.getOffset()) {
20036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // SymB is the PC, so use a PC-rel pointer-to-GOT relocation.
20136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Index = A_Base->getIndex();
20236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      IsExtern = 1;
20336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Type = MachO::ARM64_RELOC_POINTER_TO_GOT;
20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      IsPCRel = 1;
20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MachO::any_relocation_info MRE;
20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MRE.r_word0 = FixupOffset;
20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                     (IsExtern << 27) | (Type << 28));
20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Writer->addRelocation(Fragment->getParent(), MRE);
21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return;
21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines               Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
21336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Otherwise, neither symbol can be modified.
21436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Asm.getContext().FatalError(Fixup.getLoc(),
21536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  "unsupported relocation of modified symbol");
21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
21736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // We don't support PCrel relocations of differences.
21836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (IsPCRel)
21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Asm.getContext().FatalError(Fixup.getLoc(),
22036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  "unsupported pc-relative relocation of "
22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  "difference");
22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
223dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // AArch64 always uses external relocations. If there is no symbol to use as
224dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // a base address (a local symbol with no preceding non-local symbol),
22536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // error out.
22636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    //
22736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // FIXME: We should probably just synthesize an external symbol and use
22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // that.
22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (!A_Base)
23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Asm.getContext().FatalError(
23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          Fixup.getLoc(),
23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          "unsupported relocation of local symbol '" + A->getName() +
23336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines              "'. Must have non-local symbol earlier in section.");
23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (!B_Base)
23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Asm.getContext().FatalError(
23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          Fixup.getLoc(),
23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          "unsupported relocation of local symbol '" + B->getName() +
23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines              "'. Must have non-local symbol earlier in section.");
23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (A_Base == B_Base && A_Base)
24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Asm.getContext().FatalError(Fixup.getLoc(),
24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  "unsupported relocation with identical base");
24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
244dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Value += (!A_SD.getFragment() ? 0
245dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                  : Writer->getSymbolAddress(&A_SD, Layout)) -
246dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines             (!A_Base || !A_Base->getFragment()
24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                  ? 0
24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                  : Writer->getSymbolAddress(A_Base, Layout));
249dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Value -= (!B_SD.getFragment() ? 0
250dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                  : Writer->getSymbolAddress(&B_SD, Layout)) -
251dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines             (!B_Base || !B_Base->getFragment()
25236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                  ? 0
25336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                  : Writer->getSymbolAddress(B_Base, Layout));
25436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
25536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Index = A_Base->getIndex();
25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    IsExtern = 1;
25736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type = MachO::ARM64_RELOC_UNSIGNED;
25836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachO::any_relocation_info MRE;
26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MRE.r_word0 = FixupOffset;
26136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
26236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                   (IsExtern << 27) | (Type << 28));
26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Writer->addRelocation(Fragment->getParent(), MRE);
26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Index = B_Base->getIndex();
26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    IsExtern = 1;
26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type = MachO::ARM64_RELOC_SUBTRACTOR;
26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  } else { // A + constant
26936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
270dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const MCSymbolData &SD = Asm.getSymbolData(*Symbol);
27136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCSymbolData *Base = Asm.getAtom(&SD);
27236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const MCSectionMachO &Section = static_cast<const MCSectionMachO &>(
27336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Fragment->getParent()->getSection());
27436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
27536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // If the symbol is a variable and we weren't able to get a Base for it
27636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // (i.e., it's not in the symbol table associated with a section) resolve
27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // the relocation based its expansion instead.
27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Symbol->isVariable() && !Base) {
27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // If the evaluation is an absolute value, just use that directly
28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // to keep things easy.
28136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      int64_t Res;
28236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (SD.getSymbol().getVariableValue()->EvaluateAsAbsolute(
28336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines              Res, Layout, Writer->getSectionAddressMap())) {
28436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        FixedValue = Res;
28536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
28636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      }
28736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
28836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // FIXME: Will the Target we already have ever have any data in it
28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // we need to preserve and merge with the new Target? How about
29036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // the FixedValue?
29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (!Symbol->getVariableValue()->EvaluateAsRelocatable(Target, &Layout))
29236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Asm.getContext().FatalError(Fixup.getLoc(),
29336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                    "unable to resolve variable '" +
29436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                        Symbol->getName() + "'");
29536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return RecordRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
29636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                              FixedValue);
29736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
29836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
29936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Relocations inside debug sections always use local relocations when
30036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // possible. This seems to be done because the debugger doesn't fully
30136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // understand relocation entries and expects to find values that
30236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // have already been fixed up.
30336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Symbol->isInSection()) {
30436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
305dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Base = nullptr;
30636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
30736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
308dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // AArch64 uses external relocations as much as possible. For debug
309dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // sections, and for pointer-sized relocations (.quad), we allow section
310dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // relocations.  It's code sections that run into trouble.
31136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (Base) {
31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Index = Base->getIndex();
31336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      IsExtern = 1;
31436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Add the local offset, if needed.
31636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (Base != &SD)
31736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
31836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else if (Symbol->isInSection()) {
31936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Pointer-sized relocations can use a local relocation. Otherwise,
32036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // we have to be in a debug info section.
32136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (!Section.hasAttribute(MachO::S_ATTR_DEBUG) && Log2Size != 3)
32236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Asm.getContext().FatalError(
32336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            Fixup.getLoc(),
32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            "unsupported relocation of local symbol '" + Symbol->getName() +
32536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                "'. Must have non-local symbol earlier in section.");
32636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Adjust the relocation to be section-relative.
32736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // The index is the section ordinal (1-based).
32836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      const MCSectionData &SymSD =
32936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          Asm.getSectionData(SD.getSymbol().getSection());
33036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Index = SymSD.getOrdinal() + 1;
33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      IsExtern = 0;
33236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Value += Writer->getSymbolAddress(&SD, Layout);
33336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (IsPCRel)
33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Value -= Writer->getFragmentAddress(Fragment, Layout) +
33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                 Fixup.getOffset() + (1ULL << Log2Size);
33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    } else {
33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // Resolve constant variables.
33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (SD.getSymbol().isVariable()) {
34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        int64_t Res;
34136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        if (SD.getSymbol().getVariableValue()->EvaluateAsAbsolute(
34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                Res, Layout, Writer->getSectionAddressMap())) {
34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          FixedValue = Res;
34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          return;
34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        }
34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      }
34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Asm.getContext().FatalError(Fixup.getLoc(),
34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  "unsupported relocation of variable '" +
34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                      Symbol->getName() + "'");
35036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // If the relocation kind is Branch26, Page21, or Pageoff12, any addend
35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // is represented via an Addend relocation, not encoded directly into
35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // the instruction.
35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if ((Type == MachO::ARM64_RELOC_BRANCH26 ||
35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines       Type == MachO::ARM64_RELOC_PAGE21 ||
35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines       Type == MachO::ARM64_RELOC_PAGEOFF12) &&
35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Value) {
36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    assert((Value & 0xff000000) == 0 && "Added relocation out of range!");
36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MachO::any_relocation_info MRE;
36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MRE.r_word0 = FixupOffset;
36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                   (IsExtern << 27) | (Type << 28));
36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Writer->addRelocation(Fragment->getParent(), MRE);
36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Now set up the Addend relocation.
36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type = MachO::ARM64_RELOC_ADDEND;
37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Index = Value;
37136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    IsPCRel = 0;
37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Log2Size = 2;
37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    IsExtern = 0;
37436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Put zero into the instruction itself. The addend is in the relocation.
37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Value = 0;
37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // If there's any addend left to handle, encode it in the instruction.
38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  FixedValue = Value;
38136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // struct relocation_info (8 bytes)
38336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MachO::any_relocation_info MRE;
38436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MRE.r_word0 = FixupOffset;
38536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MRE.r_word1 = ((Index << 0) | (IsPCRel << 24) | (Log2Size << 25) |
38636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                 (IsExtern << 27) | (Type << 28));
38736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  Writer->addRelocation(Fragment->getParent(), MRE);
38836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
38936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
390dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesMCObjectWriter *llvm::createAArch64MachObjectWriter(raw_ostream &OS,
39136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                  uint32_t CPUType,
39236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                  uint32_t CPUSubtype) {
393dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return createMachObjectWriter(
394dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      new AArch64MachObjectWriter(CPUType, CPUSubtype), OS,
395dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      /*IsLittleEndian=*/true);
39636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
397