This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

x86 64 bit function argument bug?


The following weird 2 lines of C code (yes, I know taking the address of
a disappearing entity is an evil thing!):
int *i ( int arg ) { return &arg; }
long long *ll ( long long arg ) { return &arg; }

... compile on the x86 into:

	.file	"test.c"
	.text
	.align 2
	.p2align 2,,3
.globl i
	.type	i,@function
i:
	pushl	%ebp
	movl	%esp, %ebp
	leal	8(%ebp), %eax
	leave
	ret
.Lfe1:
	.size	i,.Lfe1-i
	.align 2
	.p2align 2,,3
.globl ll
	.type	ll,@function
ll:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
	leal	-8(%ebp), %eax
	leave
	ret
.Lfe2:
	.size	ll,.Lfe2-ll
	.ident	"GCC: (GNU) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)"

Note that this works as expected (that is, as with the integer argument)
with every other type except the "long long" as above and "double" which
are both 64 bit types on the x86.

Is this a bug or simply luck that the integer type works and the long
long doesn't?  This is compiled with -O3 optimization. With -O0, the
"long long" code goes through all sorts of gymnastics storing the
argument back into the place where it originally was on the stack before
taking the address of the wrong place:

	.align 2
.globl ll
	.type	ll,@function
ll:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
	movl	8(%ebp), %eax
	movl	12(%ebp), %edx
	movl	%eax, -8(%ebp)
	movl	%edx, -4(%ebp)
	leal	-8(%ebp), %eax
	leave
	ret
.Lfe2:
	.size	ll,.Lfe2-ll


Note that the 2.4 Linux kernel depends on this compiling as it expects
in at least one place that I know of:

net/core/neighbour.c
void neigh_destroy(struct neighbour *neigh)
{
        struct hh_cache *hh;

        if (!neigh->dead) {
                printk("Destroying alive neighbour %p from %08lx\n",
                       neigh,
                       *(((unsigned long*)&neigh)-1));
                return;
        }

If this is a bug, then is it fixed in a later revision of GCC, and if
so, can anybody point me to the place so I can regress it into 3.2?

If it is not a bug and is expected behavior, can anybody think of any
sort of fairly portable work around?

Thanks.



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]