ARMMachObjectWriter.cpp revision be74029f44c32efc09274a16cbff588ad10dc5ea
1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===//
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch//
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch//                     The LLVM Compiler Infrastructure
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch//
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// This file is distributed under the University of Illinois Open Source
6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// License. See LICENSE.TXT for details.
7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch//
8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch//===----------------------------------------------------------------------===//
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "MCTargetDesc/ARMBaseInfo.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "MCTargetDesc/ARMFixupKinds.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/ADT/Twine.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/MC/MCAssembler.h"
14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/MC/MCAsmLayout.h"
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/MC/MCMachObjectWriter.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "llvm/MC/MCExpr.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "llvm/MC/MCFixup.h"
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/MC/MCFixupKindInfo.h"
19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/MC/MCValue.h"
20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/Object/MachOFormat.h"
21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/Support/ErrorHandling.h"
22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "llvm/Target/TargetAsmBackend.h"
23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochusing namespace llvm;
24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochusing namespace llvm::object;
25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace {
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochclass ARMMachObjectWriter : public MCMachObjectTargetWriter {
28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void RecordARMScatteredRelocation(MachObjectWriter *Writer,
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    const MCAssembler &Asm,
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    const MCAsmLayout &Layout,
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    const MCFragment *Fragment,
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    const MCFixup &Fixup,
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    MCValue Target,
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    unsigned Log2Size,
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    uint64_t &FixedValue);
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void RecordARMMovwMovtRelocation(MachObjectWriter *Writer,
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   const MCAssembler &Asm,
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   const MCAsmLayout &Layout,
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   const MCFragment *Fragment,
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                   const MCFixup &Fixup, MCValue Target,
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                   uint64_t &FixedValue);
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccipublic:
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType,
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      uint32_t CPUSubtype)
46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               /*UseAggressiveSymbolFolding=*/true) {}
48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void RecordRelocation(MachObjectWriter *Writer,
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        const MCAssembler &Asm, const MCAsmLayout &Layout,
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        const MCFragment *Fragment, const MCFixup &Fixup,
52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        MCValue Target, uint64_t &FixedValue);
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                              unsigned &Log2Size) {
58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  RelocType = unsigned(macho::RIT_Vanilla);
59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  Log2Size = ~0U;
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  switch (Kind) {
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  default:
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  case FK_Data_1:
66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(1);
67ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case FK_Data_2:
69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(2);
70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case FK_Data_4:
72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(4);
73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case FK_Data_8:
75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(8);
76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Handle 24-bit branch kinds.
79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_ldst_pcrel_12:
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  case ARM::fixup_arm_pcrel_10:
81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_adr_pcrel_12:
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  case ARM::fixup_arm_condbranch:
83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_uncondbranch:
84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    RelocType = unsigned(macho::RIT_ARM_Branch24Bit);
85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Report as 'long', even though that is not quite accurate.
86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(4);
87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Handle Thumb branches.
90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_thumb_br:
91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit);
92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(2);
93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_t2_uncondbranch:
96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_thumb_bl:
97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_thumb_blx:
98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit);
99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(4);
100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_movt_hi16:
103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_movt_hi16_pcrel:
104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_t2_movt_hi16:
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  case ARM::fixup_t2_movt_hi16_pcrel:
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    RelocType = unsigned(macho::RIT_ARM_HalfDifference);
107ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Report as 'long', even though that is not quite accurate.
108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(4);
109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_movw_lo16:
112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_arm_movw_lo16_pcrel:
113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_t2_movw_lo16:
114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  case ARM::fixup_t2_movw_lo16_pcrel:
115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    RelocType = unsigned(macho::RIT_ARM_Half);
116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Report as 'long', even though that is not quite accurate.
117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Log2Size = llvm::Log2_32(4);
118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
120}
121
122void ARMMachObjectWriter::
123RecordARMMovwMovtRelocation(MachObjectWriter *Writer,
124                            const MCAssembler &Asm,
125                            const MCAsmLayout &Layout,
126                            const MCFragment *Fragment,
127                            const MCFixup &Fixup,
128                            MCValue Target,
129                            uint64_t &FixedValue) {
130  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
131  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
132  unsigned Type = macho::RIT_ARM_Half;
133
134  // See <reloc.h>.
135  const MCSymbol *A = &Target.getSymA()->getSymbol();
136  MCSymbolData *A_SD = &Asm.getSymbolData(*A);
137
138  if (!A_SD->getFragment())
139    report_fatal_error("symbol '" + A->getName() +
140                       "' can not be undefined in a subtraction expression");
141
142  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
143  uint32_t Value2 = 0;
144  uint64_t SecAddr =
145    Writer->getSectionAddress(A_SD->getFragment()->getParent());
146  FixedValue += SecAddr;
147
148  if (const MCSymbolRefExpr *B = Target.getSymB()) {
149    MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
150
151    if (!B_SD->getFragment())
152      report_fatal_error("symbol '" + B->getSymbol().getName() +
153                         "' can not be undefined in a subtraction expression");
154
155    // Select the appropriate difference relocation type.
156    Type = macho::RIT_ARM_HalfDifference;
157    Value2 = Writer->getSymbolAddress(B_SD, Layout);
158    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
159  }
160
161  // Relocations are written out in reverse order, so the PAIR comes first.
162  // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
163  //
164  // For these two r_type relocations they always have a pair following them and
165  // the r_length bits are used differently.  The encoding of the r_length is as
166  // follows:
167  //   low bit of r_length:
168  //      0 - :lower16: for movw instructions
169  //      1 - :upper16: for movt instructions
170  //   high bit of r_length:
171  //      0 - arm instructions
172  //      1 - thumb instructions
173  // the other half of the relocated expression is in the following pair
174  // relocation entry in the the low 16 bits of r_address field.
175  unsigned ThumbBit = 0;
176  unsigned MovtBit = 0;
177  switch ((unsigned)Fixup.getKind()) {
178  default: break;
179  case ARM::fixup_arm_movt_hi16:
180  case ARM::fixup_arm_movt_hi16_pcrel:
181    MovtBit = 1;
182    break;
183  case ARM::fixup_t2_movt_hi16:
184  case ARM::fixup_t2_movt_hi16_pcrel:
185    MovtBit = 1;
186    // Fallthrough
187  case ARM::fixup_t2_movw_lo16:
188  case ARM::fixup_t2_movw_lo16_pcrel:
189    ThumbBit = 1;
190    break;
191  }
192
193
194  if (Type == macho::RIT_ARM_HalfDifference) {
195    uint32_t OtherHalf = MovtBit
196      ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
197
198    macho::RelocationEntry MRE;
199    MRE.Word0 = ((OtherHalf       <<  0) |
200                 (macho::RIT_Pair << 24) |
201                 (MovtBit         << 28) |
202                 (ThumbBit        << 29) |
203                 (IsPCRel         << 30) |
204                 macho::RF_Scattered);
205    MRE.Word1 = Value2;
206    Writer->addRelocation(Fragment->getParent(), MRE);
207  }
208
209  macho::RelocationEntry MRE;
210  MRE.Word0 = ((FixupOffset <<  0) |
211               (Type        << 24) |
212               (MovtBit     << 28) |
213               (ThumbBit    << 29) |
214               (IsPCRel     << 30) |
215               macho::RF_Scattered);
216  MRE.Word1 = Value;
217  Writer->addRelocation(Fragment->getParent(), MRE);
218}
219
220void ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
221                                                    const MCAssembler &Asm,
222                                                    const MCAsmLayout &Layout,
223                                                    const MCFragment *Fragment,
224                                                    const MCFixup &Fixup,
225                                                    MCValue Target,
226                                                    unsigned Log2Size,
227                                                    uint64_t &FixedValue) {
228  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
229  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
230  unsigned Type = macho::RIT_Vanilla;
231
232  // See <reloc.h>.
233  const MCSymbol *A = &Target.getSymA()->getSymbol();
234  MCSymbolData *A_SD = &Asm.getSymbolData(*A);
235
236  if (!A_SD->getFragment())
237    report_fatal_error("symbol '" + A->getName() +
238                       "' can not be undefined in a subtraction expression");
239
240  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
241  uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
242  FixedValue += SecAddr;
243  uint32_t Value2 = 0;
244
245  if (const MCSymbolRefExpr *B = Target.getSymB()) {
246    MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
247
248    if (!B_SD->getFragment())
249      report_fatal_error("symbol '" + B->getSymbol().getName() +
250                         "' can not be undefined in a subtraction expression");
251
252    // Select the appropriate difference relocation type.
253    Type = macho::RIT_Difference;
254    Value2 = Writer->getSymbolAddress(B_SD, Layout);
255    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
256  }
257
258  // Relocations are written out in reverse order, so the PAIR comes first.
259  if (Type == macho::RIT_Difference ||
260      Type == macho::RIT_Generic_LocalDifference) {
261    macho::RelocationEntry MRE;
262    MRE.Word0 = ((0         <<  0) |
263                 (macho::RIT_Pair  << 24) |
264                 (Log2Size  << 28) |
265                 (IsPCRel   << 30) |
266                 macho::RF_Scattered);
267    MRE.Word1 = Value2;
268    Writer->addRelocation(Fragment->getParent(), MRE);
269  }
270
271  macho::RelocationEntry MRE;
272  MRE.Word0 = ((FixupOffset <<  0) |
273               (Type        << 24) |
274               (Log2Size    << 28) |
275               (IsPCRel     << 30) |
276               macho::RF_Scattered);
277  MRE.Word1 = Value;
278  Writer->addRelocation(Fragment->getParent(), MRE);
279}
280
281void ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
282                                           const MCAssembler &Asm,
283                                           const MCAsmLayout &Layout,
284                                           const MCFragment *Fragment,
285                                           const MCFixup &Fixup,
286                                           MCValue Target,
287                                           uint64_t &FixedValue) {
288  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
289  unsigned Log2Size;
290  unsigned RelocType = macho::RIT_Vanilla;
291  if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) {
292    report_fatal_error("unknown ARM fixup kind!");
293    return;
294  }
295
296  // If this is a difference or a defined symbol plus an offset, then we need a
297  // scattered relocation entry.  Differences always require scattered
298  // relocations.
299  if (Target.getSymB()) {
300    if (RelocType == macho::RIT_ARM_Half ||
301        RelocType == macho::RIT_ARM_HalfDifference)
302      return RecordARMMovwMovtRelocation(Writer, Asm, Layout, Fragment, Fixup,
303                                         Target, FixedValue);
304    return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
305                                        Target, Log2Size, FixedValue);
306  }
307
308  // Get the symbol data, if any.
309  MCSymbolData *SD = 0;
310  if (Target.getSymA())
311    SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
312
313  // FIXME: For other platforms, we need to use scattered relocations for
314  // internal relocations with offsets.  If this is an internal relocation with
315  // an offset, it also needs a scattered relocation entry.
316  //
317  // Is this right for ARM?
318  uint32_t Offset = Target.getConstant();
319  if (IsPCRel && RelocType == macho::RIT_Vanilla)
320    Offset += 1 << Log2Size;
321  if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD))
322    return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
323                                        Target, Log2Size, FixedValue);
324
325  // See <reloc.h>.
326  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
327  unsigned Index = 0;
328  unsigned IsExtern = 0;
329  unsigned Type = 0;
330
331  if (Target.isAbsolute()) { // constant
332    // FIXME!
333    report_fatal_error("FIXME: relocations to absolute targets "
334                       "not yet implemented");
335  } else {
336    // Resolve constant variables.
337    if (SD->getSymbol().isVariable()) {
338      int64_t Res;
339      if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
340            Res, Layout, Writer->getSectionAddressMap())) {
341        FixedValue = Res;
342        return;
343      }
344    }
345
346    // Check whether we need an external or internal relocation.
347    if (Writer->doesSymbolRequireExternRelocation(SD)) {
348      IsExtern = 1;
349      Index = SD->getIndex();
350
351      // For external relocations, make sure to offset the fixup value to
352      // compensate for the addend of the symbol address, if it was
353      // undefined. This occurs with weak definitions, for example.
354      if (!SD->Symbol->isUndefined())
355        FixedValue -= Layout.getSymbolOffset(SD);
356    } else {
357      // The index is the section ordinal (1-based).
358      const MCSectionData &SymSD = Asm.getSectionData(
359        SD->getSymbol().getSection());
360      Index = SymSD.getOrdinal() + 1;
361      FixedValue += Writer->getSectionAddress(&SymSD);
362    }
363    if (IsPCRel)
364      FixedValue -= Writer->getSectionAddress(Fragment->getParent());
365
366    // The type is determined by the fixup kind.
367    Type = RelocType;
368  }
369
370  // struct relocation_info (8 bytes)
371  macho::RelocationEntry MRE;
372  MRE.Word0 = FixupOffset;
373  MRE.Word1 = ((Index     <<  0) |
374               (IsPCRel   << 24) |
375               (Log2Size  << 25) |
376               (IsExtern  << 27) |
377               (Type      << 28));
378  Writer->addRelocation(Fragment->getParent(), MRE);
379}
380
381MCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS,
382                                                bool Is64Bit,
383                                                uint32_t CPUType,
384                                                uint32_t CPUSubtype) {
385  return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit,
386                                                        CPUType,
387                                                        CPUSubtype),
388                                OS, /*IsLittleEndian=*/true);
389}
390