Bug 34001 - Incorrect x86 fastcall behavior
Summary: Incorrect x86 fastcall behavior
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: 4.3.0
Assignee: H.J. Lu
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: patch
Depends on:
Blocks:
 
Reported: 2007-11-05 23:40 UTC by Zia Ansari
Modified: 2007-11-28 01:25 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2007-11-09 16:55:09


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Zia Ansari 2007-11-05 23:40:24 UTC
4byte structures that are passed as parameters to a fastcall routine will get passed as registers. This does not match the original fastcall convention, which passes such structures on the stack.

Compiling this code:
#include <stdio.h>

typedef struct {
  int a;
} my_struct;

int __attribute__((fastcall)) foo(my_struct s, int b)
{
  return s.a + b;
}


main()
{
  my_struct ss;
  ss.a = 1;
  printf("\nfoo = %d.\n",foo(ss,2));
}

Results in:
.
.
        movl    $1, -12(%ebp)
        movl    -12(%ebp), %ecx
        movl    $2, %edx
        call    _foo
.
.
and
.
.
.globl _foo
_foo:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        movl    %ecx, -12(%ebp)
        movl    %edx, -16(%ebp)
        movl    -12(%ebp), %eax
        addl    -16(%ebp), %eax
        leave
        ret

With GCC.

Using other compilers that support fastcall will pass the struct value on the stack.
Comment 1 H.J. Lu 2007-11-08 17:12:04 UTC
I verified that it isn't fixed in gcc 4.3.0.
Comment 2 H.J. Lu 2007-11-09 16:55:09 UTC
From

http://msdn2.microsoft.com/en-us/library/6xa169sk(VS.80).aspx

"The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left."

But it isn't clear if it applies to structure/union. We tested all MS compilers
we have and verified that the above doesn't apply to structure/union. To make
fastcall compatible with MS compilers, we should only put scalar arguments
in ECX and EDX.
Comment 3 H.J. Lu 2007-11-09 17:34:17 UTC
A patch is posted at

http://gcc.gnu.org/ml/gcc-patches/2007-11/msg00531.html
Comment 4 H.J. Lu 2007-11-12 03:27:05 UTC
From "info gcc",

`fastcall'
     On the Intel 386, the `fastcall' attribute causes the compiler to
     pass the first argument (if of integral type) in the register ECX
                              ^^^^^^^^^^^^^^^^^^^
     and the second argument (if of integral type) in the register EDX.
                              ^^^^^^^^^^^^^^^^^^^
     Subsequent and other typed arguments are passed on the stack.
     The called function will pop the arguments off the stack.  If the
     number of arguments is variable all arguments are pushed on the
     stack.

It looks like gcc document follows MS compiler and we didn't implement
it correctly.
Comment 5 H.J. Lu 2007-11-16 04:52:01 UTC
The correct patch is at

http://gcc.gnu.org/ml/gcc-patches/2007-11/msg00885.html
Comment 6 H.J. Lu 2007-11-26 23:19:02 UTC
We have changed fastcall behavior from gcc 3.4 to 4.1. For

---
#define FASTCALL __attribute((fastcall))

double FASTCALL  f_dii( double p1d, int p2i, int p3i ){  return p1d + (double)p2
i + (double)p3i;  }

int    test_x;
int    test_y;
double test_d1;

void caller( void ){
  f_dii( test_d1, test_x, test_y );
}
---

Gcc 3.4 doesn't pass the first 2 integral parameters in ecx/edx and gcc
4.1 does.
Comment 7 H.J. Lu 2007-11-27 02:36:01 UTC
(In reply to comment #6)
> We have changed fastcall behavior from gcc 3.4 to 4.1. For
> 
> ---
> #define FASTCALL __attribute((fastcall))
> 
> double FASTCALL  f_dii( double p1d, int p2i, int p3i ){  return p1d +
> (double)p2
> i + (double)p3i;  }
> 
> int    test_x;
> int    test_y;
> double test_d1;
> 
> void caller( void ){
>   f_dii( test_d1, test_x, test_y );
> }
> ---
> 
> Gcc 3.4 doesn't pass the first 2 integral parameters in ecx/edx and gcc
> 4.1 does.
> 

This patch

http://gcc.gnu.org/ml/gcc-patches/2005-01/msg00541.html

fixes this fast call bug by changing the abi.
Comment 8 hjl@gcc.gnu.org 2007-11-28 01:20:46 UTC
Subject: Bug 34001

Author: hjl
Date: Wed Nov 28 01:20:34 2007
New Revision: 130488

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=130488
Log:
2007-11-27  H.J. Lu  <hongjiu.lu@intel.com>
	    Joey Ye <joey.ye@intel.com>

	PR target/34001
	* config/i386/i386.c (function_arg_32): Don't pass aggregate
	arguments in ECX/EDX for fastcall.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/i386/i386.c

Comment 9 H.J. Lu 2007-11-28 01:25:32 UTC
Fixed in gcc 4.3.