1226584Sdim//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===//
2226584Sdim//
3226584Sdim//                     The LLVM Compiler Infrastructure
4226584Sdim//
5226584Sdim// This file is distributed under the University of Illinois Open Source
6226584Sdim// License. See LICENSE.TXT for details.
7226584Sdim//
8226584Sdim//===----------------------------------------------------------------------===//
9226584Sdim
10249423Sdim#include "MCTargetDesc/ARMMCTargetDesc.h"
11226584Sdim#include "MCTargetDesc/ARMBaseInfo.h"
12226584Sdim#include "MCTargetDesc/ARMFixupKinds.h"
13226584Sdim#include "llvm/ADT/Twine.h"
14249423Sdim#include "llvm/MC/MCAsmLayout.h"
15226584Sdim#include "llvm/MC/MCAssembler.h"
16234353Sdim#include "llvm/MC/MCContext.h"
17226584Sdim#include "llvm/MC/MCExpr.h"
18226584Sdim#include "llvm/MC/MCFixup.h"
19226584Sdim#include "llvm/MC/MCFixupKindInfo.h"
20249423Sdim#include "llvm/MC/MCMachObjectWriter.h"
21288943Sdim#include "llvm/MC/MCSection.h"
22226584Sdim#include "llvm/MC/MCValue.h"
23226584Sdim#include "llvm/Support/ErrorHandling.h"
24261991Sdim#include "llvm/Support/MachO.h"
25226584Sdimusing namespace llvm;
26226584Sdim
27226584Sdimnamespace {
28226584Sdimclass ARMMachObjectWriter : public MCMachObjectTargetWriter {
29226584Sdim  void RecordARMScatteredRelocation(MachObjectWriter *Writer,
30226584Sdim                                    const MCAssembler &Asm,
31226584Sdim                                    const MCAsmLayout &Layout,
32226584Sdim                                    const MCFragment *Fragment,
33226584Sdim                                    const MCFixup &Fixup,
34226584Sdim                                    MCValue Target,
35276479Sdim                                    unsigned Type,
36226584Sdim                                    unsigned Log2Size,
37226584Sdim                                    uint64_t &FixedValue);
38234353Sdim  void RecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
39234353Sdim                                        const MCAssembler &Asm,
40234353Sdim                                        const MCAsmLayout &Layout,
41234353Sdim                                        const MCFragment *Fragment,
42234353Sdim                                        const MCFixup &Fixup, MCValue Target,
43234353Sdim                                        uint64_t &FixedValue);
44226584Sdim
45243830Sdim  bool requiresExternRelocation(MachObjectWriter *Writer,
46243830Sdim                                const MCAssembler &Asm,
47288943Sdim                                const MCFragment &Fragment, unsigned RelocType,
48288943Sdim                                const MCSymbol &S, uint64_t FixedValue);
49243830Sdim
50226584Sdimpublic:
51288943Sdim  ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)
52288943Sdim      : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}
53226584Sdim
54288943Sdim  void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
55288943Sdim                        const MCAsmLayout &Layout, const MCFragment *Fragment,
56288943Sdim                        const MCFixup &Fixup, MCValue Target,
57288943Sdim                        uint64_t &FixedValue) override;
58226584Sdim};
59226584Sdim}
60226584Sdim
61226584Sdimstatic bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
62226584Sdim                              unsigned &Log2Size) {
63261991Sdim  RelocType = unsigned(MachO::ARM_RELOC_VANILLA);
64226584Sdim  Log2Size = ~0U;
65226584Sdim
66226584Sdim  switch (Kind) {
67226584Sdim  default:
68226584Sdim    return false;
69226584Sdim
70226584Sdim  case FK_Data_1:
71226584Sdim    Log2Size = llvm::Log2_32(1);
72226584Sdim    return true;
73226584Sdim  case FK_Data_2:
74226584Sdim    Log2Size = llvm::Log2_32(2);
75226584Sdim    return true;
76226584Sdim  case FK_Data_4:
77226584Sdim    Log2Size = llvm::Log2_32(4);
78226584Sdim    return true;
79226584Sdim  case FK_Data_8:
80226584Sdim    Log2Size = llvm::Log2_32(8);
81226584Sdim    return true;
82226584Sdim
83276479Sdim    // These fixups are expected to always be resolvable at assembly time and
84276479Sdim    // have no relocations supported.
85226584Sdim  case ARM::fixup_arm_ldst_pcrel_12:
86226584Sdim  case ARM::fixup_arm_pcrel_10:
87226584Sdim  case ARM::fixup_arm_adr_pcrel_12:
88288943Sdim  case ARM::fixup_arm_thumb_br:
89276479Sdim    return false;
90276479Sdim
91276479Sdim    // Handle 24-bit branch kinds.
92226584Sdim  case ARM::fixup_arm_condbranch:
93226584Sdim  case ARM::fixup_arm_uncondbranch:
94234353Sdim  case ARM::fixup_arm_uncondbl:
95234353Sdim  case ARM::fixup_arm_condbl:
96234353Sdim  case ARM::fixup_arm_blx:
97261991Sdim    RelocType = unsigned(MachO::ARM_RELOC_BR24);
98226584Sdim    // Report as 'long', even though that is not quite accurate.
99226584Sdim    Log2Size = llvm::Log2_32(4);
100226584Sdim    return true;
101226584Sdim
102226584Sdim  case ARM::fixup_t2_uncondbranch:
103226584Sdim  case ARM::fixup_arm_thumb_bl:
104226584Sdim  case ARM::fixup_arm_thumb_blx:
105261991Sdim    RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22);
106226584Sdim    Log2Size = llvm::Log2_32(4);
107226584Sdim    return true;
108226584Sdim
109234353Sdim  // For movw/movt r_type relocations they always have a pair following them and
110234353Sdim  // the r_length bits are used differently.  The encoding of the r_length is as
111234353Sdim  // follows:
112234353Sdim  //   low bit of r_length:
113234353Sdim  //      0 - :lower16: for movw instructions
114234353Sdim  //      1 - :upper16: for movt instructions
115234353Sdim  //   high bit of r_length:
116234353Sdim  //      0 - arm instructions
117234353Sdim  //      1 - thumb instructions
118226584Sdim  case ARM::fixup_arm_movt_hi16:
119261991Sdim    RelocType = unsigned(MachO::ARM_RELOC_HALF);
120234353Sdim    Log2Size = 1;
121234353Sdim    return true;
122226584Sdim  case ARM::fixup_t2_movt_hi16:
123261991Sdim    RelocType = unsigned(MachO::ARM_RELOC_HALF);
124234353Sdim    Log2Size = 3;
125226584Sdim    return true;
126226584Sdim
127226584Sdim  case ARM::fixup_arm_movw_lo16:
128261991Sdim    RelocType = unsigned(MachO::ARM_RELOC_HALF);
129234353Sdim    Log2Size = 0;
130234353Sdim    return true;
131226584Sdim  case ARM::fixup_t2_movw_lo16:
132261991Sdim    RelocType = unsigned(MachO::ARM_RELOC_HALF);
133234353Sdim    Log2Size = 2;
134226584Sdim    return true;
135226584Sdim  }
136226584Sdim}
137226584Sdim
138226584Sdimvoid ARMMachObjectWriter::
139234353SdimRecordARMScatteredHalfRelocation(MachObjectWriter *Writer,
140234353Sdim                                 const MCAssembler &Asm,
141234353Sdim                                 const MCAsmLayout &Layout,
142234353Sdim                                 const MCFragment *Fragment,
143234353Sdim                                 const MCFixup &Fixup,
144234353Sdim                                 MCValue Target,
145234353Sdim                                 uint64_t &FixedValue) {
146226584Sdim  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
147226584Sdim  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
148261991Sdim  unsigned Type = MachO::ARM_RELOC_HALF;
149226584Sdim
150226584Sdim  // See <reloc.h>.
151226584Sdim  const MCSymbol *A = &Target.getSymA()->getSymbol();
152226584Sdim
153296417Sdim  if (!A->getFragment()) {
154296417Sdim    Asm.getContext().reportError(Fixup.getLoc(),
155234353Sdim                       "symbol '" + A->getName() +
156226584Sdim                       "' can not be undefined in a subtraction expression");
157296417Sdim    return;
158296417Sdim  }
159226584Sdim
160288943Sdim  uint32_t Value = Writer->getSymbolAddress(*A, Layout);
161226584Sdim  uint32_t Value2 = 0;
162288943Sdim  uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());
163226584Sdim  FixedValue += SecAddr;
164226584Sdim
165226584Sdim  if (const MCSymbolRefExpr *B = Target.getSymB()) {
166288943Sdim    const MCSymbol *SB = &B->getSymbol();
167226584Sdim
168296417Sdim    if (!SB->getFragment()) {
169296417Sdim      Asm.getContext().reportError(Fixup.getLoc(),
170234353Sdim                         "symbol '" + B->getSymbol().getName() +
171226584Sdim                         "' can not be undefined in a subtraction expression");
172296417Sdim      return;
173296417Sdim    }
174226584Sdim
175226584Sdim    // Select the appropriate difference relocation type.
176261991Sdim    Type = MachO::ARM_RELOC_HALF_SECTDIFF;
177288943Sdim    Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout);
178288943Sdim    FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());
179226584Sdim  }
180226584Sdim
181226584Sdim  // Relocations are written out in reverse order, so the PAIR comes first.
182226584Sdim  // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
183226584Sdim  //
184226584Sdim  // For these two r_type relocations they always have a pair following them and
185226584Sdim  // the r_length bits are used differently.  The encoding of the r_length is as
186226584Sdim  // follows:
187226584Sdim  //   low bit of r_length:
188226584Sdim  //      0 - :lower16: for movw instructions
189226584Sdim  //      1 - :upper16: for movt instructions
190226584Sdim  //   high bit of r_length:
191226584Sdim  //      0 - arm instructions
192226584Sdim  //      1 - thumb instructions
193226584Sdim  // the other half of the relocated expression is in the following pair
194239462Sdim  // relocation entry in the low 16 bits of r_address field.
195226584Sdim  unsigned ThumbBit = 0;
196226584Sdim  unsigned MovtBit = 0;
197226584Sdim  switch ((unsigned)Fixup.getKind()) {
198226584Sdim  default: break;
199226584Sdim  case ARM::fixup_arm_movt_hi16:
200226584Sdim    MovtBit = 1;
201234353Sdim    // The thumb bit shouldn't be set in the 'other-half' bit of the
202234353Sdim    // relocation, but it will be set in FixedValue if the base symbol
203234353Sdim    // is a thumb function. Clear it out here.
204276479Sdim    if (Asm.isThumbFunc(A))
205234353Sdim      FixedValue &= 0xfffffffe;
206226584Sdim    break;
207226584Sdim  case ARM::fixup_t2_movt_hi16:
208276479Sdim    if (Asm.isThumbFunc(A))
209234353Sdim      FixedValue &= 0xfffffffe;
210226584Sdim    MovtBit = 1;
211226584Sdim    // Fallthrough
212226584Sdim  case ARM::fixup_t2_movw_lo16:
213226584Sdim    ThumbBit = 1;
214226584Sdim    break;
215226584Sdim  }
216226584Sdim
217261991Sdim  if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) {
218226584Sdim    uint32_t OtherHalf = MovtBit
219226584Sdim      ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
220226584Sdim
221261991Sdim    MachO::any_relocation_info MRE;
222261991Sdim    MRE.r_word0 = ((OtherHalf             <<  0) |
223261991Sdim                   (MachO::ARM_RELOC_PAIR << 24) |
224261991Sdim                   (MovtBit               << 28) |
225261991Sdim                   (ThumbBit              << 29) |
226261991Sdim                   (IsPCRel               << 30) |
227261991Sdim                   MachO::R_SCATTERED);
228261991Sdim    MRE.r_word1 = Value2;
229288943Sdim    Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
230226584Sdim  }
231226584Sdim
232261991Sdim  MachO::any_relocation_info MRE;
233261991Sdim  MRE.r_word0 = ((FixupOffset <<  0) |
234261991Sdim                 (Type        << 24) |
235261991Sdim                 (MovtBit     << 28) |
236261991Sdim                 (ThumbBit    << 29) |
237261991Sdim                 (IsPCRel     << 30) |
238261991Sdim                 MachO::R_SCATTERED);
239261991Sdim  MRE.r_word1 = Value;
240288943Sdim  Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
241226584Sdim}
242226584Sdim
243226584Sdimvoid ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer,
244226584Sdim                                                    const MCAssembler &Asm,
245226584Sdim                                                    const MCAsmLayout &Layout,
246226584Sdim                                                    const MCFragment *Fragment,
247226584Sdim                                                    const MCFixup &Fixup,
248226584Sdim                                                    MCValue Target,
249276479Sdim                                                    unsigned Type,
250226584Sdim                                                    unsigned Log2Size,
251226584Sdim                                                    uint64_t &FixedValue) {
252226584Sdim  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
253226584Sdim  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
254226584Sdim
255226584Sdim  // See <reloc.h>.
256226584Sdim  const MCSymbol *A = &Target.getSymA()->getSymbol();
257226584Sdim
258296417Sdim  if (!A->getFragment()) {
259296417Sdim    Asm.getContext().reportError(Fixup.getLoc(),
260234353Sdim                       "symbol '" + A->getName() +
261226584Sdim                       "' can not be undefined in a subtraction expression");
262296417Sdim    return;
263296417Sdim  }
264226584Sdim
265288943Sdim  uint32_t Value = Writer->getSymbolAddress(*A, Layout);
266288943Sdim  uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());
267226584Sdim  FixedValue += SecAddr;
268226584Sdim  uint32_t Value2 = 0;
269226584Sdim
270226584Sdim  if (const MCSymbolRefExpr *B = Target.getSymB()) {
271276479Sdim    assert(Type == MachO::ARM_RELOC_VANILLA && "invalid reloc for 2 symbols");
272288943Sdim    const MCSymbol *SB = &B->getSymbol();
273226584Sdim
274296417Sdim    if (!SB->getFragment()) {
275296417Sdim      Asm.getContext().reportError(Fixup.getLoc(),
276234353Sdim                         "symbol '" + B->getSymbol().getName() +
277226584Sdim                         "' can not be undefined in a subtraction expression");
278296417Sdim      return;
279296417Sdim    }
280226584Sdim
281226584Sdim    // Select the appropriate difference relocation type.
282261991Sdim    Type = MachO::ARM_RELOC_SECTDIFF;
283288943Sdim    Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout);
284288943Sdim    FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());
285226584Sdim  }
286226584Sdim
287226584Sdim  // Relocations are written out in reverse order, so the PAIR comes first.
288261991Sdim  if (Type == MachO::ARM_RELOC_SECTDIFF ||
289261991Sdim      Type == MachO::ARM_RELOC_LOCAL_SECTDIFF) {
290261991Sdim    MachO::any_relocation_info MRE;
291261991Sdim    MRE.r_word0 = ((0                     <<  0) |
292261991Sdim                   (MachO::ARM_RELOC_PAIR << 24) |
293261991Sdim                   (Log2Size              << 28) |
294261991Sdim                   (IsPCRel               << 30) |
295261991Sdim                   MachO::R_SCATTERED);
296261991Sdim    MRE.r_word1 = Value2;
297288943Sdim    Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
298226584Sdim  }
299226584Sdim
300261991Sdim  MachO::any_relocation_info MRE;
301261991Sdim  MRE.r_word0 = ((FixupOffset <<  0) |
302261991Sdim                 (Type        << 24) |
303261991Sdim                 (Log2Size    << 28) |
304261991Sdim                 (IsPCRel     << 30) |
305261991Sdim                 MachO::R_SCATTERED);
306261991Sdim  MRE.r_word1 = Value;
307288943Sdim  Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
308226584Sdim}
309226584Sdim
310243830Sdimbool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer,
311243830Sdim                                                   const MCAssembler &Asm,
312243830Sdim                                                   const MCFragment &Fragment,
313243830Sdim                                                   unsigned RelocType,
314288943Sdim                                                   const MCSymbol &S,
315243830Sdim                                                   uint64_t FixedValue) {
316243830Sdim  // Most cases can be identified purely from the symbol.
317288943Sdim  if (Writer->doesSymbolRequireExternRelocation(S))
318243830Sdim    return true;
319243830Sdim  int64_t Value = (int64_t)FixedValue;  // The displacement is signed.
320243830Sdim  int64_t Range;
321243830Sdim  switch (RelocType) {
322243830Sdim  default:
323243830Sdim    return false;
324261991Sdim  case MachO::ARM_RELOC_BR24:
325243830Sdim    // PC pre-adjustment of 8 for these instructions.
326243830Sdim    Value -= 8;
327243830Sdim    // ARM BL/BLX has a 25-bit offset.
328243830Sdim    Range = 0x1ffffff;
329243830Sdim    break;
330261991Sdim  case MachO::ARM_THUMB_RELOC_BR22:
331243830Sdim    // PC pre-adjustment of 4 for these instructions.
332243830Sdim    Value -= 4;
333243830Sdim    // Thumb BL/BLX has a 24-bit offset.
334243830Sdim    Range = 0xffffff;
335243830Sdim  }
336243830Sdim  // BL/BLX also use external relocations when an internal relocation
337243830Sdim  // would result in the target being out of range. This gives the linker
338243830Sdim  // enough information to generate a branch island.
339288943Sdim  Value += Writer->getSectionAddress(&S.getSection());
340243830Sdim  Value -= Writer->getSectionAddress(Fragment.getParent());
341243830Sdim  // If the resultant value would be out of range for an internal relocation,
342243830Sdim  // use an external instead.
343243830Sdim  if (Value > Range || Value < -(Range + 1))
344243830Sdim    return true;
345243830Sdim  return false;
346243830Sdim}
347243830Sdim
348288943Sdimvoid ARMMachObjectWriter::recordRelocation(MachObjectWriter *Writer,
349288943Sdim                                           MCAssembler &Asm,
350226584Sdim                                           const MCAsmLayout &Layout,
351226584Sdim                                           const MCFragment *Fragment,
352288943Sdim                                           const MCFixup &Fixup, MCValue Target,
353226584Sdim                                           uint64_t &FixedValue) {
354226584Sdim  unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
355226584Sdim  unsigned Log2Size;
356261991Sdim  unsigned RelocType = MachO::ARM_RELOC_VANILLA;
357296417Sdim  if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) {
358234353Sdim    // If we failed to get fixup kind info, it's because there's no legal
359234353Sdim    // relocation type for the fixup kind. This happens when it's a fixup that's
360234353Sdim    // expected to always be resolvable at assembly time and not have any
361234353Sdim    // relocations needed.
362296417Sdim    Asm.getContext().reportError(Fixup.getLoc(),
363296417Sdim                                 "unsupported relocation on symbol");
364296417Sdim    return;
365296417Sdim  }
366226584Sdim
367226584Sdim  // If this is a difference or a defined symbol plus an offset, then we need a
368226584Sdim  // scattered relocation entry.  Differences always require scattered
369226584Sdim  // relocations.
370226584Sdim  if (Target.getSymB()) {
371261991Sdim    if (RelocType == MachO::ARM_RELOC_HALF)
372234353Sdim      return RecordARMScatteredHalfRelocation(Writer, Asm, Layout, Fragment,
373234353Sdim                                              Fixup, Target, FixedValue);
374226584Sdim    return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
375276479Sdim                                        Target, RelocType, Log2Size,
376276479Sdim                                        FixedValue);
377226584Sdim  }
378226584Sdim
379226584Sdim  // Get the symbol data, if any.
380288943Sdim  const MCSymbol *A = nullptr;
381226584Sdim  if (Target.getSymA())
382288943Sdim    A = &Target.getSymA()->getSymbol();
383226584Sdim
384226584Sdim  // FIXME: For other platforms, we need to use scattered relocations for
385226584Sdim  // internal relocations with offsets.  If this is an internal relocation with
386226584Sdim  // an offset, it also needs a scattered relocation entry.
387226584Sdim  //
388226584Sdim  // Is this right for ARM?
389226584Sdim  uint32_t Offset = Target.getConstant();
390261991Sdim  if (IsPCRel && RelocType == MachO::ARM_RELOC_VANILLA)
391226584Sdim    Offset += 1 << Log2Size;
392288943Sdim  if (Offset && A && !Writer->doesSymbolRequireExternRelocation(*A))
393226584Sdim    return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
394276479Sdim                                        Target, RelocType, Log2Size,
395276479Sdim                                        FixedValue);
396226584Sdim
397226584Sdim  // See <reloc.h>.
398226584Sdim  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
399226584Sdim  unsigned Index = 0;
400226584Sdim  unsigned Type = 0;
401288943Sdim  const MCSymbol *RelSymbol = nullptr;
402226584Sdim
403226584Sdim  if (Target.isAbsolute()) { // constant
404226584Sdim    // FIXME!
405226584Sdim    report_fatal_error("FIXME: relocations to absolute targets "
406226584Sdim                       "not yet implemented");
407226584Sdim  } else {
408226584Sdim    // Resolve constant variables.
409288943Sdim    if (A->isVariable()) {
410226584Sdim      int64_t Res;
411288943Sdim      if (A->getVariableValue()->evaluateAsAbsolute(
412288943Sdim              Res, Layout, Writer->getSectionAddressMap())) {
413226584Sdim        FixedValue = Res;
414226584Sdim        return;
415226584Sdim      }
416226584Sdim    }
417226584Sdim
418226584Sdim    // Check whether we need an external or internal relocation.
419288943Sdim    if (requiresExternRelocation(Writer, Asm, *Fragment, RelocType, *A,
420243830Sdim                                 FixedValue)) {
421288943Sdim      RelSymbol = A;
422226584Sdim
423226584Sdim      // For external relocations, make sure to offset the fixup value to
424226584Sdim      // compensate for the addend of the symbol address, if it was
425226584Sdim      // undefined. This occurs with weak definitions, for example.
426288943Sdim      if (!A->isUndefined())
427288943Sdim        FixedValue -= Layout.getSymbolOffset(*A);
428226584Sdim    } else {
429226584Sdim      // The index is the section ordinal (1-based).
430288943Sdim      const MCSection &Sec = A->getSection();
431288943Sdim      Index = Sec.getOrdinal() + 1;
432288943Sdim      FixedValue += Writer->getSectionAddress(&Sec);
433226584Sdim    }
434226584Sdim    if (IsPCRel)
435226584Sdim      FixedValue -= Writer->getSectionAddress(Fragment->getParent());
436226584Sdim
437226584Sdim    // The type is determined by the fixup kind.
438226584Sdim    Type = RelocType;
439226584Sdim  }
440226584Sdim
441226584Sdim  // struct relocation_info (8 bytes)
442261991Sdim  MachO::any_relocation_info MRE;
443261991Sdim  MRE.r_word0 = FixupOffset;
444288943Sdim  MRE.r_word1 =
445288943Sdim      (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
446234353Sdim
447234353Sdim  // Even when it's not a scattered relocation, movw/movt always uses
448234353Sdim  // a PAIR relocation.
449261991Sdim  if (Type == MachO::ARM_RELOC_HALF) {
450239462Sdim    // The other-half value only gets populated for the movt and movw
451239462Sdim    // relocation entries.
452243830Sdim    uint32_t Value = 0;
453234353Sdim    switch ((unsigned)Fixup.getKind()) {
454234353Sdim    default: break;
455239462Sdim    case ARM::fixup_arm_movw_lo16:
456239462Sdim    case ARM::fixup_t2_movw_lo16:
457239462Sdim      Value = (FixedValue >> 16) & 0xffff;
458239462Sdim      break;
459234353Sdim    case ARM::fixup_arm_movt_hi16:
460234353Sdim    case ARM::fixup_t2_movt_hi16:
461239462Sdim      Value = FixedValue & 0xffff;
462234353Sdim      break;
463234353Sdim    }
464261991Sdim    MachO::any_relocation_info MREPair;
465261991Sdim    MREPair.r_word0 = Value;
466261991Sdim    MREPair.r_word1 = ((0xffffff              <<  0) |
467261991Sdim                       (Log2Size              << 25) |
468261991Sdim                       (MachO::ARM_RELOC_PAIR << 28));
469234353Sdim
470288943Sdim    Writer->addRelocation(nullptr, Fragment->getParent(), MREPair);
471234353Sdim  }
472234353Sdim
473288943Sdim  Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
474226584Sdim}
475226584Sdim
476288943SdimMCObjectWriter *llvm::createARMMachObjectWriter(raw_pwrite_stream &OS,
477288943Sdim                                                bool Is64Bit, uint32_t CPUType,
478226584Sdim                                                uint32_t CPUSubtype) {
479226584Sdim  return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit,
480226584Sdim                                                        CPUType,
481226584Sdim                                                        CPUSubtype),
482226584Sdim                                OS, /*IsLittleEndian=*/true);
483226584Sdim}
484