156 changes: 156 additions & 0 deletions lld/test/ELF/arm-thumb2-adr.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// RUN: llvm-mc --triple=thumbv7m-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %s
// RUN: echo "SECTIONS { \
// RUN: .rodata.low 0x8012 : { *(.rodata.low) } \
// RUN: .text.low 0x8f00 : { *(.text.low) } \
// RUN: .text.neg 0x9000 : { *(.text.neg) } \
// RUN: .text.pos 0x10000 : { *(.text.pos) } \
// RUN: .text.high 0x10100 : { *(.text.high) } \
// RUN: .data_high 0x1100f : { *(.data.high) } \
// RUN: } " > %t.script
// RUN: ld.lld --script %t.script %t.o -o %t
// RUN: llvm-readobj --symbols %t | FileCheck %s --check-prefix=SYMS
// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7m-none-eabi %t
// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7m-none-eabi %t | FileCheck %s

/// Test the various legal cases for the R_ARM_THM_ALU_PREL_11_0 relocation
/// Interesting things to note
/// Range is +- 4095 bytes
/// The expression is S + A - Pa where Pa is AlignDown(PC, 4) so we will use
/// 2-byte nops to make some of the adr psuedo instructions 2-byte aligned.
.section .rodata.low, "a", %progbits
dat1:
.byte 0
dat2:
.byte 1
dat3:
.byte 2
dat4:
.byte 3

.section .text.low, "ax", %progbits
.balign 4
.global target1
.type target1, %function
target1:
bx lr
.type target2, %function
target2:
bx lr

.section .text.neg, "ax", %progbits
.balign 4
.global _start
.thumb_func
_start:
nop
adr.w r0, dat1
adr.w r1, dat2
nop
adr.w r2, dat3
adr.w r3, dat4
.balign 4
adr.w r0, target1
nop
adr.w r1, target2

.section .text.pos, "ax", %progbits
.balign 4
.global pos
.thumb_func
pos:
adr.w r2, target3
nop
adr.w r3, target4
.balign 4
adr.w r0, dat5
adr.w r1, dat6
nop
adr.w r2, dat7
adr.w r3, dat8
/// positive addend in instruction, all others are -4 (PC bias)
adr.w r4, dat5 + 8

.section .text.high, "ax", %progbits
.balign 4
.thumb_func
.global target3
target3:
bx lr
.thumb_func
target4:
bx lr

.section .data.high, "aw", %progbits
dat5:
.byte 0
dat6:
.byte 1
dat7:
.byte 2
dat8:
.byte 3

// SYMS: Name: dat1
// SYMS-NEXT: Value: 0x8012
// SYMS: Name: dat2
// SYMS-NEXT: Value: 0x8013
// SYMS: Name: dat3
// SYMS-NEXT: Value: 0x8014
// SYMS: Name: dat4
// SYMS-NEXT: Value: 0x8015

// CHECK: 00008f00 target1:
// CHECK-NEXT: 8f00: bx lr
// CHECK: 00008f02 target2:
// CHECK-NEXT: 8f02: bx lr

// CHECK: 00009000 _start:
// CHECK-NEXT: 9000: nop
/// AlignDown(0x9002+4, 4) - 0xff2 = 0x8012
// CHECK-NEXT: 9002: adr.w r0, #-4082
/// AlignDown(0x9006+4, 4) - 0xff5 = 0x8013
// CHECK-NEXT: 9006: adr.w r1, #-4085
// CHECK-NEXT: 900a: nop
/// AlignDown(0x900c+4, 4) - 0xffc = 0x8014
// CHECK-NEXT: 900c: adr.w r2, #-4092
/// AlignDown(0x9010+4, 4) - 0xfff = 0x8015
// CHECK-NEXT: 9010: adr.w r3, #-4095
/// AlignDown(0x9014+4, 4) - 0x117 = 0x8f01
// CHECK-NEXT: 9014: adr.w r0, #-279
// CHECK-NEXT: 9018: nop
/// AlignDown(0x901a+4, 4) - 0x119 = 0x8f03
// CHECK-NEXT: 901a: adr.w r1, #-281

// CHECK: 00010000 pos:
/// AlignDown(0x10000+4, 4) + 0xfd = 0x10101
// CHECK-NEXT: 10000: adr.w r2, #253
// CHECK-NEXT: 10004: nop
/// AlignDown(0x10006+4, 4) + 0xfb = 0x10103
// CHECK-NEXT: 10006: adr.w r3, #251
// CHECK-NEXT: 1000a: nop
/// AlignDown(0x1000c+4, 4) + 0xfff = 0x1100f
// CHECK-NEXT: 1000c: adr.w r0, #4095
/// AlignDown(0x10010+4, 4) + 0xffc = 0x11010
// CHECK-NEXT: 10010: adr.w r1, #4092
// CHECK-NEXT: 10014: nop
/// AlignDown(0x10016+4, 4) + 0xff9 = 0x11011
// CHECK-NEXT: 10016: adr.w r2, #4089
/// AlignDown(0x1001a+4, 4) + 0xff6 = 0x11012
// CHECK-NEXT: 1001a: adr.w r3, #4086
/// AlignDown(0x1001e+4, 4) + 0xff7 = 0x11017 = dat5 + 8
// CHECK-NEXT: 1001e: adr.w r4, #4087

// CHECK: 00010100 target3:
// CHECK-NEXT: 10100: bx lr

// CHECK: 00010102 target4:
// CHECK-NEXT: 10102: bx lr

// SYMS: Name: dat5
// SYMS-NEXT: Value: 0x1100F
// SYMS: Name: dat6
// SYMS-NEXT: Value: 0x11010
// SYMS: Name: dat7
// SYMS-NEXT: Value: 0x11011
// SYMS: Name: dat8
// SYMS-NEXT: Value: 0x11012
25 changes: 25 additions & 0 deletions lld/test/ELF/arm-thumb2-ldrlit-err.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: llvm-mc -g --triple=thumbv7m-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %s
// RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s

.section .text.0, "ax", %progbits
.thumb_func
.balign 4
low:
bx lr
nop
nop

.section .text.1, "ax", %progbits
.global _start
.thumb_func
_start:
// CHECK: {{.*}}.s:[[# @LINE+1]]:(.text.1+0x0): relocation R_ARM_THM_PC12 out of range: 4098 is not in [0, 4095]
ldr.w r0, low - 4091
// CHECK: {{.*}}.s:[[# @LINE+1]]:(.text.1+0x4): relocation R_ARM_THM_PC12 out of range: 4096 is not in [0, 4095]
ldr.w r0, high + 4091

.section .text.2
.thumb_func
.balign 4
high:
bx lr
156 changes: 156 additions & 0 deletions lld/test/ELF/arm-thumb2-ldrlit.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// RUN: llvm-mc --triple=thumbv7m-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %s
// RUN: echo "SECTIONS { \
// RUN: .rodata.low 0x8012 : { *(.rodata.low) } \
// RUN: .text.low 0x8f00 : { *(.text.low) } \
// RUN: .text.neg 0x9000 : { *(.text.neg) } \
// RUN: .text.pos 0x10000 : { *(.text.pos) } \
// RUN: .text.high 0x10100 : { *(.text.high) } \
// RUN: .data_high 0x1100f : { *(.data.high) } \
// RUN: } " > %t.script
// RUN: ld.lld --script %t.script %t.o -o %t
// RUN: llvm-readobj --symbols %t | FileCheck %s --check-prefix=SYMS
// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7m-none-eabi %t | FileCheck %s

/// Test the various legal cases for the R_ARM_THM_PC12 relocation
/// Interesting things to note
/// Range is +- 4095 bytes
/// The Thumb bit for function symbols is ignored
/// The expression is S + A - Pa where Pa is AlignDown(PC, 4) so we will use
/// 2-byte nops to make some of the ldr instructions 2-byte aligned.
.section .rodata.low, "a", %progbits
dat1:
.byte 0
dat2:
.byte 1
dat3:
.byte 2
dat4:
.byte 3

.section .text.low, "ax", %progbits
.balign 4
.global target1
.type target1, %function
target1:
bx lr
.type target2, %function
target2:
bx lr

.section .text.neg, "ax", %progbits
.balign 4
.global _start
.thumb_func
_start:
nop
ldr r0, dat1
ldr r1, dat2
nop
ldr r2, dat3
ldr r3, dat4
.balign 4
ldr r0, target1
nop
ldr r1, target2

.section .text.pos, "ax", %progbits
.balign 4
.global pos
.thumb_func
pos:
ldr r2, target3
nop
ldr r3, target4
.balign 4
ldr r0, dat5
ldr r1, dat6
nop
ldr r2, dat7
ldr r3, dat8
/// positive addend in instruction, all others are -4 (PC bias)
ldr.w r4, dat5 + 8

.section .text.high, "ax", %progbits
.balign 4
.thumb_func
.global target3
target3:
bx lr
.thumb_func
target4:
bx lr

.section .data.high, "aw", %progbits
dat5:
.byte 0
dat6:
.byte 1
dat7:
.byte 2
dat8:
.byte 3

// SYMS: Name: dat1
// SYMS-NEXT: Value: 0x8012
// SYMS: Name: dat2
// SYMS-NEXT: Value: 0x8013
// SYMS: Name: dat3
// SYMS-NEXT: Value: 0x8014
// SYMS: Name: dat4
// SYMS-NEXT: Value: 0x8015

// CHECK: 00008f00 target1:
// CHECK-NEXT: 8f00: bx lr
// CHECK: 00008f02 target2:
// CHECK-NEXT: 8f02: bx lr

// CHECK: 00009000 _start:
// CHECK-NEXT: 9000: nop
/// AlignDown(0x9002+4, 4) - 0xff2 = 0x8012
// CHECK-NEXT: 9002: ldr.w r0, [pc, #-4082]
/// AlignDown(0x9006+4, 4) - 0xff5 = 0x8013
// CHECK-NEXT: 9006: ldr.w r1, [pc, #-4085]
// CHECK-NEXT: 900a: nop
/// AlignDown(0x900c+4, 4) - 0xffc = 0x8014
// CHECK-NEXT: 900c: ldr.w r2, [pc, #-4092]
/// AlignDown(0x9010+4, 4) - 0xfff = 0x8015
// CHECK-NEXT: 9010: ldr.w r3, [pc, #-4095]
/// AlignDown(0x9014+4, 4) - 0x118 = 0x8f00
// CHECK-NEXT: 9014: ldr.w r0, [pc, #-280]
// CHECK-NEXT: 9018: nop
/// AlignDown(0x901a+4, 4) - 0x11a = 0x8f02
// CHECK-NEXT: 901a: ldr.w r1, [pc, #-282]

// CHECK: 00010000 pos:
/// AlignDown(0x10000+4, 4) + 0x1c = 0x10100
// CHECK-NEXT: 10000: ldr.w r2, [pc, #252]
// CHECK-NEXT: 10004: nop
/// AlignDown(0x10006+4, 4) + 0x1a = 0x10122
// CHECK-NEXT: 10006: ldr.w r3, [pc, #250]
// CHECK-NEXT: 1000a: nop
/// AlignDown(0x1000c+4, 4) + 0xfff = 0x1100f
// CHECK-NEXT: 1000c: ldr.w r0, [pc, #4095]
/// AlignDown(0x10010+4, 4) + 0xffc = 0x11010
// CHECK-NEXT: 10010: ldr.w r1, [pc, #4092]
// CHECK-NEXT: 10014: nop
/// AlignDown(0x10016+4, 4) + 0xff9 = 0x11011
// CHECK-NEXT: 10016: ldr.w r2, [pc, #4089]
/// AlignDown(0x1001a+4, 4) + 0xff6 = 0x11012
// CHECK-NEXT: 1001a: ldr.w r3, [pc, #4086]
/// AlignDown(0x1001e+4, 4) + 0xff7 = 0x11017 = dat5 + 8
// CHECK-NEXT: 1001e: ldr.w r4, [pc, #4087]

// CHECK: 00010100 target3:
// CHECK-NEXT: 10100: bx lr

// CHECK: 00010102 target4:
// CHECK-NEXT: 10102: bx lr

// SYMS: Name: dat5
// SYMS-NEXT: Value: 0x1100F
// SYMS: Name: dat6
// SYMS-NEXT: Value: 0x11010
// SYMS: Name: dat7
// SYMS-NEXT: Value: 0x11011
// SYMS: Name: dat8
// SYMS-NEXT: Value: 0x11012
12 changes: 7 additions & 5 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
// Name Offset (bits) Size (bits) Flags
{"fixup_arm_ldst_pcrel_12", 0, 32, IsPCRelConstant},
{"fixup_t2_ldst_pcrel_12", 0, 32,
IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
MCFixupKindInfo::FKF_IsPCRel |
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
{"fixup_arm_pcrel_10_unscaled", 0, 32, IsPCRelConstant},
{"fixup_arm_pcrel_10", 0, 32, IsPCRelConstant},
{"fixup_t2_pcrel_10", 0, 32,
Expand All @@ -74,10 +75,12 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_t2_pcrel_9", 0, 32,
IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
{"fixup_thumb_adr_pcrel_10", 0, 8,
IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
MCFixupKindInfo::FKF_IsPCRel |
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
{"fixup_arm_adr_pcrel_12", 0, 32, IsPCRelConstant},
{"fixup_t2_adr_pcrel_12", 0, 32,
IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
MCFixupKindInfo::FKF_IsPCRel |
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
{"fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
Expand Down Expand Up @@ -109,8 +112,7 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_bfc_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_bfcsel_else_target", 0, 32, 0},
{"fixup_wls", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}
};
{"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}};
const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = {
// This table *must* be in the order that the fixup_* kinds are defined in
// ARMFixupKinds.h.
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
default:
return ELF::R_ARM_THM_CALL;
}
case ARM::fixup_thumb_adr_pcrel_10:
case ARM::fixup_arm_thumb_cp:
return ELF::R_ARM_THM_PC8;
case ARM::fixup_t2_adr_pcrel_12:
return ELF::R_ARM_THM_ALU_PREL_11_0;
case ARM::fixup_t2_ldst_pcrel_12:
return ELF::R_ARM_THM_PC12;
case ARM::fixup_bf_target:
return ELF::R_ARM_THM_BF16;
case ARM::fixup_bfc_target:
Expand Down
18 changes: 18 additions & 0 deletions llvm/test/MC/ARM/pcrel-global-rel.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@ RUN: llvm-mc -filetype=obj -triple=armv7 %s -o %t
@ RUN: llvm-readobj -r %t

@ Check that for ELF targets we generate a relocation for a within section
@ pc-relative reference to a global symbol as it may be interposed and we won't
@ know till link time whether this is possible.
.thumb
.thumb_func

.globl bar
bar:
adr r0, bar @ thumb_adr_pcrel_10
adr.w r0, bar @ t2_adr_pcrel_12
ldr.w pc, bar @ t2_ldst_pcrel_12

@ CHECK: 0x0 R_ARM_THM_ALU_PREL_11_0 bar 0x0
@ CHECK-NEXT: 0x4 R_ARM_THM_ALU_PREL_11_0 bar 0x0
@ CHECK-NEXT: 0x8 R_ARM_THM_PC12 bar 0x0
8 changes: 0 additions & 8 deletions llvm/test/MC/ARM/pcrel-global.s
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,3 @@ vldr d0, foo @ arm_pcrel_10
adr r2, foo @ arm_adr_pcrel_12
ldr r0, foo @ arm_ldst_pcrel_12

.thumb
.thumb_func

.globl bar
bar:
adr r0, bar @ thumb_adr_pcrel_10
adr.w r0, bar @ t2_adr_pcrel_12
ldr.w pc, bar @ t2_ldst_pcrel_12
6 changes: 4 additions & 2 deletions llvm/test/MC/ARM/thumb1-relax-adr.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
@ RUN: not llvm-mc -triple thumbv7m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
@ RUN: not llvm-mc -triple thumbv7m-none-eabi -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
@ RUN: llvm-mc -triple thumbv6m-none-eabi -filetype=obj %s -o - | llvm-readobj --relocs | FileCheck --check-prefix=CHECK-ELF-T1 %s
@ RUN: llvm-mc -triple thumbv7m-none-eabi -filetype=obj %s -o - | llvm-readobj --relocs | FileCheck --check-prefix=CHECK-ELF-T2 %s

.global func1
_func1:
adr r0, _func2
@ CHECK-ERROR: unsupported relocation on symbol

@ CHECK-ELF-T1: 0x0 R_ARM_THM_PC8 _func2 0x0
@ CHECK-ELF-T2: 0x0 R_ARM_THM_ALU_PREL_11_0 _func2 0x0
6 changes: 4 additions & 2 deletions llvm/test/MC/ARM/thumb1-relax-ldrlit.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
@ RUN: not llvm-mc -triple thumbv6m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
@ RUN: not llvm-mc -triple thumbv7m-none-macho -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
@ RUN: not llvm-mc -triple thumbv7m-none-eabi -filetype=obj -o /dev/null %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
@ RUN: llvm-mc -triple thumbv6m-none-eabi -filetype=obj %s -o - | llvm-readobj --relocs | FileCheck --check-prefix=CHECK-ELF-T1 %s
@ RUN: llvm-mc -triple thumbv7m-none-eabi -filetype=obj %s -o - | llvm-readobj --relocs | FileCheck --check-prefix=CHECK-ELF-T2 %s

.global func1
_func1:
ldr r0, _func2
@ CHECK-ERROR: unsupported relocation on symbol

@ CHECK-ELF-T1: 0x0 R_ARM_THM_PC8 _func2 0x0
@ CHECK-ELF-T2: 0x0 R_ARM_THM_PC12 _func2 0x0