summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp9
-rw-r--r--llvm/test/MC/ARM/macho-movwt.s66
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 -
OpenPOWER on IntegriCloud