This is the mail archive of the gcc-patches@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]

RE: PATCH: PR target/34001: Incorrect x86 fastcall behavior


HJ,

You patch has a minor problem that fastcall will pass non-scalar integer parameter in EAX/ECX/EDX, which is still imcompatible to MS fastcall. MSVC pass parameter on stack unless it is scalar integer less equal to 32 bits.

With this patch GCC fastcall passes first parameter in EAX when it is not a scalar integer less equal to 32 bits. Check following example and review the patch fixing it:

#define MAGIC 123
typedef struct {
char c1, c2;
} a_type;

int
#ifdef _GNU_C_
__attribute__ ((fastcall))
#else
__fastcall
#endif
foo(a_type a, int b, int c, int d)
{
        return a.c1 + b + c + d;
}

int main()
{
        a_type a;
        a.c1=MAGIC;
        return foo(a,0,1,2) == MAGIC + 1 ? 0 : 1;
}


MSVC 6 and 7:
@foo@16:
  00000000: 55              push      ebp
  00000001: 8B EC           mov       ebp,esp
  00000003: 83 EC 08        sub       esp,8
  00000006: 89 55 F8        mov       dword ptr [ebp-8],edx   ;arg3 in edx
  00000009: 89 4D FC        mov       dword ptr [ebp-4],ecx   ;arg2 in ecx
  0000000C: 0F BE 45 08     movsx     eax,byte ptr [ebp+8]   ;arg1 in stack
  00000010: 03 45 FC        add       eax,dword ptr [ebp-4]
  00000013: 03 45 F8        add       eax,dword ptr [ebp-8]
  00000016: 03 45 0C        add       eax,dword ptr [ebp+0Ch] ;arg4 in stack
  00000019: 8B E5           mov       esp,ebp
  0000001B: 5D              pop       ebp
  0000001C: C2 08 00        ret       8
_main:
  0000001F: 55              push      ebp
  00000020: 8B EC           mov       ebp,esp
  00000022: 51              push      ecx
  00000023: C6 45 FC 7B     mov       byte ptr [ebp-4],7Bh
  00000027: 6A 02           push      2                    ;param4 in stack
  00000029: BA 01 00 00 00  mov       edx,1                ;param3 in edx
  0000002E: 33 C9           xor       ecx,ecx              ;param2 in ecx
  00000030: 66 8B 45 FC     mov       ax,word ptr [ebp-4]  ;param1 in eax
  00000034: 50              push      eax
  00000035: E8 00 00 00 00  call      0000003A
  0000003A: 33 C9           xor       ecx,ecx
  0000003C: 83 F8 7C        cmp       eax,7Ch
  0000003F: 0F 95 C1        setne     cl
  00000042: 8B C1           mov       eax,ecx
  00000044: 8B E5           mov       esp,ebp
  00000046: 5D              pop       ebp
  00000047: C3              ret
 
GCC 4.3 with your fastcall patch: 
        .file   "f.c"
        .text
.globl foo
        .type   foo, @function
foo:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        movw    %ax, -2(%ebp)  ;arg1 in eax
        movl    %edx, -8(%ebp) ;arg2 in edx
        movzbl  -2(%ebp), %eax
        movsbl  %al,%eax
        addl    -8(%ebp), %eax
        addl    8(%ebp), %eax  ;arg3 in stack
        addl    12(%ebp), %eax ;arg4 in stack
        leave
        ret     $8
        .size   foo, .-foo
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $24, %esp
        movb    $123, -6(%ebp)
        movzwl  -6(%ebp), %eax ; param1 in eax
        movl    $2, 4(%esp)    ; param4 in stack
        movl    $1, (%esp)     ; param3 in stack
        movl    $0, %edx       ; param2 in edx
        call    foo
        subl    $8, %esp
        cmpl    $124, %eax
        setne   %al
        movzbl  %al, %eax
        movl    -4(%ebp), %ecx
        leave
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.3.0 20071104 (experimental) [trunk revision 129880]"
        .section        .note.GNU-stack,"",@progbits


Here is a patch to fix it:
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c      (revision 129880)
+++ gcc/config/i386/i386.c      (working copy)
@@ -4229,9 +4229,12 @@
          int regno = cum->regno;

          /* Fastcall allocates the first two DWORD (SImode) or
-            smaller arguments to ECX and EDX.  */
+            smaller arguments to ECX and EDX if it isn't an
+            aggregate type .  */
          if (cum->fastcall)
            {
+             if (type && AGGREGATE_TYPE_P (type))
+               break;
              if (mode == BLKmode || mode == DImode)
                break;
  
With this patch generated code will be:
        .file   "f.c"
        .text
.globl foo
        .type   foo, @function
foo:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $4, %esp
        movl    %edx, -4(%ebp)
        movzbl  8(%ebp), %eax
        movsbl  %al,%eax
        addl    -4(%ebp), %eax
        addl    12(%ebp), %eax
        addl    16(%ebp), %eax
        leave
        ret     $12
        .size   foo, .-foo
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $28, %esp
        movb    $123, -6(%ebp)
        movl    $2, 8(%esp)
        movl    $1, 4(%esp)
        movzwl  -6(%ebp), %eax
        movw    %ax, (%esp)
        movl    $0, %edx
        call    foo
        subl    $12, %esp
        cmpl    $124, %eax
        setne   %al
        movzbl  %al, %eax
        movl    -4(%ebp), %ecx
        leave
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.3.0 20071104 (experimental) [trunk revision 129880]"
        .section        .note.GNU-stack,"",@progbits

Thanks - Joey

-----Original Message-----
From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-owner@gcc.gnu.org] On Behalf Of H.J. Lu
Sent: 2007年11月10日 1:01
To: gcc-patches@gcc.gnu.org
Cc: jh@suse.cz; ubizjak@gmail.com
Subject: PATCH: PR target/34001: Incorrect x86 fastcall behavior

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.



H.J.
---
2007-11-09  H.J. Lu  <hongjiu.lu@intel.com>

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

--- gcc/config/i386/i386.c.fastcall     2007-11-06 19:52:12.000000000 -0800
+++ gcc/config/i386/i386.c      2007-11-08 11:48:38.000000000 -0800
@@ -4233,8 +4233,10 @@ function_arg_32 (CUMULATIVE_ARGS *cum, e
          int regno = cum->regno;

          /* Fastcall allocates the first two DWORD (SImode) or
-            smaller arguments to ECX and EDX.  */
-         if (cum->fastcall)
+            smaller arguments to ECX and EDX if it isn't an
+            aggregate type .  */
+         if (cum->fastcall
+             && (!type || !AGGREGATE_TYPE_P (type)))
            {
              if (mode == BLKmode || mode == DImode)
                break;


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