Skip to content

Commit 457e14b

Browse files
authored
[LLD][ARM] Arm v6-m should not use short Thunks. (#118111)
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.
1 parent 46e04f7 commit 457e14b

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

lld/ELF/Thunks.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,14 @@ bool ThumbThunk::getMayUseShortThunk() {
792792
if (!mayUseShortThunk)
793793
return false;
794794
uint64_t s = getARMThunkDestVA(ctx, destination);
795-
if ((s & 1) == 0 || !ctx.arg.armJ1J2BranchEncoding) {
795+
// To use a short thunk the destination must be Thumb and the target must
796+
// have the wide branch instruction B.w. This instruction is included when
797+
// Thumb 2 is present, or in v8-M (and above) baseline architectures.
798+
// armJ1J2BranchEncoding is available in all architectures with a profile and
799+
// the one v6 CPU that implements Thumb 2 (Arm1156t2-s).
800+
// Movt and Movw instructions require Thumb 2 or v8-M baseline.
801+
if ((s & 1) == 0 || !ctx.arg.armJ1J2BranchEncoding ||
802+
!ctx.arg.armHasMovtMovw) {
796803
mayUseShortThunk = false;
797804
addLongMapSyms();
798805
return false;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// REQUIRES: arm
2+
// RUN: rm -rf %t && split-file %s %t && cd %t
3+
// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv6m-none-eabi asm -o v6m.o
4+
// RUN: ld.lld --script=lds v6m.o -o v6m
5+
// RUN: llvm-objdump --no-print-imm-hex --no-show-raw-insn -d v6m --triple=armv6m-none-eabi | FileCheck %s
6+
7+
// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv8m.base-none-eabi asm -o v8m.o
8+
// RUN: ld.lld --script=lds v8m.o -o v8m
9+
// RUN: llvm-objdump --no-print-imm-hex --no-show-raw-insn -d v8m --triple=armv8m.base-none-eabi | FileCheck --check-prefix=CHECKV8BASE %s
10+
11+
/// Test that short thunks are not generated for v6-m as this architecture
12+
/// does not have the B.w instruction.
13+
14+
//--- asm
15+
.syntax unified
16+
17+
.section .text_low, "ax", %progbits
18+
.thumb
19+
.type _start, %function
20+
.balign 4
21+
.globl _start
22+
_start:
23+
bl far
24+
.space 0x1000 - (. - _start)
25+
26+
/// Thunks will be inserted here. They are in short thunk range for a B.w
27+
/// instruction. Expect v6-M to use a long thunk as v6-M does not have B.w.
28+
/// Expect v8-m.base to use a short thunk as despite not having Thumb 2 it
29+
/// does have B.w.
30+
31+
// CHECK-LABEL: <__Thumbv6MABSLongThunk_far>:
32+
// CHECK-NEXT: 2000: push {r0, r1}
33+
// CHECK-NEXT: ldr r0, [pc, #4]
34+
// CHECK-NEXT: str r0, [sp, #4]
35+
// CHECK-NEXT: pop {r0, pc}
36+
// CHECK-NEXT: 01 20 00 01 .word 0x01002001
37+
38+
// CHECKV8BASE-LABEL: <__Thumbv7ABSLongThunk_far>:
39+
// CHECKV8BASE-NEXT: 2000: b.w 0x1002000 <far>
40+
41+
.section .text_high, "ax", %progbits
42+
.globl far
43+
.type far, %function
44+
.balign 4
45+
far:
46+
bx lr
47+
48+
//--- lds
49+
50+
PHDRS {
51+
low PT_LOAD FLAGS(0x1 | 0x4);
52+
high PT_LOAD FLAGS(0x1 | 0x4);
53+
}
54+
SECTIONS {
55+
.text_low 0x1000 : { *(.text_low) }
56+
.text_high 0x1002000 : { *(.text_high) }
57+
}

0 commit comments

Comments
 (0)