ARMMachObjectWriter.cpp revision 261991
1210944Sjkim//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===//
2210944Sjkim//
3210944Sjkim//                     The LLVM Compiler Infrastructure
4210944Sjkim//
5210944Sjkim// This file is distributed under the University of Illinois Open Source
6210944Sjkim// License. See LICENSE.TXT for details.
7217365Sjkim//
8281075Sdim//===----------------------------------------------------------------------===//
9210944Sjkim
10210944Sjkim#include "MCTargetDesc/ARMMCTargetDesc.h"
11217365Sjkim#include "MCTargetDesc/ARMBaseInfo.h"
12217365Sjkim#include "MCTargetDesc/ARMFixupKinds.h"
13217365Sjkim#include "llvm/ADT/Twine.h"
14217365Sjkim#include "llvm/MC/MCAsmLayout.h"
15217365Sjkim#include "llvm/MC/MCAssembler.h"
16217365Sjkim#include "llvm/MC/MCContext.h"
17217365Sjkim#include "llvm/MC/MCExpr.h"
18217365Sjkim#include "llvm/MC/MCFixup.h"
19217365Sjkim#include "llvm/MC/MCFixupKindInfo.h"
20217365Sjkim#include "llvm/MC/MCMachOSymbolFlags.h"
21217365Sjkim#include "llvm/MC/MCMachObjectWriter.h"
22217365Sjkim#include "llvm/MC/MCValue.h"
23217365Sjkim#include "llvm/Support/ErrorHandling.h"
24217365Sjkim#include "llvm/Support/MachO.h"
25210944Sjkimusing namespace llvm;
26217365Sjkim
27217365Sjkimnamespace {
28217365Sjkimclass ARMMachObjectWriter : public MCMachObjectTargetWriter {
29210944Sjkim  void RecordARMScatteredRelocation(MachObjectWriter *Writer,
30217365Sjkim                                    const MCAssembler &Asm,
31217365Sjkim                                    const MCAsmLayout &Layout,
32217365Sjkim                                    const MCFragment *Fragment,
33217365Sjkim                                    const MCFixup &Fixup,
34217365Sjkim                                    MCValue Target,
35217365Sjkim                                    unsigned Log2Size,
36217365Sjkim                                    uint64_t &FixedValue);
37217365Sjkim  void RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
38217365Sjkim                                        const MCAssembler &Asm,
39217365Sjkim                                        const MCAsmLayout &Layout,
40217365Sjkim                                        const MCFragment *Fragment,
41217365Sjkim                                        const MCFixup &Fixup, MCValue Target,
42217365Sjkim                                        uint64_t &FixedValue);
43210944Sjkim
44210976Sjkim  bool requiresExternRelocation(MachObjectWriter *Writer,
45210976Sjkim                                const MCAssembler &Asm,
46210944Sjkim                                const MCFragment &Fragment,
47210944Sjkim                                unsigned RelocType, const MCSymbolData *SD,
48210944Sjkim                                uint64_t FixedValue);
49210944Sjkim
50210944Sjkimpublic:
51281075Sdim  ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType,
52281075Sdim                      uint32_t CPUSubtype)
53281075Sdim    : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
54281075Sdim                               /*UseAggressiveSymbolFolding=*/true) {}
55281075Sdim
56281075Sdim  void RecordRelocation(MachObjectWriter *Writer,
57281075Sdim                        const MCAssembler &Asm, const MCAsmLayout &Layout,
58281075Sdim                        const MCFragment *Fragment, const MCFixup &Fixup,
59281075Sdim                        MCValue Target, uint64_t &FixedValue);
60281075Sdim};
61281075Sdim}
62281075Sdim
63281075Sdimstatic bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
64281075Sdim                              unsigned &Log2Size) {
65281075Sdim  RelocType = unsigned(MachO::ARM_RELOC_VANILLA);
66281075Sdim  Log2Size = ~0U;
67281075Sdim
68281075Sdim  switch (Kind) {
69281075Sdim  default:
70281075Sdim    return false;
71281075Sdim
72281075Sdim  case FK_Data_1:
73281075Sdim    Log2Size = llvm::Log2_32(1);
74281075Sdim    return true;
75281075Sdim  case FK_Data_2:
76281075Sdim    Log2Size = llvm::Log2_32(2);
77281075Sdim    return true;
78281075Sdim  case FK_Data_4:
79210944Sjkim    Log2Size = llvm::Log2_32(4);
80210944Sjkim    return true;
81210944Sjkim  case FK_Data_8:
82210944Sjkim    Log2Size = llvm::Log2_32(8);
83210944Sjkim    return true;
84210944Sjkim
85210944Sjkim    // Handle 24-bit branch kinds.
86210944Sjkim  case ARM::fixup_arm_ldst_pcrel_12:
87210944Sjkim  case ARM::fixup_arm_pcrel_10:
88210944Sjkim  case ARM::fixup_arm_adr_pcrel_12:
89210944Sjkim  case ARM::fixup_arm_condbranch:
90210944Sjkim  case ARM::fixup_arm_uncondbranch:
91210944Sjkim  case ARM::fixup_arm_uncondbl:
92210944Sjkim  case ARM::fixup_arm_condbl:
93210944Sjkim  case ARM::fixup_arm_blx:
94210944Sjkim    RelocType = unsigned(MachO::ARM_RELOC_BR24);
95210944Sjkim    // Report as 'long', even though that is not quite accurate.
96210944Sjkim    Log2Size = llvm::Log2_32(4);
97210944Sjkim    return true;
98210944Sjkim
99210944Sjkim    // Handle Thumb branches.
100210944Sjkim  case ARM::fixup_arm_thumb_br:
101210944Sjkim    RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22);
102210944Sjkim    Log2Size = llvm::Log2_32(2);
103210944Sjkim    return true;
104213806Sjkim
105210944Sjkim  case ARM::fixup_t2_uncondbranch:
106239340Sjkim  case ARM::fixup_arm_thumb_bl:
107281075Sdim  case ARM::fixup_arm_thumb_blx:
108281687Sjkim    RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22);
109210944Sjkim    Log2Size = llvm::Log2_32(4);
110210944Sjkim    return true;
111210944Sjkim
112253690Sjkim  // For movw/movt r_type relocations they always have a pair following them and
113210944Sjkim  // the r_length bits are used differently.  The encoding of the r_length is as
114210944Sjkim  // follows:
115210944Sjkim  //   low bit of r_length:
116253690Sjkim  //      0 - :lower16: for movw instructions
117253690Sjkim  //      1 - :upper16: for movt instructions
118253690Sjkim  //   high bit of r_length:
119210944Sjkim  //      0 - arm instructions
120253690Sjkim  //      1 - thumb instructions
121253690Sjkim  case ARM::fixup_arm_movt_hi16:
122253690Sjkim  case ARM::fixup_arm_movt_hi16_pcrel:
123253690Sjkim    RelocType = unsigned(MachO::ARM_RELOC_HALF);
124253690Sjkim    Log2Size = 1;
125253690Sjkim    return true;
126210944Sjkim  case ARM::fixup_t2_movt_hi16:
127210944Sjkim  case ARM::fixup_t2_movt_hi16_pcrel:
128210944Sjkim    RelocType = unsigned(MachO::ARM_RELOC_HALF);
129210944Sjkim    Log2Size = 3;
130210944Sjkim    return true;
131210944Sjkim
132210944Sjkim  case ARM::fixup_arm_movw_lo16:
133210944Sjkim  case ARM::fixup_arm_movw_lo16_pcrel:
134210944Sjkim    RelocType = unsigned(MachO::ARM_RELOC_HALF);
135210944Sjkim    Log2Size = 0;
136210944Sjkim    return true;
137210944Sjkim  case ARM::fixup_t2_movw_lo16:
138210944Sjkim  case ARM::fixup_t2_movw_lo16_pcrel:
139210944Sjkim    RelocType = unsigned(MachO::ARM_RELOC_HALF);
140210944Sjkim    Log2Size = 2;
141210944Sjkim    return true;
142210944Sjkim  }
143210944Sjkim}
144210944Sjkim
145249112Sjkimvoid ARMMachObjectWriter::
146210944SjkimRecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
147210944Sjkim                                 const MCAssembler &Asm,
148210944Sjkim                                 const MCAsmLayout &Layout,
149249112Sjkim                                 const MCFragment *Fragment,
150249112Sjkim                                 const MCFixup &Fixup,
151249112Sjkim                                 MCValue Target,
152249112Sjkim                                 uint64_t &FixedValue) {
153249112Sjkim  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
154249112Sjkim  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
155210944Sjkim  unsigned Type = MachO::ARM_RELOC_HALF;
156210944Sjkim
157210944Sjkim  // See <reloc.h>.
158210944Sjkim  const MCSymbol *A = &Target.getSymA()->getSymbol();
159210944Sjkim  MCSymbolData *A_SD = &Asm.getSymbolData(*A);
160210944Sjkim
161210944Sjkim  if (!A_SD->getFragment())
162210944Sjkim    Asm.getContext().FatalError(Fixup.getLoc(),
163210944Sjkim                       "symbol '" + A->getName() +
164210944Sjkim                       "' can not be undefined in a subtraction expression");
165210944Sjkim
166210944Sjkim  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
167210944Sjkim  uint32_t Value2 = 0;
168210944Sjkim  uint64_t SecAddr =
169210944Sjkim    Writer->getSectionAddress(A_SD->getFragment()->getParent());
170210944Sjkim  FixedValue += SecAddr;
171210944Sjkim
172210944Sjkim  if (const MCSymbolRefExpr *B = Target.getSymB()) {
173210944Sjkim    MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
174210944Sjkim
175210944Sjkim    if (!B_SD->getFragment())
176249112Sjkim      Asm.getContext().FatalError(Fixup.getLoc(),
177210944Sjkim                         "symbol '" + B->getSymbol().getName() +
178210944Sjkim                         "' can not be undefined in a subtraction expression");
179210944Sjkim
180210944Sjkim    // Select the appropriate difference relocation type.
181210944Sjkim    Type = MachO::ARM_RELOC_HALF_SECTDIFF;
182210944Sjkim    Value2 = Writer->getSymbolAddress(B_SD, Layout);
183249112Sjkim    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
184210944Sjkim  }
185210944Sjkim
186210944Sjkim  // Relocations are written out in reverse order, so the PAIR comes first.
187249112Sjkim  // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
188210944Sjkim  //
189210944Sjkim  // For these two r_type relocations they always have a pair following them and
190210944Sjkim  // the r_length bits are used differently.  The encoding of the r_length is as
191249112Sjkim  // follows:
192249112Sjkim  //   low bit of r_length:
193249112Sjkim  //      0 - :lower16: for movw instructions
194249112Sjkim  //      1 - :upper16: for movt instructions
195249112Sjkim  //   high bit of r_length:
196249112Sjkim  //      0 - arm instructions
197210944Sjkim  //      1 - thumb instructions
198210944Sjkim  // the other half of the relocated expression is in the following pair
199210944Sjkim  // relocation entry in the low 16 bits of r_address field.
200210944Sjkim  unsigned ThumbBit = 0;
201210944Sjkim  unsigned MovtBit = 0;
202210944Sjkim  switch ((unsigned)Fixup.getKind()) {
203210944Sjkim  default: break;
204253690Sjkim  case ARM::fixup_arm_movt_hi16:
205253690Sjkim  case ARM::fixup_arm_movt_hi16_pcrel:
206210944Sjkim    MovtBit = 1;
207210944Sjkim    // The thumb bit shouldn't be set in the 'other-half' bit of the
208210944Sjkim    // relocation, but it will be set in FixedValue if the base symbol
209253690Sjkim    // is a thumb function. Clear it out here.
210253690Sjkim    if (A_SD->getFlags() & SF_ThumbFunc)
211253690Sjkim      FixedValue &= 0xfffffffe;
212210944Sjkim    break;
213253690Sjkim  case ARM::fixup_t2_movt_hi16:
214253690Sjkim  case ARM::fixup_t2_movt_hi16_pcrel:
215253690Sjkim    if (A_SD->getFlags() & SF_ThumbFunc)
216253690Sjkim      FixedValue &= 0xfffffffe;
217253690Sjkim    MovtBit = 1;
218253690Sjkim    // Fallthrough
219253690Sjkim  case ARM::fixup_t2_movw_lo16:
220253690Sjkim  case ARM::fixup_t2_movw_lo16_pcrel:
221253690Sjkim    ThumbBit = 1;
222253690Sjkim    break;
223210944Sjkim  }
224210944Sjkim
225210944Sjkim  if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
226210944Sjkim    uint32_t OtherHalf = MovtBit
227249112Sjkim      ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
228210944Sjkim
229210944Sjkim    MachO::any_relocation_info MRE;
230210944Sjkim    MRE.r_word0 = ((OtherHalf             <<  0) |
231210944Sjkim                   (MachO::ARM_RELOC_PAIR << 24) |
232210944Sjkim                   (MovtBit               << 28) |
233210944Sjkim                   (ThumbBit              << 29) |
234210944Sjkim                   (IsPCRel               << 30) |
235210944Sjkim                   MachO::R_SCATTERED);
236210944Sjkim    MRE.r_word1 = Value2;
237210944Sjkim    Writer->addRelocation(Fragment->getParent(), MRE);
238210944Sjkim  }
239210944Sjkim
240210944Sjkim  MachO::any_relocation_info MRE;
241210944Sjkim  MRE.r_word0 = ((FixupOffset <<  0) |
242210944Sjkim                 (Type        << 24) |
243210944Sjkim                 (MovtBit     << 28) |
244210944Sjkim                 (ThumbBit    << 29) |
245210944Sjkim                 (IsPCRel     << 30) |
246210944Sjkim                 MachO::R_SCATTERED);
247210944Sjkim  MRE.r_word1 = Value;
248210944Sjkim  Writer->addRelocation(Fragment->getParent(), MRE);
249210944Sjkim}
250210944Sjkim
251210944Sjkimvoid ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
252210944Sjkim                                                    const MCAssembler &Asm,
253210944Sjkim                                                    const MCAsmLayout &Layout,
254210944Sjkim                                                    const MCFragment *Fragment,
255210944Sjkim                                                    const MCFixup &Fixup,
256210944Sjkim                                                    MCValue Target,
257210944Sjkim                                                    unsigned Log2Size,
258210944Sjkim                                                    uint64_t &FixedValue) {
259210944Sjkim  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
260210944Sjkim  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
261210944Sjkim  unsigned Type = MachO::ARM_RELOC_VANILLA;
262210944Sjkim
263210944Sjkim  // See <reloc.h>.
264210944Sjkim  const MCSymbol *A = &Target.getSymA()->getSymbol();
265210944Sjkim  MCSymbolData *A_SD = &Asm.getSymbolData(*A);
266210944Sjkim
267210944Sjkim  if (!A_SD->getFragment())
268210944Sjkim    Asm.getContext().FatalError(Fixup.getLoc(),
269210944Sjkim                       "symbol '" + A->getName() +
270210944Sjkim                       "' can not be undefined in a subtraction expression");
271210944Sjkim
272210944Sjkim  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
273210944Sjkim  uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
274210944Sjkim  FixedValue += SecAddr;
275210944Sjkim  uint32_t Value2 = 0;
276210944Sjkim
277210944Sjkim  if (const MCSymbolRefExpr *B = Target.getSymB()) {
278210944Sjkim    MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
279210944Sjkim
280210944Sjkim    if (!B_SD->getFragment())
281210944Sjkim      Asm.getContext().FatalError(Fixup.getLoc(),
282210944Sjkim                         "symbol '" + B->getSymbol().getName() +
283210944Sjkim                         "' can not be undefined in a subtraction expression");
284210944Sjkim
285210944Sjkim    // Select the appropriate difference relocation type.
286210944Sjkim    Type = MachO::ARM_RELOC_SECTDIFF;
287210944Sjkim    Value2 = Writer->getSymbolAddress(B_SD, Layout);
288210944Sjkim    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
289210944Sjkim  }
290210944Sjkim
291210944Sjkim  // Relocations are written out in reverse order, so the PAIR comes first.
292210944Sjkim  if (Type == MachO::ARM_RELOC_SECTDIFF ||
293210944Sjkim      Type == MachO::ARM_RELOC_LOCAL_SECTDIFF) {
294210944Sjkim    MachO::any_relocation_info MRE;
295210944Sjkim    MRE.r_word0 = ((0                     <<  0) |
296210944Sjkim                   (MachO::ARM_RELOC_PAIR << 24) |
297210944Sjkim                   (Log2Size              << 28) |
298210944Sjkim                   (IsPCRel               << 30) |
299210944Sjkim                   MachO::R_SCATTERED);
300210944Sjkim    MRE.r_word1 = Value2;
301210944Sjkim    Writer->addRelocation(Fragment->getParent(), MRE);
302210944Sjkim  }
303210944Sjkim
304210944Sjkim  MachO::any_relocation_info MRE;
305210944Sjkim  MRE.r_word0 = ((FixupOffset <<  0) |
306210944Sjkim                 (Type        << 24) |
307210944Sjkim                 (Log2Size    << 28) |
308210944Sjkim                 (IsPCRel     << 30) |
309210944Sjkim                 MachO::R_SCATTERED);
310210944Sjkim  MRE.r_word1 = Value;
311210944Sjkim  Writer->addRelocation(Fragment->getParent(), MRE);
312210944Sjkim}
313210944Sjkim
314210944Sjkimbool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer,
315210944Sjkim                                                   const MCAssembler &Asm,
316210944Sjkim                                                   const MCFragment &Fragment,
317210944Sjkim                                                   unsigned RelocType,
318210944Sjkim                                                   const MCSymbolData *SD,
319210944Sjkim                                                   uint64_t FixedValue) {
320210944Sjkim  // Most cases can be identified purely from the symbol.
321210944Sjkim  if (Writer->doesSymbolRequireExternRelocation(SD))
322210944Sjkim    return true;
323210944Sjkim  int64_t Value = (int64_t)FixedValue;  // The displacement is signed.
324210944Sjkim  int64_t Range;
325210944Sjkim  switch (RelocType) {
326210944Sjkim  default:
327210944Sjkim    return false;
328210944Sjkim  case MachO::ARM_RELOC_BR24:
329210944Sjkim    // PC pre-adjustment of 8 for these instructions.
330210944Sjkim    Value -= 8;
331210944Sjkim    // ARM BL/BLX has a 25-bit offset.
332210944Sjkim    Range = 0x1ffffff;
333210944Sjkim    break;
334210944Sjkim  case MachO::ARM_THUMB_RELOC_BR22:
335210944Sjkim    // PC pre-adjustment of 4 for these instructions.
336210944Sjkim    Value -= 4;
337210944Sjkim    // Thumb BL/BLX has a 24-bit offset.
338210944Sjkim    Range = 0xffffff;
339210944Sjkim  }
340210944Sjkim  // BL/BLX also use external relocations when an internal relocation
341210944Sjkim  // would result in the target being out of range. This gives the linker
342210944Sjkim  // enough information to generate a branch island.
343210944Sjkim  const MCSectionData &SymSD = Asm.getSectionData(
344210944Sjkim    SD->getSymbol().getSection());
345210944Sjkim  Value += Writer->getSectionAddress(&SymSD);
346210944Sjkim  Value -= Writer->getSectionAddress(Fragment.getParent());
347210944Sjkim  // If the resultant value would be out of range for an internal relocation,
348210944Sjkim  // use an external instead.
349210944Sjkim  if (Value > Range || Value < -(Range + 1))
350253690Sjkim    return true;
351253690Sjkim  return false;
352253690Sjkim}
353253690Sjkim
354253690Sjkimvoid ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer,
355253690Sjkim                                           const MCAssembler &Asm,
356253690Sjkim                                           const MCAsmLayout &Layout,
357253690Sjkim                                           const MCFragment *Fragment,
358253690Sjkim                                           const MCFixup &Fixup,
359253690Sjkim                                           MCValue Target,
360253690Sjkim                                           uint64_t &FixedValue) {
361253690Sjkim  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
362253690Sjkim  unsigned Log2Size;
363253690Sjkim  unsigned RelocType = MachO::ARM_RELOC_VANILLA;
364253690Sjkim  if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size))
365253690Sjkim    // If we failed to get fixup kind info, it's because there's no legal
366253690Sjkim    // relocation type for the fixup kind. This happens when it's a fixup that's
367253690Sjkim    // expected to always be resolvable at assembly time and not have any
368253690Sjkim    // relocations needed.
369253690Sjkim    Asm.getContext().FatalError(Fixup.getLoc(),
370253690Sjkim                                "unsupported relocation on symbol");
371253690Sjkim
372253690Sjkim  // If this is a difference or a defined symbol plus an offset, then we need a
373253690Sjkim  // scattered relocation entry.  Differences always require scattered
374253690Sjkim  // relocations.
375253690Sjkim  if (Target.getSymB()) {
376253690Sjkim    if (RelocType == MachO::ARM_RELOC_HALF)
377253690Sjkim      return RecordARMScatteredHalfRelocation(Writer, Asm, Layout, Fragment,
378253690Sjkim                                              Fixup, Target, FixedValue);
379253690Sjkim    return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
380253690Sjkim                                        Target, Log2Size, FixedValue);
381253690Sjkim  }
382253690Sjkim
383253690Sjkim  // Get the symbol data, if any.
384253690Sjkim  MCSymbolData *SD = 0;
385253690Sjkim  if (Target.getSymA())
386253690Sjkim    SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
387253690Sjkim
388253690Sjkim  // FIXME: For other platforms, we need to use scattered relocations for
389253690Sjkim  // internal relocations with offsets.  If this is an internal relocation with
390253690Sjkim  // an offset, it also needs a scattered relocation entry.
391253690Sjkim  //
392253690Sjkim  // Is this right for ARM?
393253690Sjkim  uint32_t Offset = Target.getConstant();
394253690Sjkim  if (IsPCRel && RelocType == MachO::ARM_RELOC_VANILLA)
395253690Sjkim    Offset += 1 << Log2Size;
396253690Sjkim  if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD))
397253690Sjkim    return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
398253690Sjkim                                        Target, Log2Size, FixedValue);
399253690Sjkim
400253690Sjkim  // See <reloc.h>.
401210944Sjkim  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
402210944Sjkim  unsigned Index = 0;
403210944Sjkim  unsigned IsExtern = 0;
404210944Sjkim  unsigned Type = 0;
405210944Sjkim
406210944Sjkim  if (Target.isAbsolute()) { // constant
407210944Sjkim    // FIXME!
408210944Sjkim    report_fatal_error("FIXME: relocations to absolute targets "
409210944Sjkim                       "not yet implemented");
410210944Sjkim  } else {
411210944Sjkim    // Resolve constant variables.
412210944Sjkim    if (SD->getSymbol().isVariable()) {
413210944Sjkim      int64_t Res;
414210944Sjkim      if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
415210944Sjkim            Res, Layout, Writer->getSectionAddressMap())) {
416210944Sjkim        FixedValue = Res;
417210944Sjkim        return;
418210944Sjkim      }
419210944Sjkim    }
420210944Sjkim
421210944Sjkim    // Check whether we need an external or internal relocation.
422210944Sjkim    if (requiresExternRelocation(Writer, Asm, *Fragment, RelocType, SD,
423210944Sjkim                                 FixedValue)) {
424210944Sjkim      IsExtern = 1;
425210944Sjkim      Index = SD->getIndex();
426210944Sjkim
427210944Sjkim      // For external relocations, make sure to offset the fixup value to
428210944Sjkim      // compensate for the addend of the symbol address, if it was
429210944Sjkim      // undefined. This occurs with weak definitions, for example.
430210944Sjkim      if (!SD->Symbol->isUndefined())
431210944Sjkim        FixedValue -= Layout.getSymbolOffset(SD);
432210944Sjkim    } else {
433210944Sjkim      // The index is the section ordinal (1-based).
434210944Sjkim      const MCSectionData &SymSD = Asm.getSectionData(
435210944Sjkim        SD->getSymbol().getSection());
436210944Sjkim      Index = SymSD.getOrdinal() + 1;
437210944Sjkim      FixedValue += Writer->getSectionAddress(&SymSD);
438210944Sjkim    }
439210944Sjkim    if (IsPCRel)
440210944Sjkim      FixedValue -= Writer->getSectionAddress(Fragment->getParent());
441210944Sjkim
442210944Sjkim    // The type is determined by the fixup kind.
443210944Sjkim    Type = RelocType;
444210944Sjkim  }
445210944Sjkim
446210944Sjkim  // struct relocation_info (8 bytes)
447210944Sjkim  MachO::any_relocation_info MRE;
448210944Sjkim  MRE.r_word0 = FixupOffset;
449210944Sjkim  MRE.r_word1 = ((Index     <<  0) |
450210944Sjkim                 (IsPCRel   << 24) |
451210944Sjkim                 (Log2Size  << 25) |
452210944Sjkim                 (IsExtern  << 27) |
453210944Sjkim                 (Type      << 28));
454210944Sjkim
455210944Sjkim  // Even when it's not a scattered relocation, movw/movt always uses
456249112Sjkim  // a PAIR relocation.
457210944Sjkim  if (Type == MachO::ARM_RELOC_HALF) {
458210944Sjkim    // The other-half value only gets populated for the movt and movw
459210944Sjkim    // relocation entries.
460210944Sjkim    uint32_t Value = 0;
461210944Sjkim    switch ((unsigned)Fixup.getKind()) {
462210944Sjkim    default: break;
463210944Sjkim    case ARM::fixup_arm_movw_lo16:
464210944Sjkim    case ARM::fixup_arm_movw_lo16_pcrel:
465210944Sjkim    case ARM::fixup_t2_movw_lo16:
466210944Sjkim    case ARM::fixup_t2_movw_lo16_pcrel:
467210944Sjkim      Value = (FixedValue >> 16) & 0xffff;
468210944Sjkim      break;
469210944Sjkim    case ARM::fixup_arm_movt_hi16:
470210944Sjkim    case ARM::fixup_arm_movt_hi16_pcrel:
471210944Sjkim    case ARM::fixup_t2_movt_hi16:
472210944Sjkim    case ARM::fixup_t2_movt_hi16_pcrel:
473210944Sjkim      Value = FixedValue & 0xffff;
474210944Sjkim      break;
475210944Sjkim    }
476210944Sjkim    MachO::any_relocation_info MREPair;
477210944Sjkim    MREPair.r_word0 = Value;
478210944Sjkim    MREPair.r_word1 = ((0xffffff              <<  0) |
479210944Sjkim                       (Log2Size              << 25) |
480210944Sjkim                       (MachO::ARM_RELOC_PAIR << 28));
481210944Sjkim
482210944Sjkim    Writer->addRelocation(Fragment->getParent(), MREPair);
483249112Sjkim  }
484249112Sjkim
485249112Sjkim  Writer->addRelocation(Fragment->getParent(), MRE);
486249663Sjkim}
487249112Sjkim
488249112SjkimMCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS,
489210944Sjkim                                                bool Is64Bit,
490210944Sjkim                                                uint32_t CPUType,
491210944Sjkim                                                uint32_t CPUSubtype) {
492210944Sjkim  return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit,
493210944Sjkim                                                        CPUType,
494210944Sjkim                                                        CPUSubtype),
495210944Sjkim                                OS, /*IsLittleEndian=*/true);
496210944Sjkim}
497210944Sjkim