Bug 30553 - Registers not spilled to the stack properly when accessing address of parameter in function call
Summary: Registers not spilled to the stack properly when accessing address of parame...
Status: RESOLVED DUPLICATE of bug 21920
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-01-23 04:59 UTC by Stefan Burström
Modified: 2007-01-23 05:08 UTC (History)
9 users (show)

See Also:
Host: x86-pc-cygwin
Target: arm-elf-gcc
Build: x86-pc-cygwin
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 Stefan Burström 2007-01-23 04:59:41 UTC
To get the binary int of a double, it is common to cast the ptr to the double to an int ptr and then access the data the pointer points to. However, if the variable containing the double is a function call parameter and the parameter is passed in registers and hasn't been spilled to the stack yet, the pointer access will be accessing uninitialized stack space:

Example:

arm-elf-gcc -Os -mthumb

int myfunc(double x)
{
	int a;
	a = *(int *)&x;	 // x isn't spilled to the stack before the * access is done
	return a+2;
}

int myfunc2(int x)
{
	int a;
	a = *(int *)&x;	// gcc figures out that it doesn't have to go through memory to do the access
	return a+2;
}

extern void dummy(void);

int myfunc3(double x)
{
	int a;
	dummy(); // This function call forces gcc to spill x (r0 and r1) to memory
	a = *(int *)&x;	
	return a+2;
}

The disassembly is:

00000000 <myfunc>:
   0:   b082            sub     sp, #8
   2:   9800            ldr     r0, [sp, #0] ; reading from [sp, #0] where r0 should have been saved. Error!
   4:   b002            add     sp, #8
   6:   3002            add     r0, #2
   8:   4770            bx      lr
        ...

0000000c <myfunc2>:
   c:   3002            add     r0, #2 ; Doesn't have to go through the stack. OK!
   e:   4770            bx      lr

00000010 <myfunc3>:
  10:   b500            push    {lr}
  12:   b082            sub     sp, #8
  14:   9000            str     r0, [sp, #0] ; Aha! r0 is correctly spilled to the stack to be able to make the function call below
  16:   9101            str     r1, [sp, #4]
  18:   fffef7ff        bl      0 <dummy>
  1c:   9800            ldr     r0, [sp, #0] ; Reading from the stack now gives the correct result. OK!
  1e:   b002            add     sp, #8
  20:   3002            add     r0, #2
  22:   bd00            pop     {pc}

The problem appears for both thumb and normal arm code. I guess the same thing can happen on any platform that passes the initial parameters in registers
Comment 1 Andrew Pinski 2007-01-23 05:08:49 UTC
This is a very obvious case of violating C/C++ aliasing rules.

You are accessing a double as an int which is undefined by the C/C++ aliasing rules.  either use -fno-strict-aliasing, memcpy or an union (which is only unspecified behavior in C while GCC defines it).

*** This bug has been marked as a duplicate of 21920 ***