[lld] [LLD][ARM] Arm v6-m should not use short Thunks. (PR #118111)
Peter Smith via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 2 01:24:34 PST 2024
https://github.com/smithp35 updated https://github.com/llvm/llvm-project/pull/118111
>From 7c7ea18e7ec8980ef13f19496c11429f352828fd Mon Sep 17 00:00:00 2001
From: Peter Smith <peter.smith at arm.com>
Date: Fri, 29 Nov 2024 15:45:59 +0000
Subject: [PATCH 1/2] [LLD][ARM] Arm v6-m should not use short Thunks.
Thumb short thunks use the B.w instruction. This instruction is not
present on Arm v6-m so we should prevent these targets from using
short-thunks. We want to permit Arm v8-m.base targets to continue
using short thunks as it does have the B.w instruction despite not
implementing all of Thumb 2.
Add a check to see if the Movt and Movw instructions are present
before enabling short thunks for Thumb. The v6-m architecture has
J1J2BranchEncoding, but it does not have Movt and Movw, whereas
v8-m.base has both.
The memory map and limited flash size of an Arm v6-m CPU makes a
short thunk very unlikely in practice, but it is worth getting it
right just in case.
---
lld/ELF/Thunks.cpp | 9 +++-
lld/test/ELF/arm-thumb-thunk-v6m-noshort.s | 57 ++++++++++++++++++++++
2 files changed, 65 insertions(+), 1 deletion(-)
create mode 100644 lld/test/ELF/arm-thumb-thunk-v6m-noshort.s
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 629ce356ce2e7d..4e4e0684a3f596 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -792,7 +792,14 @@ bool ThumbThunk::getMayUseShortThunk() {
if (!mayUseShortThunk)
return false;
uint64_t s = getARMThunkDestVA(ctx, destination);
- if ((s & 1) == 0 || !ctx.arg.armJ1J2BranchEncoding) {
+ // To use a short thunk the destination must be Thumb and the target must
+ // have the wide branch instruction B.w. This instruction is included when
+ // Thumb 2 is present, or in v8-M (and above) baseline architectures.
+ // armJ1J2BranchEncoding is available in all architectures with a profile and
+ // the one v6 CPU that implements Thumb 2 (Arm1156t2-s).
+ // Movt and Movw instructions require Thumb 2 or v8-M baseline.
+ if ((s & 1) == 0 || !ctx.arg.armJ1J2BranchEncoding ||
+ !ctx.arg.armHasMovtMovw) {
mayUseShortThunk = false;
addLongMapSyms();
return false;
diff --git a/lld/test/ELF/arm-thumb-thunk-v6m-noshort.s b/lld/test/ELF/arm-thumb-thunk-v6m-noshort.s
new file mode 100644
index 00000000000000..6b68b7bde67d03
--- /dev/null
+++ b/lld/test/ELF/arm-thumb-thunk-v6m-noshort.s
@@ -0,0 +1,57 @@
+// REQUIRES: arm
+// RUN: rm -rf %t && split-file %s %t && cd %t
+// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv6m-none-eabi asm -o v6m.o
+// RUN: ld.lld --script=lds v6m.o -o v6m
+// RUN: llvm-objdump --no-print-imm-hex --no-show-raw-insn -d v6m --triple=armv6m-none-eabi
+
+// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv8m.base-none-eabi asm -o v8m.o
+// RUN: ld.lld --script=lds v8m.o -o v8m
+// RUN: llvm-objdump --no-print-imm-hex --no-show-raw-insn -d v8m --triple=armv8m.base-none-eabi | FileCheck --check-prefix=CHECKV8BASE %s
+
+/// Test that short thunks are not generated for v6-m as this architecture
+/// does not have the B.w instruction.
+
+//--- asm
+ .syntax unified
+
+ .section .text_low, "ax", %progbits
+ .thumb
+ .type _start, %function
+ .balign 4
+ .globl _start
+_start:
+ bl far
+ .space 0x1000 - (. - _start)
+
+/// Thunks will be inserted here. They are in short thunk range for a B.w
+/// instruction. Expect v6-M to use a long thunk as v6-M does not have B.w.
+/// Expect v8-m.base to use a short thunk as despite not having Thumb 2 it
+/// does have B.w.
+
+// CHECK-LABEL: <__Thumbv6MABSLongThunk_far>:
+// CHECK-NEXT: 2000: push {r0, r1}
+// CHECK-NEXT: ldr r0, [pc, #4]
+// CHECK-NEXT: str r0, [sp, #4]
+// CHECK-NEXT: pop {r0, pc}
+// CHECK-NEXT: bo01 20 00 01 .word 0x01002001
+
+// CHECKV8BASE-LABEL: <__Thumbv7ABSLongThunk_far>:
+// CHECKV8BASE-NEXT: 2000: b.w 0x1002000 <far>
+
+ .section .text_high, "ax", %progbits
+ .globl far
+ .type far, %function
+ .balign 4
+far:
+ bx lr
+
+//--- lds
+
+PHDRS {
+ low PT_LOAD FLAGS(0x1 | 0x4);
+ high PT_LOAD FLAGS(0x1 | 0x4);
+}
+SECTIONS {
+ .text_low 0x1000 : { *(.text_low) }
+ .text_high 0x1002000 : { *(.text_high) }
+}
>From aa708d263defe63fe23dbf822e565a160943009b Mon Sep 17 00:00:00 2001
From: Peter Smith <peter.smith at arm.com>
Date: Mon, 2 Dec 2024 09:21:00 +0000
Subject: [PATCH 2/2] Remember to add FileCheck to disassembly.
Also remove errant tmux switch buffer typo.
---
lld/test/ELF/arm-thumb-thunk-v6m-noshort.s | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lld/test/ELF/arm-thumb-thunk-v6m-noshort.s b/lld/test/ELF/arm-thumb-thunk-v6m-noshort.s
index 6b68b7bde67d03..43d6fc27f55c9c 100644
--- a/lld/test/ELF/arm-thumb-thunk-v6m-noshort.s
+++ b/lld/test/ELF/arm-thumb-thunk-v6m-noshort.s
@@ -2,7 +2,7 @@
// RUN: rm -rf %t && split-file %s %t && cd %t
// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv6m-none-eabi asm -o v6m.o
// RUN: ld.lld --script=lds v6m.o -o v6m
-// RUN: llvm-objdump --no-print-imm-hex --no-show-raw-insn -d v6m --triple=armv6m-none-eabi
+// RUN: llvm-objdump --no-print-imm-hex --no-show-raw-insn -d v6m --triple=armv6m-none-eabi | FileCheck %s
// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv8m.base-none-eabi asm -o v8m.o
// RUN: ld.lld --script=lds v8m.o -o v8m
@@ -33,7 +33,7 @@ _start:
// CHECK-NEXT: ldr r0, [pc, #4]
// CHECK-NEXT: str r0, [sp, #4]
// CHECK-NEXT: pop {r0, pc}
-// CHECK-NEXT: bo01 20 00 01 .word 0x01002001
+// CHECK-NEXT: 01 20 00 01 .word 0x01002001
// CHECKV8BASE-LABEL: <__Thumbv7ABSLongThunk_far>:
// CHECKV8BASE-NEXT: 2000: b.w 0x1002000 <far>
More information about the llvm-commits
mailing list