From d04434959746b346914c5a801f24fecd4cbbaa7d Mon Sep 17 00:00:00 2001 From: Eleanor Bonnici Date: Wed, 29 Nov 2023 16:24:52 +0000 Subject: [PATCH 1/2] [llvm][MC][ARM][Assembly] Emit relocations for ADRs and big-endian targets Follow-up on https://github.com/llvm/llvm-project/pull/72873/ When ADR/LDR instructions reference a label in a different section, the offset is not known until link time, however, the assembler assumes it can resolve them in some cases. The previous patch addressed the issue for most LDR instructions, focusing on little-endian targets. This patch addresses the remaining work for ADRs and big-endian targets. --- .../Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 15 ++++++----- .../ARM/MCTargetDesc/ARMELFObjectWriter.cpp | 6 +++++ llvm/test/MC/ARM/pcrel-adr16-relocs.s | 23 +++++++++++++++++ llvm/test/MC/ARM/pcrel-adr32-relocs.s | 25 +++++++++++++++++++ llvm/test/MC/ARM/pcrel-arm-ldr-imm8-relocs.s | 6 +++++ llvm/test/MC/ARM/pcrel-global.s | 10 ++------ llvm/test/MC/ARM/pcrel-ldr-relocs.s | 8 ++++-- llvm/test/MC/ARM/pcrel-thumb-ldr2-relocs.s | 3 +++ llvm/test/MC/ARM/thumb1-relax-adr.s | 1 - 9 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 llvm/test/MC/ARM/pcrel-adr16-relocs.s create mode 100644 llvm/test/MC/ARM/pcrel-adr32-relocs.s diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index ca3b77e4a3565..41b3c6005231e 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -88,10 +88,12 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, {"fixup_arm_ldst_abs_12", 0, 32, 0}, {"fixup_thumb_adr_pcrel_10", 0, 8, - IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, - {"fixup_arm_adr_pcrel_12", 0, 32, IsPCRelConstant}, + MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, + {"fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, {"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}, @@ -133,10 +135,11 @@ const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { // ARMFixupKinds.h. // // Name Offset (bits) Size (bits) Flags - {"fixup_arm_ldst_pcrel_12", 0, 32, IsPCRelConstant}, + {"fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, {"fixup_t2_ldst_pcrel_12", 0, 32, - IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, - {"fixup_arm_pcrel_10_unscaled", 0, 32, IsPCRelConstant}, + MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, + {"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, {"fixup_arm_pcrel_10", 0, 32, IsPCRelConstant}, {"fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp index 985097fc32810..44695a86c4e36 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -164,6 +164,12 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, return ELF::R_ARM_LDRS_PC_G0; case ARM::fixup_t2_ldst_pcrel_12: return ELF::R_ARM_THM_PC12; + case ARM::fixup_arm_adr_pcrel_12: + return ELF::R_ARM_ALU_PC_G0; + case ARM::fixup_thumb_adr_pcrel_10: + 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_bf_target: return ELF::R_ARM_THM_BF16; case ARM::fixup_bfc_target: diff --git a/llvm/test/MC/ARM/pcrel-adr16-relocs.s b/llvm/test/MC/ARM/pcrel-adr16-relocs.s new file mode 100644 index 0000000000000..dd73c9d28a682 --- /dev/null +++ b/llvm/test/MC/ARM/pcrel-adr16-relocs.s @@ -0,0 +1,23 @@ +@ RUN: llvm-mc -filetype=obj --triple=thumbv6m-none-eabi %s -o %t +@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=RELOC +@ RUN: llvm-objdump -d --triple=thumbv6m-none-eabi %t | FileCheck %s --check-prefix=ADDEND + + .section .text._func1, "ax" + + .balign 4 + .global _func1 + .type _func1, %function +_func1: + adr r0, _func2 +@ RELOC: R_ARM_THM_PC8 + bx lr + +// Checking the encoding only, as the disassembly is not quite correct here. + +// Thumb16 encoding supports only adding of the encoded immediate (not +// subtracting, see [Arm ARM]), therefore sign change is required if the pcrel +// offset is negative. This makes the calculation of the addend for +// R_ARM_THM_PC8 more complex, for details see [ELF for the Arm 32-bit +// architecture]. +@ ADDEND: a0ff + diff --git a/llvm/test/MC/ARM/pcrel-adr32-relocs.s b/llvm/test/MC/ARM/pcrel-adr32-relocs.s new file mode 100644 index 0000000000000..015a4d79ccf68 --- /dev/null +++ b/llvm/test/MC/ARM/pcrel-adr32-relocs.s @@ -0,0 +1,25 @@ +@ RUN: llvm-mc -filetype=obj -triple=armv7 %s -o %t +@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=RELOC +@ RUN: llvm-objdump -d --triple=armv7 %t | FileCheck %s --check-prefix=ADDEND + +@ RUN: llvm-mc -filetype=obj --triple=armebv7-unknown-unknown %s -o %t +@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=RELOC +@ RUN: llvm-objdump -d --triple=armebv7-unknown-unknown %t | FileCheck %s --check-prefix=ADDEND + + .section .text._func1, "ax" + + .balign 4 + .global _func1 + .type _func1, %function +_func1: + adr r0, _func2 +@ RELOC: R_ARM_ALU_PC_G0 + .thumb + adr r0, _func2 +@ RELOC: R_ARM_THM_ALU_PREL_11_0 + bx lr + +@ ADDEND: sub r0, pc, #8 +@ ADDEND-NEXT: adr.w r0, #-4 + + diff --git a/llvm/test/MC/ARM/pcrel-arm-ldr-imm8-relocs.s b/llvm/test/MC/ARM/pcrel-arm-ldr-imm8-relocs.s index 40453d6ef341a..f8b166d4c2485 100644 --- a/llvm/test/MC/ARM/pcrel-arm-ldr-imm8-relocs.s +++ b/llvm/test/MC/ARM/pcrel-arm-ldr-imm8-relocs.s @@ -1,6 +1,9 @@ @ RUN: llvm-mc -filetype=obj -triple=armv7 %s -o %t @ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=ARM @ RUN: llvm-objdump -d --triple=armv7 %t | FileCheck %s --check-prefix=ARM_ADDEND +@ RUN: llvm-mc -filetype=obj --triple=armebv7-unknown-unknown %s -o %t +@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=ARM +@ RUN: llvm-objdump -d --triple=armebv7-unknown-unknown %t | FileCheck %s --check-prefix=ARM_ADDEND @ ARM: R_ARM_LDRS_PC_G0 @ ARM: R_ARM_LDRS_PC_G0 @@ -8,6 +11,7 @@ @ ARM: R_ARM_LDRS_PC_G0 @ ARM: R_ARM_LDRS_PC_G0 @ ARM: R_ARM_LDRS_PC_G0 +@ ARM: R_ARM_LDRS_PC_G0 // The value format is decimal in these specific cases, but it's hex for other // ldr instructions. These checks are valid for both formats. @@ -18,6 +22,7 @@ @ ARM_ADDEND: r0, [pc, #-{{16|0x10}}] @ ARM_ADDEND: r0, [pc, #-{{16|0x10}}] @ ARM_ADDEND: r0, [pc] +@ ARM_ADDEND: r0, r1, [pc] .arm .section .text.bar, "ax" @@ -31,6 +36,7 @@ bar: ldrh r0, just_after-8 ldrsb r0, just_after-8 ldrsh r0, foo+8 + ldrd r0,r1, foo+8 bx lr .section .data.foo, "a", %progbits diff --git a/llvm/test/MC/ARM/pcrel-global.s b/llvm/test/MC/ARM/pcrel-global.s index 15d46cf2063ec..1e9e6e989356e 100644 --- a/llvm/test/MC/ARM/pcrel-global.s +++ b/llvm/test/MC/ARM/pcrel-global.s @@ -7,11 +7,9 @@ @ CHECK: There are no relocations in this file. @ DISASM-LABEL: : -@ DISASM-NEXT: adr.w r0, #-4 -@ DISASM-NEXT: adr.w r0, #-8 -@ DISASM-NEXT: ldr r0, [pc, #0x0] @ 0x14 +@ DISASM-NEXT: ldr r0, [pc, #0x0] @ 0x8 @ DISASM-NEXT: add r0, pc -@ DISASM-NEXT: .word 0xfffffff3 +@ DISASM-NEXT: .word 0xfffffffb @@ GNU assembler creates an R_ARM_REL32 referencing bar. @ DISASM-NOT: {{.}} @@ -20,16 +18,12 @@ .globl foo foo: vldr d0, foo @ arm_pcrel_10 -adr r2, foo @ arm_adr_pcrel_12 .thumb .thumb_func .type bar, %function .globl bar bar: -adr r0, bar @ thumb_adr_pcrel_10 -adr.w r0, bar @ t2_adr_pcrel_12 - ldr r0, .LCPI .LPC0_1: add r0, pc diff --git a/llvm/test/MC/ARM/pcrel-ldr-relocs.s b/llvm/test/MC/ARM/pcrel-ldr-relocs.s index 120d54ebafe08..e0f27f2994999 100644 --- a/llvm/test/MC/ARM/pcrel-ldr-relocs.s +++ b/llvm/test/MC/ARM/pcrel-ldr-relocs.s @@ -4,12 +4,17 @@ @ RUN: llvm-mc -filetype=obj -triple=thumbv7 %s -o %t @ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=THUMB @ RUN: llvm-objdump -d --triple=thumbv7 %t | FileCheck %s --check-prefix=THUMB_ADDEND +@ RUN: llvm-mc -filetype=obj -triple=armebv7 %s -o %t +@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=ARM +@ RUN: llvm-objdump -d --triple=armebv7 %t | FileCheck %s --check-prefix=ARM_ADDEND +@ RUN: llvm-mc -filetype=obj -triple=thumbebv7 %s -o %t +@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=THUMB +@ RUN: llvm-objdump -d --triple=thumbebv7 %t | FileCheck %s --check-prefix=THUMB_ADDEND @ ARM: R_ARM_LDR_PC_G0 @ ARM: R_ARM_LDR_PC_G0 @ ARM: R_ARM_LDR_PC_G0 @ ARM: R_ARM_LDR_PC_G0 - @ ARM_ADDEND: r0, [pc, #-0x8] @ ARM_ADDEND: r0, [pc, #-0x8] @ ARM_ADDEND: r0, [pc, #-0x10] @@ -19,7 +24,6 @@ @ THUMB: R_ARM_THM_PC12 @ THUMB: R_ARM_THM_PC12 @ THUMB: R_ARM_THM_PC12 - @ THUMB_ADDEND: r0, [pc, #-0x4] @ THUMB_ADDEND: r0, [pc, #-0x4] @ THUMB_ADDEND: r0, [pc, #-0xc] diff --git a/llvm/test/MC/ARM/pcrel-thumb-ldr2-relocs.s b/llvm/test/MC/ARM/pcrel-thumb-ldr2-relocs.s index 17ca72bd3f00c..3aa371fc7d702 100644 --- a/llvm/test/MC/ARM/pcrel-thumb-ldr2-relocs.s +++ b/llvm/test/MC/ARM/pcrel-thumb-ldr2-relocs.s @@ -1,6 +1,9 @@ @ RUN: llvm-mc -filetype=obj -triple=thumbv7 %s -o %t @ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=THUMB @ RUN: llvm-objdump -d --triple=thumbv7 %t | FileCheck %s --check-prefix=THUMB_ADDEND +@ RUN: llvm-mc -filetype=obj --triple=thumbebv7-unknown-unknown %s -o %t +@ RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=THUMB +@ RUN: llvm-objdump -d --triple=thumbebv7-unknown-unknown %t | FileCheck %s --check-prefix=THUMB_ADDEND @ All the ldr variants produce a relocation @ THUMB: R_ARM_THM_PC12 diff --git a/llvm/test/MC/ARM/thumb1-relax-adr.s b/llvm/test/MC/ARM/thumb1-relax-adr.s index fc5c7c39df5ae..97b566f4833e6 100644 --- a/llvm/test/MC/ARM/thumb1-relax-adr.s +++ b/llvm/test/MC/ARM/thumb1-relax-adr.s @@ -1,6 +1,5 @@ @ 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 .global func1 _func1: From eed3aa3a4e0866aa1b131902a26d563fb716f609 Mon Sep 17 00:00:00 2001 From: Eleanor Bonnici Date: Fri, 1 Dec 2023 10:43:09 +0000 Subject: [PATCH 2/2] fixup! [llvm][MC][ARM][Assembly] Emit relocations for ADRs and big-endian targets Address David's review comments --- llvm/test/MC/ARM/pcrel-adr16-relocs.s | 5 ++++- llvm/test/MC/ARM/pcrel-adr32-relocs.s | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/test/MC/ARM/pcrel-adr16-relocs.s b/llvm/test/MC/ARM/pcrel-adr16-relocs.s index dd73c9d28a682..adef746c3607a 100644 --- a/llvm/test/MC/ARM/pcrel-adr16-relocs.s +++ b/llvm/test/MC/ARM/pcrel-adr16-relocs.s @@ -13,11 +13,14 @@ _func1: bx lr // Checking the encoding only, as the disassembly is not quite correct here. +//00000000 <_func1>: +// 0: a0ff adr r0, #1020 <_func1+0x103> // Thumb16 encoding supports only adding of the encoded immediate (not // subtracting, see [Arm ARM]), therefore sign change is required if the pcrel // offset is negative. This makes the calculation of the addend for // R_ARM_THM_PC8 more complex, for details see [ELF for the Arm 32-bit // architecture]. -@ ADDEND: a0ff + +@ ADDEND: a0ff adr diff --git a/llvm/test/MC/ARM/pcrel-adr32-relocs.s b/llvm/test/MC/ARM/pcrel-adr32-relocs.s index 015a4d79ccf68..5fd30f24630f9 100644 --- a/llvm/test/MC/ARM/pcrel-adr32-relocs.s +++ b/llvm/test/MC/ARM/pcrel-adr32-relocs.s @@ -22,4 +22,3 @@ _func1: @ ADDEND: sub r0, pc, #8 @ ADDEND-NEXT: adr.w r0, #-4 -