Skip to content
Merged
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
9 changes: 8 additions & 1 deletion lld/ELF/Thunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
57 changes: 57 additions & 0 deletions lld/test/ELF/arm-thumb-thunk-v6m-noshort.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// REQUIRES: arm
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test passes even without the code change. Is that expected?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies it looks like I forgot to add FileCheck to the objdump for v6-m. Now done, which revealed a typo induced by fumbling a tmux switch buffer.

Tested that this now passes with the patch, and doesn't with an existing lld.

// 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 | 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
// 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: 01 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) }
}
Loading