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]

[PATCH] libffi: x86 win32 fix


Hi

Here is a patch for libffi.
On x86 win32 platform, libffi testsuite fails some test cases.
There is three causes;

 - wrong structure alignment size of double and 64-bits integer.

 - when returning structure and size of structure is 1, 2, 4, or
   8-bytes, return value is pass by register instead of hidden first
   argument for pointer to return value storage.

 - test case libffi.call/many_win32.c couldn't compile.
   It needs to include <float.h> but missing, and variable `ul' is
   undefined.

Attached file libffi-win32.patch is a patch to fix these problems.
struct_align.tar.gz is some test cases to check structure alignment.

I tested this patch on i686-pc-cygwin and i686-pc-linux-gnu


2003-12-04  Hosaka Yuji  <hos@tamanegi.org>

	* src/types.c: Fix alignment size of X86_WIN32 case int64 and
	double.
	* src/x86/ffi.c (ffi_prep_args): Replace ecif->cif->rtype->type
	with ecif->cif->flags.
	(ffi_call, ffi_prep_incoming_args_SYSV): Replace cif->rtype->type
	with cif->flags.
	(ffi_prep_cif_machdep): Add X86_WIN32 struct case.
	(ffi_closure_SYSV): Add 1 or 2-bytes struct case for X86_WIN32.
	* src/x86/win32.S (retstruct1b, retstruct2b, sc_retstruct1b,
	sc_retstruct2b): Add for 1 or 2-bytes struct case.
	* testsuite/libffi.call/many_win32.c: include <float.h>.
	* testsuite/libffi.call/many_win32.c (main): Replace variable
	int i with unsigned long ul.

	* testsuite/libffi.call/cls_align_uint64.c: Check uint64 align.
	* testsuite/libffi.call/cls_align_sint64.c: Check sint64 align.
	* testsuite/libffi.call/cls_align_uint32.c: Check uint32 align.
	* testsuite/libffi.call/cls_align_sint32.c: Check sint32 align.
	* testsuite/libffi.call/cls_align_uint16.c: Check uint16 align.
	* testsuite/libffi.call/cls_align_sint16.c: Check sint16 align.
	* testsuite/libffi.call/cls_align_float.c: Check float align.
	* testsuite/libffi.call/cls_align_double.c: Check float align.
	* testsuite/libffi.call/cls_align_longdouble.c: Check long double
	align.
	* testsuite/libffi.call/cls_align_pointer.c: Check pointer align.

-- 
hosaka
Index: src/types.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libffi/src/types.c,v
retrieving revision 1.12
diff -c -3 -r1.12 types.c
*** src/types.c	21 Oct 2003 19:01:54 -0000	1.12
--- src/types.c	3 Dec 2003 16:44:18 -0000
***************
*** 53,59 ****
  
  #endif
  
! #if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
  
  FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
  FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
--- 53,59 ----
  
  #endif
  
! #if defined X86 || defined ARM || defined M68K
  
  FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
  FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
***************
*** 73,79 ****
--- 73,83 ----
  
  #if defined X86 || defined X86_WIN32 || defined M68K
  
+ #ifdef X86_WIN32
+ FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+ #else
  FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+ #endif
  FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
  
  #elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
Index: src/x86/ffi.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libffi/src/x86/ffi.c,v
retrieving revision 1.11
diff -c -3 -r1.11 ffi.c
*** src/x86/ffi.c	2 Dec 2003 05:39:06 -0000	1.11
--- src/x86/ffi.c	3 Dec 2003 16:44:19 -0000
***************
*** 47,53 ****
  
    argp = stack;
  
!   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
      {
        *(void **) argp = ecif->rvalue;
        argp += 4;
--- 47,53 ----
  
    argp = stack;
  
!   if (ecif->cif->flags == FFI_TYPE_STRUCT)
      {
        *(void **) argp = ecif->rvalue;
        argp += 4;
***************
*** 121,127 ****
--- 121,129 ----
    switch (cif->rtype->type)
      {
      case FFI_TYPE_VOID:
+ #ifndef X86_WIN32
      case FFI_TYPE_STRUCT:
+ #endif
      case FFI_TYPE_SINT64:
      case FFI_TYPE_FLOAT:
      case FFI_TYPE_DOUBLE:
***************
*** 133,138 ****
--- 135,165 ----
        cif->flags = FFI_TYPE_SINT64;
        break;
  
+ #ifdef X86_WIN32
+     case FFI_TYPE_STRUCT:
+       if (cif->rtype->size == 1)
+         {
+           cif->flags = FFI_TYPE_SINT8; /* same as char size */
+         }
+       else if (cif->rtype->size == 2)
+         {
+           cif->flags = FFI_TYPE_SINT16; /* same as short size */
+         }
+       else if (cif->rtype->size == 4)
+         {
+           cif->flags = FFI_TYPE_INT; /* same as int type */
+         }
+       else if (cif->rtype->size == 8)
+         {
+           cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
+         }
+       else
+         {
+           cif->flags = FFI_TYPE_STRUCT;
+         }
+       break;
+ #endif
+ 
      default:
        cif->flags = FFI_TYPE_INT;
        break;
***************
*** 177,183 ****
    /* value address then we need to make one		        */
  
    if ((rvalue == NULL) && 
!       (cif->rtype->type == FFI_TYPE_STRUCT))
      {
        /*@-sysunrecog@*/
        ecif.rvalue = alloca(cif->rtype->size);
--- 204,210 ----
    /* value address then we need to make one		        */
  
    if ((rvalue == NULL) && 
!       (cif->flags == FFI_TYPE_STRUCT))
      {
        /*@-sysunrecog@*/
        ecif.rvalue = alloca(cif->rtype->size);
***************
*** 274,279 ****
--- 301,316 ----
  	   : : "r"(resp)
  	   : "eax", "edx");
      }
+ #ifdef X86_WIN32
+   else if (rtype == FFI_TYPE_SINT8) /* 1-byte struct  */
+     {
+       asm ("movsbl (%0),%%eax" : : "r" (resp) : "eax");
+     }
+   else if (rtype == FFI_TYPE_SINT16) /* 2-bytes struct */
+     {
+       asm ("movswl (%0),%%eax" : : "r" (resp) : "eax");
+     }
+ #endif
  }
  
  /*@-exportheader@*/
***************
*** 289,295 ****
  
    argp = stack;
  
!   if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
      *rvalue = *(void **) argp;
      argp += 4;
    }
--- 326,332 ----
  
    argp = stack;
  
!   if ( cif->flags == FFI_TYPE_STRUCT ) {
      *rvalue = *(void **) argp;
      argp += 4;
    }
Index: src/x86/win32.S
===================================================================
RCS file: /cvsroot/gcc/gcc/libffi/src/x86/win32.S,v
retrieving revision 1.4
diff -c -3 -r1.4 win32.S
*** src/x86/win32.S	21 Oct 2003 19:01:58 -0000	1.4
--- src/x86/win32.S	3 Dec 2003 16:44:19 -0000
***************
*** 114,125 ****
   
  retint64:
          cmpl  $FFI_TYPE_SINT64,%ecx
!         jne   retstruct
          # Load %ecx with the pointer to storage for the return value
          movl  24(%ebp),%ecx
          movl  %eax,0(%ecx)
          movl  %edx,4(%ecx)
   
  retstruct:
          # Nothing to do!
   
--- 114,141 ----
   
  retint64:
          cmpl  $FFI_TYPE_SINT64,%ecx
!         jne   retstruct1b
          # Load %ecx with the pointer to storage for the return value
          movl  24(%ebp),%ecx
          movl  %eax,0(%ecx)
          movl  %edx,4(%ecx)
   
+ retstruct1b:
+         cmpl  $FFI_TYPE_SINT8,%ecx
+         jne   retstruct2b
+         # Load %ecx with the pointer to storage for the return value
+         movl  24(%ebp),%ecx
+         movb  %al,0(%ecx)
+         jmp   epilogue
+  
+ retstruct2b:
+         cmpl  $FFI_TYPE_SINT16,%ecx
+         jne   retstruct
+         # Load %ecx with the pointer to storage for the return value
+         movl  24(%ebp),%ecx
+         movw  %ax,0(%ecx)
+         jmp   epilogue
+  
  retstruct:
          # Nothing to do!
   
***************
*** 209,219 ****
  
  sc_retint64:
          cmpl  $FFI_TYPE_SINT64,%ecx
!         jne   sc_retstruct
          # Load %ecx with the pointer to storage for the return value
          movl  24(%ebp),%ecx
          movl  %eax,0(%ecx)
          movl  %edx,4(%ecx)
  
  sc_retstruct:
          # Nothing to do!
--- 225,251 ----
  
  sc_retint64:
          cmpl  $FFI_TYPE_SINT64,%ecx
!         jne   sc_retstruct1b
          # Load %ecx with the pointer to storage for the return value
          movl  24(%ebp),%ecx
          movl  %eax,0(%ecx)
          movl  %edx,4(%ecx)
+ 
+ sc_retstruct1b:
+         cmpl  $FFI_TYPE_SINT8,%ecx
+         jne   sc_retstruct2b
+         # Load %ecx with the pointer to storage for the return value
+         movl  24(%ebp),%ecx
+         movb  %al,0(%ecx)
+         jmp   sc_epilogue
+ 
+ sc_retstruct2b:
+         cmpl  $FFI_TYPE_SINT16,%ecx
+         jne   sc_retstruct
+         # Load %ecx with the pointer to storage for the return value
+         movl  24(%ebp),%ecx
+         movw  %ax,0(%ecx)
+         jmp   sc_epilogue
  
  sc_retstruct:
          # Nothing to do!
Index: testsuite/libffi.call/many_win32.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libffi/testsuite/libffi.call/many_win32.c,v
retrieving revision 1.1
diff -c -3 -r1.1 many_win32.c
*** testsuite/libffi.call/many_win32.c	4 Sep 2003 14:47:48 -0000	1.1
--- testsuite/libffi.call/many_win32.c	3 Dec 2003 16:44:19 -0000
***************
*** 7,12 ****
--- 7,13 ----
  /* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
  
  #include "ffitest.h"
+ #include <float.h>
  
  static float __attribute__((stdcall)) stdcall_many(float f1,
  						   float f2,
***************
*** 32,38 ****
    void *values[13];
    float fa[13];
    float f, ff;
!   int i;
    
    for (ul = 0; ul < 13; ul++)
      {
--- 33,39 ----
    void *values[13];
    float fa[13];
    float f, ff;
!   unsigned long ul;
    
    for (ul = 0; ul < 13; ul++)
      {

Attachment: struct_align.tar.gz
Description: GNU Zip compressed data


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