PPCMachObjectWriter.cpp revision 5510728d28bb1ee04abc32da3d21b7df12948053
1d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang//===-- PPCMachObjectWriter.cpp - PPC Mach-O Writer -----------------------===//
2d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang//
3d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang//                     The LLVM Compiler Infrastructure
4d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang//
5d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang// This file is distributed under the University of Illinois Open Source
6d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang// License. See LICENSE.TXT for details.
7d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang//
8d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang//===----------------------------------------------------------------------===//
9d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
10d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "MCTargetDesc/PPCMCTargetDesc.h"
11d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "MCTargetDesc/PPCFixupKinds.h"
12d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/ADT/Twine.h"
13d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/MC/MCAsmLayout.h"
14d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/MC/MCAssembler.h"
15d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/MC/MCContext.h"
16d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/MC/MCMachObjectWriter.h"
17d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/MC/MCSectionMachO.h"
18d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/MC/MCValue.h"
19d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/Support/ErrorHandling.h"
20d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang#include "llvm/Support/Format.h"
215510728d28bb1ee04abc32da3d21b7df12948053Charles Davis#include "llvm/Support/MachO.h"
22d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
23d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangusing namespace llvm;
24d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
25d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangnamespace {
26d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangclass PPCMachObjectWriter : public MCMachObjectTargetWriter {
27d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  bool RecordScatteredRelocation(MachObjectWriter *Writer,
28d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                 const MCAssembler &Asm,
29d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                 const MCAsmLayout &Layout,
30d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                 const MCFragment *Fragment,
31d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                 const MCFixup &Fixup, MCValue Target,
32d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                 unsigned Log2Size, uint64_t &FixedValue);
33d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
34d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  void RecordPPCRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
35d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                           const MCAsmLayout &Layout,
36d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                           const MCFragment *Fragment, const MCFixup &Fixup,
37d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                           MCValue Target, uint64_t &FixedValue);
38d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
39d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangpublic:
40d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)
41d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
42d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                 /*UseAggressiveSymbolFolding=*/Is64Bit) {}
43d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
44d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
45d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                        const MCAsmLayout &Layout, const MCFragment *Fragment,
46d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                        const MCFixup &Fixup, MCValue Target,
47d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                        uint64_t &FixedValue) {
48d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    if (Writer->is64Bit()) {
49d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      report_fatal_error("Relocation emission for MachO/PPC64 unimplemented.");
50d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    } else
51d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      RecordPPCRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
52d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                          FixedValue);
53d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  }
54d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang};
55d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
56d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
57d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// computes the log2 of the size of the relocation,
58d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// used for relocation_info::r_length.
59d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangstatic unsigned getFixupKindLog2Size(unsigned Kind) {
60d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  switch (Kind) {
61d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  default:
62d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    report_fatal_error("log2size(FixupKind): Unhandled fixup kind!");
63d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case FK_PCRel_1:
64d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case FK_Data_1:
65d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    return 0;
66d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case FK_PCRel_2:
67d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case FK_Data_2:
68d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    return 1;
69d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case FK_PCRel_4:
70d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case PPC::fixup_ppc_brcond14:
71d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case PPC::fixup_ppc_half16:
72d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case PPC::fixup_ppc_br24:
73d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case FK_Data_4:
74d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    return 2;
75d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case FK_PCRel_8:
76d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  case FK_Data_8:
77d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    return 3;
78d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  }
79d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  return 0;
80d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
81d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
82d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
83d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// Outline based on PPCELFObjectWriter::getRelocTypeInner().
84d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangstatic unsigned getRelocType(const MCValue &Target,
85d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                             const MCFixupKind FixupKind, // from
86d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                                          // Fixup.getKind()
87d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                             const bool IsPCRel) {
88d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const MCSymbolRefExpr::VariantKind Modifier =
89d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      Target.isAbsolute() ? MCSymbolRefExpr::VK_None
90d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                          : Target.getSymA()->getKind();
91d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // determine the type of the relocation
925510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  unsigned Type = MachO::GENERIC_RELOC_VANILLA;
93d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  if (IsPCRel) { // relative to PC
94d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    switch ((unsigned)FixupKind) {
95d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    default:
96d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      report_fatal_error("Unimplemented fixup kind (relative)");
97d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    case PPC::fixup_ppc_br24:
985510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      Type = MachO::PPC_RELOC_BR24; // R_PPC_REL24
99d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
100d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    case PPC::fixup_ppc_brcond14:
1015510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      Type = MachO::PPC_RELOC_BR14;
102d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
103d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    case PPC::fixup_ppc_half16:
104d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      switch (Modifier) {
105d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      default:
106d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        llvm_unreachable("Unsupported modifier for half16 fixup");
107d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      case MCSymbolRefExpr::VK_PPC_HA:
1085510728d28bb1ee04abc32da3d21b7df12948053Charles Davis        Type = MachO::PPC_RELOC_HA16;
109d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        break;
110d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      case MCSymbolRefExpr::VK_PPC_LO:
1115510728d28bb1ee04abc32da3d21b7df12948053Charles Davis        Type = MachO::PPC_RELOC_LO16;
112d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        break;
113d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      case MCSymbolRefExpr::VK_PPC_HI:
1145510728d28bb1ee04abc32da3d21b7df12948053Charles Davis        Type = MachO::PPC_RELOC_HI16;
115d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        break;
116d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      }
117d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
118d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    }
119d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  } else {
120d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    switch ((unsigned)FixupKind) {
121d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    default:
122d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      report_fatal_error("Unimplemented fixup kind (absolute)!");
123d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    case PPC::fixup_ppc_half16:
124d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      switch (Modifier) {
125d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      default:
126d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        llvm_unreachable("Unsupported modifier for half16 fixup");
127d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      case MCSymbolRefExpr::VK_PPC_HA:
1285510728d28bb1ee04abc32da3d21b7df12948053Charles Davis        Type = MachO::PPC_RELOC_HA16_SECTDIFF;
129d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        break;
130d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      case MCSymbolRefExpr::VK_PPC_LO:
1315510728d28bb1ee04abc32da3d21b7df12948053Charles Davis        Type = MachO::PPC_RELOC_LO16_SECTDIFF;
132d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        break;
133d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      case MCSymbolRefExpr::VK_PPC_HI:
1345510728d28bb1ee04abc32da3d21b7df12948053Charles Davis        Type = MachO::PPC_RELOC_HI16_SECTDIFF;
135d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        break;
136d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      }
137d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
138d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    case FK_Data_4:
139d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
140d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    case FK_Data_2:
141d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
142d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    }
143d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  }
144d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  return Type;
145d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
146d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
1475510728d28bb1ee04abc32da3d21b7df12948053Charles Davisstatic void makeRelocationInfo(MachO::any_relocation_info &MRE,
148d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                               const uint32_t FixupOffset, const uint32_t Index,
149d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                               const unsigned IsPCRel, const unsigned Log2Size,
150d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                               const unsigned IsExtern, const unsigned Type) {
1515510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  MRE.r_word0 = FixupOffset;
152d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // The bitfield offsets that work (as determined by trial-and-error)
153d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // are different than what is documented in the mach-o manuals.
1545510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  // This appears to be an endianness issue; reversing the order of the
1555510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  // documented bitfields in <llvm/Support/MachO.h> fixes this (but
1565510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  // breaks x86/ARM assembly).
1575510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  MRE.r_word1 = ((Index << 8) |    // was << 0
1585510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                 (IsPCRel << 7) |  // was << 24
1595510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                 (Log2Size << 5) | // was << 25
1605510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                 (IsExtern << 4) | // was << 27
1615510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                 (Type << 0));     // was << 28
162d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
163d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
164d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangstatic void
1655510728d28bb1ee04abc32da3d21b7df12948053Charles DavismakeScatteredRelocationInfo(MachO::any_relocation_info &MRE,
1665510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                            const uint32_t Addr, const unsigned Type,
1675510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                            const unsigned Log2Size, const unsigned IsPCRel,
1685510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                            const uint32_t Value2) {
169f69a29b23a116a3520f185054290c445abf9aa62Charles Davis  // For notes on bitfield positions and endianness, see:
170f69a29b23a116a3520f185054290c445abf9aa62Charles Davis  // https://developer.apple.com/library/mac/documentation/developertools/conceptual/MachORuntime/Reference/reference.html#//apple_ref/doc/uid/20001298-scattered_relocation_entry
1715510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  MRE.r_word0 = ((Addr << 0) | (Type << 24) | (Log2Size << 28) |
1725510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                 (IsPCRel << 30) | MachO::R_SCATTERED);
1735510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  MRE.r_word1 = Value2;
174d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
175d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
176d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// Compute fixup offset (address).
177d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangstatic uint32_t getFixupOffset(const MCAsmLayout &Layout,
178d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                               const MCFragment *Fragment,
179d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                               const MCFixup &Fixup) {
180d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
181d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // On Mach-O, ppc_fixup_half16 relocations must refer to the
182d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // start of the instruction, not the second halfword, as ELF does
183d76adee1b214fe1f5a26b8ffaec3e461beda6c88David Fang  if (unsigned(Fixup.getKind()) == PPC::fixup_ppc_half16)
184d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    FixupOffset &= ~uint32_t(3);
185d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  return FixupOffset;
186d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
187d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
188d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// \return false if falling back to using non-scattered relocation,
189d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// otherwise true for normal scattered relocation.
190d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// based on X86MachObjectWriter::RecordScatteredRelocation
191d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang/// and ARMMachObjectWriter::RecordScatteredRelocation
192d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangbool PPCMachObjectWriter::RecordScatteredRelocation(
193d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
194d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
195d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    unsigned Log2Size, uint64_t &FixedValue) {
196d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // caller already computes these, can we just pass and reuse?
197d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
198d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const MCFixupKind FK = Fixup.getKind();
199d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
200d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const unsigned Type = getRelocType(Target, FK, IsPCRel);
201d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
202d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // Is this a local or SECTDIFF relocation entry?
203d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // SECTDIFF relocation entries have symbol subtractions,
204d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // and require two entries, the first for the add-symbol value,
205d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // the second for the subtract-symbol value.
206d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
207d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // See <reloc.h>.
208d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const MCSymbol *A = &Target.getSymA()->getSymbol();
209d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  MCSymbolData *A_SD = &Asm.getSymbolData(*A);
210d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
211d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  if (!A_SD->getFragment())
212d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    report_fatal_error("symbol '" + A->getName() +
213d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                       "' can not be undefined in a subtraction expression");
214d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
215d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
216d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  uint64_t SecAddr =
217d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      Writer->getSectionAddress(A_SD->getFragment()->getParent());
218d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  FixedValue += SecAddr;
219d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  uint32_t Value2 = 0;
220d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
221d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  if (const MCSymbolRefExpr *B = Target.getSymB()) {
222d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
223d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
224d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    if (!B_SD->getFragment())
225d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      report_fatal_error("symbol '" + B->getSymbol().getName() +
226d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                         "' can not be undefined in a subtraction expression");
227d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
2285510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    // FIXME: is Type correct? see include/llvm/Support/MachO.h
229d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    Value2 = Writer->getSymbolAddress(B_SD, Layout);
230d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
231d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  }
232d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // FIXME: does FixedValue get used??
233d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
234d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // Relocations are written out in reverse order, so the PAIR comes first.
2355510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  if (Type == MachO::PPC_RELOC_SECTDIFF ||
2365510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      Type == MachO::PPC_RELOC_HI16_SECTDIFF ||
2375510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      Type == MachO::PPC_RELOC_LO16_SECTDIFF ||
2385510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      Type == MachO::PPC_RELOC_HA16_SECTDIFF ||
2395510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      Type == MachO::PPC_RELOC_LO14_SECTDIFF ||
2405510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      Type == MachO::PPC_RELOC_LOCAL_SECTDIFF) {
241d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // X86 had this piece, but ARM does not
242d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // If the offset is too large to fit in a scattered relocation,
243d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // we're hosed. It's an unfortunate limitation of the MachO format.
244d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    if (FixupOffset > 0xffffff) {
245d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      char Buffer[32];
246d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
247d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      Asm.getContext().FatalError(Fixup.getLoc(),
248d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                  Twine("Section too large, can't encode "
249d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                        "r_address (") +
250d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                      Buffer + ") into 24 bits of scattered "
251d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                               "relocation entry.");
252d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      llvm_unreachable("fatal error returned?!");
253d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    }
254d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
255d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // Is this supposed to follow MCTarget/PPCAsmBackend.cpp:adjustFixupValue()?
256d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // see PPCMCExpr::EvaluateAsRelocatableImpl()
257d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    uint32_t other_half = 0;
258d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    switch (Type) {
2595510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case MachO::PPC_RELOC_LO16_SECTDIFF:
260d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      other_half = (FixedValue >> 16) & 0xffff;
261d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // applyFixupOffset longer extracts the high part because it now assumes
262d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // this was already done.
263d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // It looks like this is not true for the FixedValue needed with Mach-O
264d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // relocs.
265d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // So we need to adjust FixedValue again here.
266d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      FixedValue &= 0xffff;
267d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
2685510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case MachO::PPC_RELOC_HA16_SECTDIFF:
269d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      other_half = FixedValue & 0xffff;
270d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      FixedValue =
271d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang          ((FixedValue >> 16) + ((FixedValue & 0x8000) ? 1 : 0)) & 0xffff;
272d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
2735510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    case MachO::PPC_RELOC_HI16_SECTDIFF:
274d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      other_half = FixedValue & 0xffff;
275d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      FixedValue = (FixedValue >> 16) & 0xffff;
276d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
277d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    default:
278d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      llvm_unreachable("Invalid PPC scattered relocation type.");
279d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      break;
280d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    }
281d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
2825510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    MachO::any_relocation_info MRE;
2835510728d28bb1ee04abc32da3d21b7df12948053Charles Davis    makeScatteredRelocationInfo(MRE, other_half, MachO::GENERIC_RELOC_PAIR,
2845510728d28bb1ee04abc32da3d21b7df12948053Charles Davis                                Log2Size, IsPCRel, Value2);
285d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    Writer->addRelocation(Fragment->getParent(), MRE);
286d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  } else {
287d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // If the offset is more than 24-bits, it won't fit in a scattered
288d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // relocation offset field, so we fall back to using a non-scattered
289d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // relocation. This is a bit risky, as if the offset reaches out of
290d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // the block and the linker is doing scattered loading on this
291d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // symbol, things can go badly.
292d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    //
293d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // Required for 'as' compatibility.
294d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    if (FixupOffset > 0xffffff)
295d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      return false;
296d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  }
2975510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  MachO::any_relocation_info MRE;
298d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  makeScatteredRelocationInfo(MRE, FixupOffset, Type, Log2Size, IsPCRel, Value);
299d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  Writer->addRelocation(Fragment->getParent(), MRE);
300d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  return true;
301d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
302d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
303d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang// see PPCELFObjectWriter for a general outline of cases
304d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fangvoid PPCMachObjectWriter::RecordPPCRelocation(
305d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
306d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
307d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    uint64_t &FixedValue) {
308d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const MCFixupKind FK = Fixup.getKind(); // unsigned
309d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const unsigned Log2Size = getFixupKindLog2Size(FK);
310d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const bool IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
311d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const unsigned RelocType = getRelocType(Target, FK, IsPCRel);
312d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
313d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // If this is a difference or a defined symbol plus an offset, then we need a
314d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // scattered relocation entry. Differences always require scattered
315d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // relocations.
316d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  if (Target.getSymB() &&
317d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // Q: are branch targets ever scattered?
3185510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      RelocType != MachO::PPC_RELOC_BR24 &&
3195510728d28bb1ee04abc32da3d21b7df12948053Charles Davis      RelocType != MachO::PPC_RELOC_BR14) {
320d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
321d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                              Log2Size, FixedValue);
322d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    return;
323d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  }
324d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
325d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // this doesn't seem right for RIT_PPC_BR24
326d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // Get the symbol data, if any.
327d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  MCSymbolData *SD = 0;
328d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  if (Target.getSymA())
329d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
330d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
331d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  // See <reloc.h>.
332d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
333d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  unsigned Index = 0;
334d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  unsigned IsExtern = 0;
335d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  unsigned Type = RelocType;
336d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
337d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  if (Target.isAbsolute()) { // constant
338d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                             // SymbolNum of 0 indicates the absolute section.
339d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                             //
340d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // FIXME: Currently, these are never generated (see code below). I cannot
341d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // find a case where they are actually emitted.
342d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    report_fatal_error("FIXME: relocations to absolute targets "
343d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                       "not yet implemented");
344d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // the above line stolen from ARM, not sure
345d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  } else {
346d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // Resolve constant variables.
347d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    if (SD->getSymbol().isVariable()) {
348d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      int64_t Res;
349d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
350d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang              Res, Layout, Writer->getSectionAddressMap())) {
351d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        FixedValue = Res;
352d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        return;
353d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      }
354d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    }
355d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
356d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    // Check whether we need an external or internal relocation.
357d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    if (Writer->doesSymbolRequireExternRelocation(SD)) {
358d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      IsExtern = 1;
359d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      Index = SD->getIndex();
360d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // For external relocations, make sure to offset the fixup value to
361d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // compensate for the addend of the symbol address, if it was
362d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // undefined. This occurs with weak definitions, for example.
363d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      if (!SD->Symbol->isUndefined())
364d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang        FixedValue -= Layout.getSymbolOffset(SD);
365d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    } else {
366d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      // The index is the section ordinal (1-based).
367d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      const MCSectionData &SymSD =
368d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang          Asm.getSectionData(SD->getSymbol().getSection());
369d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      Index = SymSD.getOrdinal() + 1;
370d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      FixedValue += Writer->getSectionAddress(&SymSD);
371d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    }
372d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang    if (IsPCRel)
373d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      FixedValue -= Writer->getSectionAddress(Fragment->getParent());
374d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  }
375d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
376f69a29b23a116a3520f185054290c445abf9aa62Charles Davis  // struct relocation_info (8 bytes)
3775510728d28bb1ee04abc32da3d21b7df12948053Charles Davis  MachO::any_relocation_info MRE;
378d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  makeRelocationInfo(MRE, FixupOffset, Index, IsPCRel, Log2Size, IsExtern,
379d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                     Type);
380d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  Writer->addRelocation(Fragment->getParent(), MRE);
381d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
382d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang
383d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid FangMCObjectWriter *llvm::createPPCMachObjectWriter(raw_ostream &OS, bool Is64Bit,
384d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                                uint32_t CPUType,
385d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang                                                uint32_t CPUSubtype) {
386d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang  return createMachObjectWriter(
387d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      new PPCMachObjectWriter(Is64Bit, CPUType, CPUSubtype), OS,
388d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang      /*IsLittleEndian=*/false);
389d4f9d05fde4b2cfd202a5852ec1ec3e960ef53edDavid Fang}
390