[Bug target/69979] New: ARM naked function attribute not handling structs bigger than 32 bits correctly
andre.simoesdiasvieira at arm dot com
gcc-bugzilla@gcc.gnu.org
Fri Feb 26 13:20:00 GMT 2016
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69979
Bug ID: 69979
Summary: ARM naked function attribute not handling structs
bigger than 32 bits correctly
Product: gcc
Version: 6.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: andre.simoesdiasvieira at arm dot com
Target Milestone: ---
As reported by Cory in https://bugs.launchpad.net/gcc-arm-embedded/+bug/1549542
It seems the naked function attribute for ARM is generating code for struct
parameters being passed in registers. This code stores these structs being
passed as registers on the stack, using 'r3' as a scratch register. Apart from
being suboptimal, this writes to 'r3' even though 'r3' might be used to hold a
parameter!
For instance with the following C code:
struct test {
int a;
int b;
};
int
foo (struct test t, int a, int b)
{
__asm ("mov r0, r3\n\t"
"bx lr");
}
when compiled with
$arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -S
will yield the following assembly:
foo:
@ Naked Function: prologue and epilogue provided by programmer.
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
mov r3, r7
stm r3, {r0, r1}
.syntax unified
@ 9 "tnaked.c" 1
mov r0, r3
bx lr
@ 0 "" 2
.syntax unified
nop
mov r0, r3
As you see 'r3' will have been rewritten with the frame pointer before being
moved to 'r0' for the return. Also the last 'mov r0, r3' after the 'nop' looks
a bit odd!
Something equally weird happens when returning such a struct:
struct test
bar (int a, int b, int c)
{
__asm ("stmia r0, {r2, r3}\n\t"
"bx lr");
}
One would naturally expect to be storing 'b' and 'c' into '[r0]', the place
where the caller expects the return value to be written to. However the
following assembly is generated, which overwrites r3 (which should contain
argument 'c'):
bar:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
mov r3, r0
@ 16 "tnaked.c" 1
stmia r0, {r2, r3}
bx lr
@ 0 "" 2
.thumb
mov r0, r3
bx lr
Again with the unexpected epilogue code creeping in.
I have observed this behavior for various ARM targets dating back to gcc 4.8
(haven't tried earlier than that).
More information about the Gcc-bugs
mailing list