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