[arm][RFC] PR target/88469 fix incorrect argument passing with 64-bit bitfields

Richard Earnshaw (lists) Richard.Earnshaw@arm.com
Thu Feb 28 13:18:00 GMT 2019


On 27/01/2019 11:20, Bernd Edlinger wrote:
> Hi,
> 
> I know I am a bit late on the party.

Sorry for the delay replying, I've been off sick...

> 
> But I have a question...
> 
> Consider this test case:
> 
> $ cat test.c
> struct s {
>   int a, b;
> } __attribute__((aligned(8)));
> 
> struct s f0;
> int f(int a, int b, int c, int d, int e, struct s f)
> {
>   f0 = f;
>   return __alignof(f);

This is equivalent to writing __alignof (struct s), so the returned
value should be 8.

HOWEVER, f itself is just a value in terms of the PCS, so it is correct
for it to be passed at SP+4.

> }
> 
> $ arm-linux-gnueabihf-gcc -march=armv5te -O3 -S test.c
> $ cat test.s
> f:
> 	@ args = 12, pretend = 0, frame = 0
> 	@ frame_needed = 0, uses_anonymous_args = 0
> 	@ link register save eliminated.
> 	push	{r4, r5}
> 	mov	r0, #8
> 	ldrd	r4, [sp, #12]

So this is wrong; before the compiler can use 'f' it has to copy it to a
suitably aligned location; it can't directly reuse the value on the
stack as that is not sufficiently aligned for the type.

> 	ldr	r3, .L4
> 	strd	r4, [r3]
> 	pop	{r4, r5}
> 	bx	lr
> 
> I am pretty sure, although there is no warning, this ABI changed in GCC 5.2

There was no explicit ABI for overaligned types in the past; so anything
could have happened.

> 
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0473m/dom1361290002364.html
> says:
> 
> "In ARMv5TE, or in ARMv6 when SCTLR.U is 0, LDRD and STRD doubleword data transfers must be
> eight-byte aligned.  Use ALIGN 8 before memory allocation directives such as DCQ if the data
> is to be accessed using LDRD or STRD.  This is not required in ARMv6 when SCTLR.U is 1, or in
> ARMv7, because in these versions, doubleword data transfers can be word-aligned."
> 
> 
> So isn't this wrong code, returning 8 for alignof when it is really 4,
> and wouldn't it crash on armv5 and armv6 with SCTLR.U=0 ?

Returning 8 is correct; since that is the alignment of the type; but GCC
does need to copy underaligned types to suitably aligned memory before
it uses them; it must not use the *value* that is passed directly,
unless it can prove that doing so is safe (and as you point out, on
armv5 it is not).

I think technically, this is separate bug from the PCS one that was
fixed, so needs a new PR.

> 
> 
> Bernd.
> 

Thanks,

R.



More information about the Gcc-patches mailing list