Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions docs/DeveloperDocs/ARM-Relocations.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ movt r0, #:upper16:symbol @ R_ARM_THM_MOVT_ABS
| `R_ARM_THM_MOVT_BREL` | `S + A - P` | `[31:16]` | none |
| `R_ARM_THM_MOVW_BREL_NC` | `((S + A) \| T) - B(S)` | `[15:0]` | none |
| `R_ARM_THM_MOVW_BREL` | `((S + A) \| T) - B(S)` | `[15:0]` | none |
| `R_ARM_ALU_PC_G0` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | none |
| `R_ARM_ALU_PC_G0` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | overflow checked |
| `R_ARM_ALU_PC_G0_NC` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | none (truncates) |
| `R_ARM_ALU_PC_G1` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | overflow checked |
| `R_ARM_ALU_PC_G1_NC` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | none (truncates) |
| `R_ARM_ALU_PC_G2` | `((S + A) \| T) - P` | top 8 bits, 4-bit rotation | overflow checked |
| `R_ARM_LDR_PC_G2` | `S + A - P` | imm12 (bits 11:0) | [0, 4095] |
| `R_ARM_LDR_PC_G0` | `S + A - P` | imm12 (bits 11:0) | [0, 4095] |

Expand Down Expand Up @@ -160,10 +164,6 @@ The table below lists every relocation that ELD's ARM backend maps to the `unsup
| 54 | `R_ARM_THM_PC12` | Thumb-2 LDR/STR 12-bit PC-relative | |
| 55 | `R_ARM_ABS32_NOI` | 32-bit absolute, no interworking bit | |
| 56 | `R_ARM_REL32_NOI` | 32-bit PC-relative, no interworking bit | |
| 57 | `R_ARM_ALU_PC_G0_NC` | Group reloc — ALU PC-relative G0, no overflow | Implement ALU_PC_G group |
| 59 | `R_ARM_ALU_PC_G1_NC` | Group reloc — ALU PC-relative G1, no overflow | Implement ALU_PC_G group |
| 60 | `R_ARM_ALU_PC_G1` | Group reloc — ALU PC-relative G1 | Implement ALU_PC_G group |
| 61 | `R_ARM_ALU_PC_G2` | Group reloc — ALU PC-relative G2 | Implement ALU_PC_G group |
| 62 | `R_ARM_LDR_PC_G1` | Group reloc — LDR PC-relative G1 | Implement LDR PC-group |
| 64 | `R_ARM_LDRS_PC_G0` | Group reloc — LDRD/STRD PC-relative G0 | Implement LDRS PC-group |
| 65 | `R_ARM_LDRS_PC_G1` | Group reloc — LDRD/STRD PC-relative G1 | Implement LDRS PC-group |
Expand Down Expand Up @@ -218,7 +218,6 @@ The following discrepancies or gaps were found when comparing this document agai
| `R_ARM_TLS_LE32` expression | Document shows `S + A + 2*WordSize + ...`; ABI defines it as `S + A - tp` (offset from thread pointer) | Fix expression in TLS table to `S + A - tp` |
| `R_ARM_GOT_BREL` bits column | Document shows `12`; ABI says the relocation places a 32-bit GOT-relative offset — the `12` refers to LDR's 12-bit immediate encoding, which is an instruction constraint, not the relocation size | Clarify as `32` with a note that the offset must fit in 12 bits |
| `R_ARM_SBREL32` | Documented as identical to `R_ARM_REL32`; ABI marks it as using the segment base `B(S)` rather than `P`, so the formula is `((S+A)\|T) - B(S)` not `-P` | Fix expression to `((S + A) \| T) - B(S)` |
| `R_ARM_ALU_PC_G0` (type 58) | Documented in this file and handled by ELD via the `alu_pc` handler; the G1/G2 variants and the `_NC` forms (57, 59-61) are unsupported — not noted in the PC-relative table | Add a note that only G0 is supported |
| Thumb branch ranges | `R_ARM_THM_CALL` and `R_ARM_THM_JUMP24` are shown with `±16 MB` range; ABI specifies the range depends on whether J1J2 encoding is available (±4 MB without it) | Add conditional range note matching the Thumb Branch table in the Veneers section |
| `R_ARM_TARGET2` | Handled by ELD (as `target2`) but not documented in any section of this file | Add `R_ARM_TARGET2` to the PC-relative or absolute table with a note that its behaviour (ABS32 or GOT-relative) is controlled by a linker option |
| Deprecated relocations | `R_ARM_PC24` and `R_ARM_PLT32` are listed in the Branch section without noting they are deprecated in favour of `R_ARM_CALL`/`R_ARM_JUMP24` | Add deprecation note |
Expand Down
12 changes: 10 additions & 2 deletions lib/Target/ARM/ARMRelocationFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@
DECL_ARM_APPLY_RELOC_FUNC(thm_jump8) \
DECL_ARM_APPLY_RELOC_FUNC(thm_jump11) \
DECL_ARM_APPLY_RELOC_FUNC(thm_jump19) \
DECL_ARM_APPLY_RELOC_FUNC(alu_pc) \
DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g0) \
DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g0_nc) \
DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g1) \
DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g1_nc) \
DECL_ARM_APPLY_RELOC_FUNC(alu_pc_g2) \
DECL_ARM_APPLY_RELOC_FUNC(ldr_pc_g2) \
DECL_ARM_APPLY_RELOC_FUNC(ldr_pc_g0) \
DECL_ARM_APPLY_RELOC_FUNC(relocAddPREL1) \
Expand Down Expand Up @@ -90,7 +94,11 @@
"R_ARM_THM_MOVW_PREL_NC") \
Func(llvm::ELF::R_ARM_THM_MOVT_PREL, thm_movt_prel, "R_ARM_THM_MOVT_PREL") \
Func(llvm::ELF::R_ARM_THM_JUMP19, thm_jump19, "R_ARM_THM_JUMP19") \
Func(llvm::ELF::R_ARM_ALU_PC_G0, alu_pc, "R_ARM_ALU_PC_G0") \
Func(llvm::ELF::R_ARM_ALU_PC_G0, alu_pc_g0, "R_ARM_ALU_PC_G0") \
Func(llvm::ELF::R_ARM_ALU_PC_G0_NC, alu_pc_g0_nc, "R_ARM_ALU_PC_G0_NC") \
Func(llvm::ELF::R_ARM_ALU_PC_G1, alu_pc_g1, "R_ARM_ALU_PC_G1") \
Func(llvm::ELF::R_ARM_ALU_PC_G1_NC, alu_pc_g1_nc, "R_ARM_ALU_PC_G1_NC") \
Func(llvm::ELF::R_ARM_ALU_PC_G2, alu_pc_g2, "R_ARM_ALU_PC_G2") \
Func(llvm::ELF::R_ARM_LDR_PC_G2, ldr_pc_g2, "R_ARM_LDR_PC_G2") \
Func(llvm::ELF::R_ARM_LDR_PC_G0, ldr_pc_g0, "R_ARM_LDR_PC_G0") \
Func(llvm::ELF::R_ARM_THM_MOVW_BREL_NC, thm_movw_brel, \
Expand Down
59 changes: 41 additions & 18 deletions lib/Target/ARM/ARMRelocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1287,9 +1287,12 @@ Relocator::Result thm_jump19(Relocation &pReloc, ARMRelocator &pParent) {
return Relocator::OK;
}

// R_ARM_ALU_PC_G0: ((S + A) | T) - P
Relocator::Result alu_pc(Relocation &pReloc, ARMRelocator &pParent) {
// perform static relocation
// R_ARM_ALU_PC_Gn / R_ARM_ALU_PC_Gn_NC: ((S + A) | T) - P
// Shared worker for the whole ALU_PC group family. pGroup selects which
// group's residual to encode and pCheck selects whether encoding failure is
// reported (false for the _NC variants, which silently truncate instead).
static Relocator::Result alu_pc_group(Relocation &pReloc, ARMRelocator &pParent,
unsigned pGroup, bool pCheck) {
Relocator::Address S = pParent.getSymValue(&pReloc);
Relocator::DWord T = getThumbBit(pParent, pReloc, /*IsJump*/ false);
Relocator::Address P = pReloc.place(pParent.module());
Expand Down Expand Up @@ -1318,27 +1321,47 @@ Relocator::Result alu_pc(Relocation &pReloc, ARMRelocator &pParent) {
Imm = -Imm;
}

if (X) {
// Find the current value bit length and the value K_n.
unsigned L = llvm::bit_width<uint32_t>(X);
unsigned K = (L < 8 ? 0 : L - 7) >> 1;
// Encode the shifted immediate.
I |= ((X >> (K * 2)) & 0xff) | ((16 - K) & 0xf) << 8;
// Mask off used bits, the residual will be needed for other groups.
X &= llvm::maskTrailingOnes<uint32_t>(K * 2);
// For higher groups, the above is repeated.
// If there is still residual, the value cannot be represented.
if (X) {
pReloc.issueUnencodableImmediate(pParent, Imm);
return Relocator::BadImm;
}
// R_ARM_ALU_PC_Gn encodes the group residual as a modified immediate
// (4-bit even rotate + 8-bit constant).
uint32_t Rem = helper_get_rem_for_group(pGroup, X);
unsigned LZ = llvm::countl_zero(Rem) & ~1u;
uint32_t RotImm = Rem;
uint32_t Rot = 0;
if (LZ < 24) {
RotImm = llvm::rotr<uint32_t>(Rem, 24 - LZ);
Rot = (LZ + 8) << 7;
}

if (pCheck && RotImm > 0xff) {
pReloc.issueUnencodableImmediate(pParent, Imm);
return Relocator::BadImm;
}

pReloc.target() = I;
pReloc.target() = I | Rot | (RotImm & 0xff);

return Relocator::OK;
}

Relocator::Result alu_pc_g0(Relocation &pReloc, ARMRelocator &pParent) {
return alu_pc_group(pReloc, pParent, /*pGroup=*/0, /*pCheck=*/true);
}

Relocator::Result alu_pc_g0_nc(Relocation &pReloc, ARMRelocator &pParent) {
return alu_pc_group(pReloc, pParent, /*pGroup=*/0, /*pCheck=*/false);
}

Relocator::Result alu_pc_g1(Relocation &pReloc, ARMRelocator &pParent) {
return alu_pc_group(pReloc, pParent, /*pGroup=*/1, /*pCheck=*/true);
}

Relocator::Result alu_pc_g1_nc(Relocation &pReloc, ARMRelocator &pParent) {
return alu_pc_group(pReloc, pParent, /*pGroup=*/1, /*pCheck=*/false);
}

Relocator::Result alu_pc_g2(Relocation &pReloc, ARMRelocator &pParent) {
return alu_pc_group(pReloc, pParent, /*pGroup=*/2, /*pCheck=*/true);
}

// R_ARM_PC24: ((S + A) | T) - P
// R_ARM_PLT32: ((S + A) | T) - P
// R_ARM_JUMP24: ((S + A) | T) - P
Expand Down
20 changes: 10 additions & 10 deletions test/ARM/FromLLD/arm-adr-err-long.s
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: llvm-mc --triple=armv7a-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %t/asm
// RUN: not %link --script %t/lds %t.o -o /dev/null 2>&1 | %filecheck %s

// FIXME: Only R_ARM_ALU_PC_G0 is enabled.
// FIXME: R_ARM_LDRS_PC_G2 is unsupported

//--- lds
SECTIONS {
Expand All @@ -28,29 +28,29 @@ _start:
.inst 0xe2400004 // sub r0, r0, #4
.reloc 0, R_ARM_ALU_PC_G0, dat1
// CHECK: Error: {{.*}}.o:(.text.1): unencodable immediate 7340040 for relocation 'R_ARM_ALU_PC_G0' referencing 'dat1
// FIXME .reloc 4, R_ARM_ALU_PC_G1, dat1
.reloc 4, R_ARM_ALU_PC_G1, dat1

.inst 0xe24f1008 // sub r1, pc, #8
.inst 0xe2411004 // sub r1, r1, #4
.inst 0xe2411000 // sub r1, r1, #0
// FIXME .reloc 8, R_ARM_ALU_PC_G0_NC, dat2
// FIXME .reloc 12, R_ARM_ALU_PC_G1, dat2
// FIXME: {{.*}}.s.tmp.o:(.text.1+0xc): unencodeable immediate 244252656 for relocation R_ARM_ALU_PC_G1
// FIXME .reloc 16, R_ARM_ALU_PC_G2, dat2
.reloc 8, R_ARM_ALU_PC_G0_NC, dat2
.reloc 12, R_ARM_ALU_PC_G1, dat2
// CHECK: Error: {{.*}}.o:(.text.1+0xc): unencodable immediate 244252656 for relocation 'R_ARM_ALU_PC_G1' referencing 'dat2'
.reloc 16, R_ARM_ALU_PC_G2, dat2

.inst 0xe24f0008 // sub r0, pc, #8
.inst 0xe2400004 // sub r0, r0, #4
.inst 0xe2400000 // sub r0, r0, #0
.reloc 20, R_ARM_ALU_PC_G0, dat1
// CHECK: Error: {{.*}}.o:(.text.1+0x14): unencodable immediate 7340060 for relocation 'R_ARM_ALU_PC_G0'
// FIXME .reloc 24, R_ARM_ALU_PC_G1, dat1
// FIXME .reloc 28, R_ARM_ALU_PC_G2, dat1
.reloc 24, R_ARM_ALU_PC_G1, dat1
.reloc 28, R_ARM_ALU_PC_G2, dat1

.inst 0xe24f0008 // sub r0, pc, #8
.inst 0xe2400004 // sub r0, r0, #4
.inst 0xe1c000d0 // ldrd r0, r1, [r0, #0]
// FIXME .reloc 32, R_ARM_ALU_PC_G0_NC, dat2
// FIXME .reloc 36, R_ARM_ALU_PC_G1_NC, dat2
.reloc 32, R_ARM_ALU_PC_G0_NC, dat2
.reloc 36, R_ARM_ALU_PC_G1_NC, dat2
// FIXME: {{.*}}.s.tmp.o:(.text.1+0x28): relocation R_ARM_LDRS_PC_G2 out of range: 4056 is not in [0, 255]; references dat2
// FIXME .reloc 40, R_ARM_LDRS_PC_G2, dat2

Expand Down
105 changes: 105 additions & 0 deletions test/ARM/FromLLD/arm-adr-long.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// REQUIRES: arm
// RUN: split-file %s %t
// RUN: %llvm-mc --triple=armv7a-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %t/asm
// RUN: %link --script %t/lds %t.o -o %t2
// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn --triple=armv7a-none-eabi %t2 | FileCheck %s

// FIXME: R_ARM_LDR_PC_G1 and R_ARM_LDRS_PC_G1 is unsupported

/// Test the long range encoding of R_ARM_ALU_PC_Gx sequences. We can encode an 8-bit
/// immediate rotated right by an even 4-bit field.

//--- lds
SECTIONS {
.text.0 0x0100000 : AT(0x0100000) { *(.text.0) }
.text.1 0x0800000 : AT(0x0800000) { *(.text.1) }
.text.2 0xf0f0000 : AT(0xf0f0000) { *(.text.2) }
}

//--- asm
.section .text.0, "ax", %progbits
dat1:
.word 0

.section .text.1, "ax", %progbits
.global _start
.type _start, %function
_start:
.inst 0xe24f0008 // sub r0, pc, #8
.inst 0xe2400004 // sub r0, r0, #4
.reloc 0, R_ARM_ALU_PC_G0_NC, dat1
.reloc 4, R_ARM_ALU_PC_G1, dat1

.inst 0xe24f1008 // sub r1, pc, #8
.inst 0xe2411004 // sub r1, r1, #4
.inst 0xe2411000 // sub r1, r1, #0
.reloc 8, R_ARM_ALU_PC_G0_NC, dat2
.reloc 12, R_ARM_ALU_PC_G1_NC, dat2
.reloc 16, R_ARM_ALU_PC_G2, dat2

.inst 0xe24f0008 // sub r0, pc, #8
.inst 0xe2400004 // sub r0, r0, #4
.inst 0xe2400000 // sub r0, r0, #0
.reloc 20, R_ARM_ALU_PC_G0_NC, dat1
.reloc 24, R_ARM_ALU_PC_G1_NC, dat1
.reloc 28, R_ARM_ALU_PC_G2, dat1

.inst 0xe24f0008 // sub r0, pc, #8
.inst 0xe2400004 // sub r0, r0, #4
.inst 0xe5900000 // ldr r0, [r0, #0]
.reloc 32, R_ARM_ALU_PC_G0_NC, dat2
.reloc 36, R_ARM_ALU_PC_G1_NC, dat2
.reloc 40, R_ARM_LDR_PC_G2, dat2

.inst 0xe24f0008 // sub r0, pc, #8
.inst 0xe5100004 // ldr r0, [r0, #-4]
.reloc 44, R_ARM_ALU_PC_G0_NC, dat1
// FIXME .reloc 48, R_ARM_LDR_PC_G1, dat1

.inst 0xe24f0008 // sub r0, pc, #8
.inst 0xe2400004 // sub r0, r0, #4
.inst 0xe5900000 // ldr r0, [r0, #0]
.reloc 52, R_ARM_ALU_PC_G0_NC, dat1
.reloc 56, R_ARM_ALU_PC_G1_NC, dat1
.reloc 60, R_ARM_LDR_PC_G2, dat1

.inst 0xe24f0008 // sub r0, pc, #8
.inst 0xe14000d4 // ldrd r0, [r0, #-4]
.reloc 64, R_ARM_ALU_PC_G0_NC, dat1
// FIXME .reloc 68, R_ARM_LDRS_PC_G1, dat1

.section .text.2, "ax", %progbits
dat2:
.word 0

// CHECK: 00100000 <dat1>:
// CHECK-NEXT: 100000: andeq r0, r0, r0

// CHECK: 00800000 <_start>:
// CHECK-NEXT: 800000: sub r0, pc, #112, #16
// CHECK-NEXT: 800004: sub r0, r0, #8

// CHECK-NEXT: 800008: add r1, pc, #232, #12
// CHECK-NEXT: 80000c: add r1, r1, #978944
// CHECK-NEXT: 800010: add r1, r1, #4080

// CHECK-NEXT: 800014: sub r0, pc, #112, #16
// CHECK-NEXT: 800018: sub r0, r0, #28
// CHECK-NEXT: 80001c: sub r0, r0, #0

// CHECK-NEXT: 800020: add r0, pc, #232, #12
// CHECK-NEXT: 800024: add r0, r0, #978944
// CHECK-NEXT: 800028: ldr r0, [r0, #4056]

// CHECK-NEXT: 80002c: sub r0, pc, #112, #16
// FIXME: 800030: ldr r0, [r0, #-52]

// CHECK: 800034: sub r0, pc, #112, #16
// CHECK-NEXT: 800038: sub r0, r0, #60
// CHECK-NEXT: 80003c: ldr r0, [r0, #-0]

// CHECK-NEXT: 800040: sub r0, pc, #112, #16
// FIXME: 800044: ldrd r0, r1, [r0, #-72]

// CHECK: 0f0f0000 <dat2>:
// CHECK-NEXT: f0f0000: andeq r0, r0, r0
13 changes: 13 additions & 0 deletions test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/1.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.arm

.section .text.1, "ax", %progbits
.space 0x28
.global _start
.type _start, %function
_start:
add r0, r0, #0
.reloc 0x28, R_ARM_ALU_PC_G0, dat2

.section .text.2, "ax", %progbits
dat2:
.word 0
4 changes: 4 additions & 0 deletions test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/overflow.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SECTIONS {
.text.1 0x0800000 : AT(0x0800000) { *(.text.1) }
.text.2 0x01700118 : AT(0x01700118) { *(.text.2) }
}
4 changes: 4 additions & 0 deletions test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/Inputs/valid.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SECTIONS {
.text.1 0x0800000 : AT(0x0800000) { *(.text.1) }
.text.2 0x01700028 : AT(0x01700028) { *(.text.2) }
}
19 changes: 19 additions & 0 deletions test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0/R_ARM_ALU_PC_G0.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#---R_ARM_ALU_PC_G0.test--------------------- Executable ----------------------#
#BEGIN_COMMENT
# This tests that R_ARM_ALU_PC_G0 patches the ADD immediate (rotate + imm8)
# field with the group-0 residual and reports overflow when that residual
# does not fit.
#END_COMMENT
#START_TEST
RUN: %clang %clangopts -c %p/Inputs/1.s -o %t1.1.o
RUN: %link %linkopts -march arm -T %p/Inputs/valid.t %t1.1.o -o %t2.out
RUN: %objdump -d --triple=armv7a-none-eabi %t2.out | %filecheck %s --check-prefix=VALID

RUN: %clang %clangopts -c %p/Inputs/1.s -o %t3.1.o
RUN: %not %link %linkopts -march arm -T %p/Inputs/overflow.t %t3.1.o -o %t4.out 2>&1 | %filecheck %s --check-prefix=OVERFLOW

#VALID: 00800028 <_start>:
#VALID-NEXT: 800028: e28008f0 add r0, r0, #240, #16

#OVERFLOW: Error: {{.*}}3.1.o:(.text.1+0x28): unencodable immediate 15728880 for relocation 'R_ARM_ALU_PC_G0' referencing 'dat2'
#END_TEST
13 changes: 13 additions & 0 deletions test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/1.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.arm

.section .text.1, "ax", %progbits
.space 0x28
.global _start
.type _start, %function
_start:
add r0, r0, #0
.reloc 0x28, R_ARM_ALU_PC_G0_NC, dat2

.section .text.2, "ax", %progbits
dat2:
.word 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SECTIONS {
.text.1 0x0800000 : AT(0x0800000) { *(.text.1) }
.text.2 0x01700118 : AT(0x01700118) { *(.text.2) }
}
4 changes: 4 additions & 0 deletions test/ARM/standalone/Relocs/R_ARM_ALU_PC_G0_NC/Inputs/valid.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SECTIONS {
.text.1 0x0800000 : AT(0x0800000) { *(.text.1) }
.text.2 0x01700118 : AT(0x01700118) { *(.text.2) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#---R_ARM_ALU_PC_G0_NC.test--------------------- Executable --------------------#
#BEGIN_COMMENT
# This tests that R_ARM_ALU_PC_G0_NC patches the ADD immediate (rotate + imm8)
# field with the group-0 residual and silently truncates a group-0 residual
# that does not fit the modified-immediate field instead of reporting an
# unencodable-immediate error.
#END_COMMENT
#START_TEST
RUN: %clang %clangopts -c %p/Inputs/1.s -o %t1.1.o
RUN: %link %linkopts -march arm -T %p/Inputs/valid.t %t1.1.o -o %t2.out
RUN: %objdump -d --triple=armv7a-none-eabi %t2.out | %filecheck %s --check-prefix=VALID

RUN: %clang %clangopts -c %p/Inputs/1.s -o %t3.1.o
RUN: %link %linkopts -march arm -T %p/Inputs/overflow.t %t3.1.o -o %t4.out 2>&1 | %filecheck %s --check-prefix=NOERROR --allow-empty
RUN: %objdump -d --triple=armv7a-none-eabi %t4.out | %filecheck %s --check-prefix=TRUNC

#VALID: 00800028 <_start>:
#VALID-NEXT: 800028: e28008f0 add r0, r0, #240, #16

#NOERROR-NOT: unencodable immediate

#TRUNC: 00800028 <_start>:
#TRUNC-NEXT: 800028: e28008f0 add r0, r0, #240, #16
#END_TEST
13 changes: 13 additions & 0 deletions test/ARM/standalone/Relocs/R_ARM_ALU_PC_G1/Inputs/1.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.arm

.section .text.1, "ax", %progbits
.space 0x28
.global _start
.type _start, %function
_start:
add r0, r0, #0
.reloc 0x28, R_ARM_ALU_PC_G1, dat2

.section .text.2, "ax", %progbits
dat2:
.word 0
Loading
Loading