diff options
| -rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp | 9 | ||||
| -rw-r--r-- | llvm/test/MC/ARM/macho-movwt.s | 66 |
2 files changed, 72 insertions, 3 deletions
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp index cfd504e533a..cfa6ce7da65 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp @@ -389,7 +389,8 @@ void ARMMachObjectWriter::recordRelocation(MachObjectWriter *Writer, uint32_t Offset = Target.getConstant(); if (IsPCRel && RelocType == MachO::ARM_RELOC_VANILLA) Offset += 1 << Log2Size; - if (Offset && A && !Writer->doesSymbolRequireExternRelocation(*A)) + if (Offset && A && !Writer->doesSymbolRequireExternRelocation(*A) && + RelocType != MachO::ARM_RELOC_HALF) return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, RelocType, Log2Size, FixedValue); @@ -447,8 +448,10 @@ void ARMMachObjectWriter::recordRelocation(MachObjectWriter *Writer, // Even when it's not a scattered relocation, movw/movt always uses // a PAIR relocation. if (Type == MachO::ARM_RELOC_HALF) { - // The other-half value only gets populated for the movt and movw - // relocation entries. + // The entire addend is needed to correctly apply a relocation. One half is + // extracted from the instruction itself, the other comes from this + // PAIR. I.e. it's correct that we insert the high bits of the addend in the + // MOVW case here. relocation entries. uint32_t Value = 0; switch ((unsigned)Fixup.getKind()) { default: break; diff --git a/llvm/test/MC/ARM/macho-movwt.s b/llvm/test/MC/ARM/macho-movwt.s new file mode 100644 index 00000000000..6f067cd86dc --- /dev/null +++ b/llvm/test/MC/ARM/macho-movwt.s @@ -0,0 +1,66 @@ +@ RUN: llvm-mc -triple thumbv7s-apple-ios9.0 %s -filetype obj -o %t.o +@ RUN: llvm-readobj -r %t.o | FileCheck %s + + .thumb + movw r0, :lower16:_x + movt r0, :upper16:_x + + movw r0, :lower16:_x+4 + movt r0, :upper16:_x+4 + + movw r0, :lower16:_x+0x10000 + movt r0, :upper16:_x+0x10000 + + .arm + movw r0, :lower16:_x + movt r0, :upper16:_x + + movw r0, :lower16:_x+4 + movt r0, :upper16:_x+4 + + movw r0, :lower16:_x+0x10000 + movt r0, :upper16:_x+0x10000 + +@ Enter the bizarre world of MachO relocations. First, they're in reverse order +@ to the actual instructions + +@ First column on the second line is the "other half" of the addend, its partner +@ being in the instruction itself. + +@ Third column identifies ARM/Thumb & HI/LO. + +@ CHECK: 0x2C 0 1 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x0 0 1 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x28 0 0 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x1 0 0 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x24 0 1 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x4 0 1 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x20 0 0 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x0 0 0 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x1C 0 1 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x0 0 1 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x18 0 0 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x0 0 0 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x14 0 3 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x0 0 3 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x10 0 2 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x1 0 2 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0xC 0 3 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x4 0 3 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x8 0 2 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x0 0 2 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x4 0 3 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x0 0 3 0 ARM_RELOC_PAIR 0 - + +@ CHECK: 0x0 0 2 1 ARM_RELOC_HALF 0 _x +@ CHECK: 0x0 0 2 0 ARM_RELOC_PAIR 0 - |

