public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
@ 2010-03-09 16:31 Thomas Martitz
  2010-03-09 16:42 ` Andrew Haley
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Martitz @ 2010-03-09 16:31 UTC (permalink / raw)
  To: gcc-help

Hello,

I'm trying to migrate to gcc 4.4.3 and eabi (from 4.0.3 non-eabi) for 
the ARM targets of Rockbox[1]. I have the strong feeling I stumbled upon 
a gcc bug here.

The story:
The core and codecs run fine under the new compiler, however at least 1 
plugin is problematic: mpegplayer[2]. The cpu throws a data abort when 
rendering begins.

I've narrowed down the problem to the following function call:

mpeg2_idct_add (last, decoder->DCTblock, dest, stride);[3]

mpeg2_idct_add itself is written entirely in assembler. gcc doesn't 
touch it. However, its prototype for C callers is[4]:

void mpeg2_idct_add(const int last, int16_t * block,
                     uint8_t * dest, const int stride);


According to the (E)ABI, all parameters are supposed to be passed in the 
registers r0-3.

The disassembly shows that this only happens for the old gcc4.0.3
new gcc:

30788e98:    ebfff984     bl    307874b0 <get_non_intra_block>
30788e9c:    e1a03000     mov    r3, r0
30788ea0:    e58d301c     str    r3, [sp, #28]
30788ea4:    e59d3014     ldr    r3, [sp, #20]
30788ea8:    e59330d0     ldr    r3, [r3, #208]    ; 0xd0
30788eac:    e59d2008     ldr    r2, [sp, #8]
30788eb0:    e58d2000     str    r2, [sp]
30788eb4:    e59d001c     ldr    r0, [sp, #28]
30788eb8:    e1a02003     mov    r2, r3
30788ebc:    e59d300c     ldr    r3, [sp, #12]
30788ec0:    ebffe28a     bl    307818f0 <mpeg2_idct_add>

old gcc:

30794760:    ebffc861     bl    307868ec <get_non_intra_block>
30794764:    e1a03000     mov    r3, r0
30794768:    e58d3014     str    r3, [sp, #20]
3079476c:    e59d3010     ldr    r3, [sp, #16]
30794770:    e59330d0     ldr    r3, [r3, #208]
30794774:    e59d0014     ldr    r0, [sp, #20]
30794778:    e1a01003     mov    r1, r3
3079477c:    e59d2008     ldr    r2, [sp, #8]
30794780:    e59d3004     ldr    r3, [sp, #4]
30794784:    ebffb4ea     bl    30781b34 <mpeg2_idct_add>

(the above disassemblies are from code generated with -O0 to make the 
parameter passig obvious)

On 4.4.3, 1 parameter is passed via the stack (I figured it goes like 
this from the old to the new compiler:  r0 = r0; r1 > r2; r2 > r3; r3 > 
stack). So, this call works fine with 4.0.3, but does not with 4.4.3.

Now the reason why I think this is a gcc bug:

If I change the prototype to  (the 2nd and 4th argument are swapped, I 
didn't change the callee or the caller, so gcc obviously throws warnings 
but the effective parameter passing was the same):

void mpeg2_idct_add(const int last, const int stride,
                     uint8_t * dest, int16_t * block);


then the plugin runs fine, without data abort. And the disassembly shows 
correct parameter passing.


EABI IIRC only mentions changed rules for passing 64bit types. This call 
should have been the same with 4.4.3. It eventually is if the parameters 
are in a different order.

If this is really a gcc bug, how should we proceed? I assume a bug 
report on bugzilla?

Best regards.


[1]: http://www.rockbox.org/
[2]: http://www.rockbox.org/wiki/PluginMpegplayer
[3]: 
http://svn.rockbox.org/viewvc.cgi/trunk/apps/plugins/mpegplayer/slice.c?revision=17904&view=markup
[4]: 
http://svn.rockbox.org/viewvc.cgi/trunk/apps/plugins/mpegplayer/mpeg2_internal.h?revision=23677&view=markup


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 16:31 Problems migrating to gcc 4.4.3&eabi - apparently a gcc bug Thomas Martitz
@ 2010-03-09 16:42 ` Andrew Haley
  2010-03-09 17:11   ` Thomas Martitz
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Haley @ 2010-03-09 16:42 UTC (permalink / raw)
  To: thomas.martitz; +Cc: gcc-help

On 03/09/2010 04:30 PM, Thomas Martitz wrote:

> EABI IIRC only mentions changed rules for passing 64bit types. This call
> should have been the same with 4.4.3. It eventually is if the parameters
> are in a different order.
> 
> If this is really a gcc bug, how should we proceed? I assume a bug
> report on bugzilla?

This is very strange.  Can you make a self-contained source file that shows
the problem on its own?  We need to be able to try it.  It doesn't have to
run, we just have to see the source it generates.

Andrew.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 16:42 ` Andrew Haley
@ 2010-03-09 17:11   ` Thomas Martitz
  2010-03-09 18:36     ` Andrew Haley
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Martitz @ 2010-03-09 17:11 UTC (permalink / raw)
  To: gcc-help

Am 09.03.2010 17:41, schrieb Andrew Haley:
> On 03/09/2010 04:30 PM, Thomas Martitz wrote:
>
>    
>> EABI IIRC only mentions changed rules for passing 64bit types. This call
>> should have been the same with 4.4.3. It eventually is if the parameters
>> are in a different order.
>>
>> If this is really a gcc bug, how should we proceed? I assume a bug
>> report on bugzilla?
>>      
> This is very strange.  Can you make a self-contained source file that shows
> the problem on its own?  We need to be able to try it.  It doesn't have to
> run, we just have to see the source it generates.
>
> Andrew.
>    

I tried, but the following code doesn't show this problem :(

-----

#define NULL (void*)0

typedef  signed short int16_t;
typedef  unsigned char uint8_t;

void foo(const int last, int16_t * block,
                     uint8_t * dest, const int stride);


int main(void)
{
     const int a = 2, d = 3;
     int16_t *b = NULL;
     uint8_t *c = NULL;

     foo(a,b,c,d);
     return 0;
}

-----

compiled with arm-elf-eabi-gcc arm-elf-eabi-gcc -O0 -c -W -Wall -Wundef 
-nostdlib -ffreestanding -Wstrict-prototypes -pipe -mcpu=arm9tdmi 
-fomit-frame-pointer -Wno-pointer-sign -fno-strict-aliasing 
-Wno-override-init -O0 -c test-arm.c

(that is the rockbox command line, stripped from a bunch of -I and -D)

Best regards.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 17:11   ` Thomas Martitz
@ 2010-03-09 18:36     ` Andrew Haley
  2010-03-09 18:54       ` Thomas Martitz
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Haley @ 2010-03-09 18:36 UTC (permalink / raw)
  To: thomas.martitz; +Cc: gcc-help

On 03/09/2010 05:11 PM, Thomas Martitz wrote:
> Am 09.03.2010 17:41, schrieb Andrew Haley:
>> On 03/09/2010 04:30 PM, Thomas Martitz wrote:
>>
>>   
>>> EABI IIRC only mentions changed rules for passing 64bit types. This call
>>> should have been the same with 4.4.3. It eventually is if the parameters
>>> are in a different order.
>>>
>>> If this is really a gcc bug, how should we proceed? I assume a bug
>>> report on bugzilla?
>>>      
>> This is very strange.  Can you make a self-contained source file
>> that shows the problem on its own?  We need to be able to try it.
>> It doesn't have to run, we just have to see the source it
>> generates.
> 
> I tried, but the following code doesn't show this problem :(

That does not surprise me.  I think you're seeing a problem that is
caused by something elsewhere in your program.  I'm guessing that
there may be a bad prototype or somesuch.

I think you need to strip down your sources until you find something.

Maybe you should try -save-temps and have a look at the actual
preprocessd source.  Maybe some bastard has done

#define int long

or something evil like that!

Andrew.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 18:36     ` Andrew Haley
@ 2010-03-09 18:54       ` Thomas Martitz
  2010-03-09 19:11         ` Thomas Martitz
  2010-03-09 19:46         ` Andrew Haley
  0 siblings, 2 replies; 11+ messages in thread
From: Thomas Martitz @ 2010-03-09 18:54 UTC (permalink / raw)
  To: gcc-help

Am 09.03.2010 19:36, schrieb Andrew Haley:
> That does not surprise me.  I think you're seeing a problem that is
> caused by something elsewhere in your program.  I'm guessing that
> there may be a bad prototype or somesuch.
>
> I think you need to strip down your sources until you find something.
>
> Maybe you should try -save-temps and have a look at the actual
> preprocessd source.  Maybe some bastard has done
>
> #define int long
>
> or something evil like that!
>
> Andrew.
>    

No, I know our codebase pretty well. This is not the problem. Not that 
int or long matters, anyway.

In the mean time we found a test case:

----
void foo(int last, char * block);

void bar(void)
{
     struct {
         char * __attribute__((aligned(8))) member;
     } s;

     foo(0,s.member);
}
----

compiled with arm-elf-eabi-gcc -c test.c

This example exposes the problem.

We found the problem is related to struct addressing and the aligned 
attribute.

- normal stack variables work
- struct members work with __attribute__((aligned(4)))
- struct members with __attribute__((aligned(X))) where X >= 8 *do not* 
work.

Look at the assembly output for this very example. block is passed in 
r2, while it's supposed to be passed in r1.

Our temporary "fix" is to make it "void foo(int last, volatile char * 
block);" [notice the volatile keyword] and it works as well (block 
passed in r1).

This is definitely a gcc bug. The generated call is dependent on the 
parameter passed. The callee can't know about this. And it also happens 
with -O0.


Best regards.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 18:54       ` Thomas Martitz
@ 2010-03-09 19:11         ` Thomas Martitz
  2010-03-09 19:39           ` John (Eljay) Love-Jensen
  2010-03-09 19:46         ` Andrew Haley
  1 sibling, 1 reply; 11+ messages in thread
From: Thomas Martitz @ 2010-03-09 19:11 UTC (permalink / raw)
  To: gcc-help

Am 09.03.2010 19:54, schrieb Thomas Martitz:
> Am 09.03.2010 19:36, schrieb Andrew Haley:
>> That does not surprise me.  I think you're seeing a problem that is
>> caused by something elsewhere in your program.  I'm guessing that
>> there may be a bad prototype or somesuch.
>>
>> I think you need to strip down your sources until you find something.
>>
>> Maybe you should try -save-temps and have a look at the actual
>> preprocessd source.  Maybe some bastard has done
>>
>> #define int long
>>
>> or something evil like that!
>>
>> Andrew.
>
> No, I know our codebase pretty well. This is not the problem. Not that 
> int or long matters, anyway.
>
> In the mean time we found a test case:
>
> ----
> void foo(int last, char * block);
>
> void bar(void)
> {
>     struct {
>         char * __attribute__((aligned(8))) member;
>     } s;
>
>     foo(0,s.member);
> }
> ----
>
> compiled with arm-elf-eabi-gcc -c test.c
>
> This example exposes the problem.
>
> We found the problem is related to struct addressing and the aligned 
> attribute.
>
> - normal stack variables work
> - struct members work with __attribute__((aligned(4)))
> - struct members with __attribute__((aligned(X))) where X >= 8 *do 
> not* work.
>
> Look at the assembly output for this very example. block is passed in 
> r2, while it's supposed to be passed in r1.
>
> Our temporary "fix" is to make it "void foo(int last, volatile char * 
> block);" [notice the volatile keyword] and it works as well (block 
> passed in r1).
>
> This is definitely a gcc bug. The generated call is dependent on the 
> parameter passed. The callee can't know about this. And it also 
> happens with -O0.
>
>
> Best regards.

A bit more on this issue.

In the rockbox code, this struct member caused the behavior:

     int16_t * ATTR_ALIGN(16) DCTblock;  /* put buffer separately to 
have it in IRAM */

Actually we don't need the pointer to be 16byte aligned, but the buffer 
it points to. Hence, removing the ATTR_ALIGN(16) (a #define for 
__attribute__((aligned(X)) ) works for us.

Nevertheless, it is a gcc bug. It seems likely that gcc confuses 
something here 64bit values must be 8byte aligned afaik. On ARM EABI, 
64bit types need to be passed into an even (and the next odd, e.g. r2 
and r3) registers. Maybe now treats all 8+ byte aligned data as 64bit, 
which would explain why it wants to put normal 32bit into even 
registers, which violates the calling convention.

Best regards.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 19:11         ` Thomas Martitz
@ 2010-03-09 19:39           ` John (Eljay) Love-Jensen
  2010-03-09 19:44             ` Thomas Martitz
  0 siblings, 1 reply; 11+ messages in thread
From: John (Eljay) Love-Jensen @ 2010-03-09 19:39 UTC (permalink / raw)
  To: thomas.martitz, GCC-help

Hi Thomas,

Is this a factor...?

"""
Note that the effectiveness of aligned attributes may be limited by inherent
limitations in your linker. On many systems, the linker is only able to
arrange for variables to be aligned up to a certain maximum alignment. (For
some linkers, the maximum supported alignment may be very very small.) If
your linker is only able to align variables up to a maximum of 8 byte
alignment, then specifying aligned(16) in an __attribute__ will still only
provide you with 8 byte alignment. See your linker documentation for further
information. 
"""

http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html

Do you know if the linker being used supports the alignment your code is
requesting on your platform?

Sincerely,
--Eljay

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 19:39           ` John (Eljay) Love-Jensen
@ 2010-03-09 19:44             ` Thomas Martitz
  0 siblings, 0 replies; 11+ messages in thread
From: Thomas Martitz @ 2010-03-09 19:44 UTC (permalink / raw)
  To: gcc-help

Am 09.03.2010 20:39, schrieb John (Eljay) Love-Jensen:
> Hi Thomas,
>
> Is this a factor...?
>
> """
> Note that the effectiveness of aligned attributes may be limited by inherent
> limitations in your linker. On many systems, the linker is only able to
> arrange for variables to be aligned up to a certain maximum alignment. (For
> some linkers, the maximum supported alignment may be very very small.) If
> your linker is only able to align variables up to a maximum of 8 byte
> alignment, then specifying aligned(16) in an __attribute__ will still only
> provide you with 8 byte alignment. See your linker documentation for further
> information.
> """
>
> http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
> http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
>
> Do you know if the linker being used supports the alignment your code is
> requesting on your platform?
>
> Sincerely,
> --Eljay
>
>    

It doesn't have anything to with the linker. The example code I posted 
shows the bug even before being linked or assembled.

And I'm not searching for help on aligning stuff, I'm searching for help 
regarding the buggy register allocation for subroutine calls.

Best regards.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 18:54       ` Thomas Martitz
  2010-03-09 19:11         ` Thomas Martitz
@ 2010-03-09 19:46         ` Andrew Haley
  2010-03-10 15:56           ` Ian Lance Taylor
  1 sibling, 1 reply; 11+ messages in thread
From: Andrew Haley @ 2010-03-09 19:46 UTC (permalink / raw)
  To: thomas.martitz; +Cc: gcc-help

On 03/09/2010 06:54 PM, Thomas Martitz wrote:
> Am 09.03.2010 19:36, schrieb Andrew Haley:
>> That does not surprise me.  I think you're seeing a problem that is
>> caused by something elsewhere in your program.  I'm guessing that
>> there may be a bad prototype or somesuch.
>>
>> I think you need to strip down your sources until you find something.
>>
>> Maybe you should try -save-temps and have a look at the actual
>> preprocessd source.  Maybe some bastard has done
>>
>> #define int long
>>
>> or something evil like that!
>>
>> Andrew.
>>    
> 
> No, I know our codebase pretty well. This is not the problem. Not that
> int or long matters, anyway.
> 
> In the mean time we found a test case:
> 
> ----
> void foo(int last, char * block);
> 
> void bar(void)
> {
>     struct {
>         char * __attribute__((aligned(8))) member;
>     } s;
> 
>     foo(0,s.member);
> }
> ----
> 
> compiled with arm-elf-eabi-gcc -c test.c
> 
> This example exposes the problem.
> 
> We found the problem is related to struct addressing and the aligned
> attribute.
> 
> - normal stack variables work
> - struct members work with __attribute__((aligned(4)))
> - struct members with __attribute__((aligned(X))) where X >= 8 *do not*
> work.
> 
> Look at the assembly output for this very example. block is passed in
> r2, while it's supposed to be passed in r1.
> 
> Our temporary "fix" is to make it "void foo(int last, volatile char *
> block);" [notice the volatile keyword] and it works as well (block
> passed in r1).
> 
> This is definitely a gcc bug. The generated call is dependent on the
> parameter passed. The callee can't know about this. And it also happens
> with -O0.

Yeah, it's a bug.  Mind you, it's pretty bizarre code: I'm not surprised
we never came across this before.

Why are you doing this, anyway?  I would have expected

char __attribute__((aligned(8))) *member;

for a pointer to an 8-aligned buffer...

Andrew.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-09 19:46         ` Andrew Haley
@ 2010-03-10 15:56           ` Ian Lance Taylor
  2010-03-10 16:36             ` Thomas Martitz
  0 siblings, 1 reply; 11+ messages in thread
From: Ian Lance Taylor @ 2010-03-10 15:56 UTC (permalink / raw)
  To: Andrew Haley; +Cc: thomas.martitz, gcc-help

Andrew Haley <aph@redhat.com> writes:

> Yeah, it's a bug.  Mind you, it's pretty bizarre code: I'm not surprised
> we never came across this before.

Bizarre or not, please report it following the guidelines at
http://gcc.gnu.org/bugs/ .  Thanks.

Ian

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Problems migrating to gcc 4.4.3&eabi  - apparently a gcc bug
  2010-03-10 15:56           ` Ian Lance Taylor
@ 2010-03-10 16:36             ` Thomas Martitz
  0 siblings, 0 replies; 11+ messages in thread
From: Thomas Martitz @ 2010-03-10 16:36 UTC (permalink / raw)
  To: gcc-help

Am 10.03.2010 16:55, schrieb Ian Lance Taylor:
> Andrew Haley<aph@redhat.com>  writes:
>
>    
>> Yeah, it's a bug.  Mind you, it's pretty bizarre code: I'm not surprised
>> we never came across this before.
>>      
> Bizarre or not, please report it following the guidelines at
> http://gcc.gnu.org/bugs/ .  Thanks.
>
> Ian
>    

I will gather the required information and post the bug reported. Thanks 
for the help so far!

Best regards.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-03-10 16:36 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-09 16:31 Problems migrating to gcc 4.4.3&eabi - apparently a gcc bug Thomas Martitz
2010-03-09 16:42 ` Andrew Haley
2010-03-09 17:11   ` Thomas Martitz
2010-03-09 18:36     ` Andrew Haley
2010-03-09 18:54       ` Thomas Martitz
2010-03-09 19:11         ` Thomas Martitz
2010-03-09 19:39           ` John (Eljay) Love-Jensen
2010-03-09 19:44             ` Thomas Martitz
2010-03-09 19:46         ` Andrew Haley
2010-03-10 15:56           ` Ian Lance Taylor
2010-03-10 16:36             ` Thomas Martitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).