Bug 29938 - [3.4.4/3.4.6/4.1.1] ARM structure pointer alignment problem with optimization
Summary: [3.4.4/3.4.6/4.1.1] ARM structure pointer alignment problem with optimization
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.1.1
: P3 major
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-11-22 10:18 UTC by Bernard Fouché
Modified: 2006-11-22 10:50 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bernard Fouché 2006-11-22 10:18:52 UTC
Hi.

I've a reduced test case showing that a function like:

struct x {
 uint8_t a;
 uint16_t b;
};

f(struct x *y)
...

will expect that 'y' is correctly aligned: it uses 'ldrh' to access y->b and ldrh documentation says "if the memory is not halfworld-aligned and no data abort occurs, the value written to the destination register is unpredictable."

Test case:

typedef unsigned char		uint8_t;
typedef unsigned short int	uint16_t;

struct x {
  uint16_t d;
  uint8_t c;
};

int f(struct x *y)
{
  diag_printf("y=%p y->c=%d(0x%x) y->d=%d(0x%x)\n\r",y,y->c,y->c,y->d,y->d);
}

int main(int argc,char **argv )
{
  void *s=malloc(sizeof(struct x)+1);
  struct x *y;

  s++;   // <- problem origin

  y=s;
  y->c=0xAA;
  y->d=0xBBCC;
  f(y);

  while(1);
}

Without "s++;":

y=0x000088e0 y->c=170(0xaa) y->d=48076(0xbbcc)

With "s++;":

y=0x000088e1 y->c=170(0xaa) y->d=-872415045(0xcc0000bb)

Generated code with -Os is:

int f(struct x *y)
{
40000698:	b500      	push	{lr}
  diag_printf("y=%p y->c=%d(0x%x) y->d=%d(0x%x)\n\r",y,y->c,y->c,y->d,y->d);
4000069a:	7883      	ldrb	r3, [r0, #2]
4000069c:	8802      	ldrh	r2, [r0, #0] <--- *HERE*
4000069e:	b082      	sub	sp, #8
400006a0:	9200      	str	r2, [sp, #0]
400006a2:	9201      	str	r2, [sp, #4]
400006a4:	1c01      	mov	r1, r0		(add r1, r0, #0)
400006a6:	1c1a      	mov	r2, r3		(add r2, r3, #0)
400006a8:	4802      	ldr	r0, [pc, #8]	(400006b4 <.text+0x674>)
400006aa:	ff4ff002 	bl	4000354c <diag_printf>
}
400006ae:	b002      	add	sp, #8
400006b0:	bc02      	pop	{r1}
400006b2:	4708      	bx	r1
400006b4:	98e4      	ldr	r0, [sp, #912]
400006b6:	4000      	and	r0, r0

Tested on arm-elf-gcc 3.4.4, 3.4.6, 4.1.1, the latest two with and without the patch related to bug 29373.

Thanks for your help.
Comment 1 Richard Earnshaw 2006-11-22 10:50:41 UTC
The compiler expects 'y' to be correctly aligned because the ABI says that it can expect this to be so.  If you write a program that then provides an unaligned value, then the behaviour is undefined and you can get any result the compiler feels like giving you.

Hint: don't increment void* pointers (it's a gcc extension that permits this anyway) and then try to assign them to a structure.  Malloc provides memory that is correctly aligned for direct assignment to any structure type.
Comment 2 Bernard Fouché 2006-11-22 11:32:51 UTC
Subject: Re:  [3.4.4/3.4.6/4.1.1] ARM structure pointer alignment
 problem with optimization

rearnsha at gcc dot gnu dot org wrote:
> ------- Comment #1 from rearnsha at gcc dot gnu dot org  2006-11-22 10:50 -------
> The compiler expects 'y' to be correctly aligned because the ABI says that it
> can expect this to be so.  If you write a program that then provides an
> unaligned value, then the behaviour is undefined and you can get any result the
> compiler feels like giving you.
>
> Hint: don't increment void* pointers (it's a gcc extension that permits this
> anyway) and then try to assign them to a structure.  Malloc provides memory
> that is correctly aligned for direct assignment to any structure type.
>
>
>   
Sorry for having taken your time for nothing. I'll read the ABI spec 
better next time. Too bad my target does not have alignment traps, I've 
fallen in the problem while building a packet with an odd size header.

Regards,

 Bernard