https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88656
Bug ID: 88656
Summary: [7/8/9 Regression] lr clobbered by thumb prologue
before __builtin_return_address(0) reads from it
Product: gcc
Version: unknown
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: aoliva at gcc dot gnu.org
Target Milestone: ---
Target: arm-none-eabi
Alas, the fix for bug 77933 broke __builtin_return_address(0) in both leaf and
non-leaf functions on ARM -mthumb, because lr is now more likely to be used as
a scratch register to save other high registers, but then its value is used in
__builtin_return_address(0) as if it still held the return address.
This remains broken in GCC9 (I've just tried r267435).
Add "r4" to the clobber list, or compile the original testcase with
-fno-omit-frame-pointer, to get:
push {r[47], lr}
mov lr, r9
mov r[47], r8
push {r[47], lr}
[ add r7, sp, #0 ];; -fno-omit-frame-pointer only
mov r0, lr
Add a call to e.g. bar() between the asm and the return, and you'll also see lr
overwritten and then used as if it still held the return address:
push {r4, lr}
mov lr, r9
mov r4, r8
push {r4, lr}
mov r4, lr
bl bar
movs r0, r4
Before the patch for PR 77933, lr would not be overwritten before use in any of
these cases.