x86_64 ABI

Maurizio Vitale maurizio.vitale@polymath-solutions.com
Thu Jul 13 17:55:00 GMT 2006


my understanding of the x86_64 ABI is that the following structure  
should be passed in registers:

struct data {
	unsigned int x;
	unsigned int y;
	unsigned long z;
};

but when I compile:

#include <stdio.h>

struct data {
   unsigned int  x       : 32;
   unsigned int  y       : 32;
   unsigned long dummy   : 64;
} ;

#ifdef __cplusplus
extern "C" int foo (data t);
#else
extern int foo (struct data t);
#endif

#ifndef __cplusplus
struct
#endif
data    d;

int
main (int argc, char* argv[])
{
   d.x = 1; d.y = 2;

   printf ("an integer %d", foo(d));

   return 0;
}

I get different results, depending on whether I compile it as C or C+ 
+ code. I'm using gcc 4.1.1 (but the same happens with 3.4.5).

In C I get:
main:
.LFB12:
         subq    $8, %rsp
.LCFI0:
         movl    $1, d+8(%rip)
         movl    $2, d+12(%rip)
         movq    d(%rip), %rdi
         movq    d+8(%rip), %rsi
         call    foo

so the argument gets passed in registers.

But in C++ the result is different and the data structure is passed  
on the stack.
main:
.LFB13:
         subq    $24, %rsp
.LCFI0:
         movl    $1, d+8(%rip)
         movq    d(%rip), %rdi
         movl    $2, d+12(%rip)
         movq    d+8(%rip), %rsi
         movq    %rdi, (%rsp)
         movq    %rsi, 8(%rsp)
         call    foo

My understanding of the ABI is that the data structure should be  
passed in registers, but in any case the behavior should be the same  
for C and C++ when data is POD. In the example if foo was a C  
function the code produced by g++ would be wrong. In this case it  
would also be very dangerous because the data structure happens to be  
_also_ in the right registers, but I expect small changes to the code  
to make it fail.
Unless g++ is actually passing the argument in registers and what's  
wrong is the spurious pushes onto the stack.

Maurizio Vitale





More information about the Gcc mailing list