OSDN Git Service

2002-11-10 Ranjit Mathew <rmathew@hotmail.com>
authorgreen <green@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 6 Dec 2002 01:16:45 +0000 (01:16 +0000)
committergreen <green@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 6 Dec 2002 01:16:45 +0000 (01:16 +0000)
* include/ffi.h.in: Added FFI_STDCALL ffi_type
  enumeration for X86_WIN32.
* src/x86/win32.S: Added ffi_call_STDCALL function
  definition.
* src/x86/ffi.c (ffi_call/ffi_raw_call): Added
  switch cases for recognising FFI_STDCALL and
  calling ffi_call_STDCALL if target is X86_WIN32.
* src/ffitest.c (my_stdcall_strlen/stdcall_many):
  stdcall versions of the "my_strlen" and "many"
  test functions (for X86_WIN32).
  Added test cases to test stdcall invocation using
  these functions.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@59878 138bc75d-0d04-0410-961f-82ee72b054a4

libffi/ChangeLog
libffi/include/ffi.h.in
libffi/src/ffitest.c
libffi/src/x86/ffi.c
libffi/src/x86/win32.S

index 423c4b0..8ed3398 100644 (file)
@@ -1,3 +1,18 @@
+2002-11-10  Ranjit Mathew <rmathew@hotmail.com>
+
+       * include/ffi.h.in: Added FFI_STDCALL ffi_type
+         enumeration for X86_WIN32.
+       * src/x86/win32.S: Added ffi_call_STDCALL function
+         definition.
+       * src/x86/ffi.c (ffi_call/ffi_raw_call): Added
+         switch cases for recognising FFI_STDCALL and
+         calling ffi_call_STDCALL if target is X86_WIN32.
+       * src/ffitest.c (my_stdcall_strlen/stdcall_many):
+         stdcall versions of the "my_strlen" and "many"
+         test functions (for X86_WIN32).
+         Added test cases to test stdcall invocation using
+         these functions.
+
 2002-11-27  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * src/s390/sysv.S (.eh_frame section): Make section read-only.
index 4f7667e..c660ede 100644 (file)
@@ -198,6 +198,8 @@ typedef enum ffi_abi {
   /* ---- Intel x86 Win32 ---------- */
 #ifdef X86_WIN32
   FFI_SYSV,
+  FFI_STDCALL,
+  /* TODO: Add fastcall support for the sake of completeness */
   FFI_DEFAULT_ABI = FFI_SYSV,
 #endif
 
@@ -287,7 +289,7 @@ typedef struct _ffi_type
   /*@null@*/ struct _ffi_type **elements;
 } ffi_type;
 
-/* These are defined in ffi.c */
+/* These are defined in types.c */
 extern ffi_type ffi_type_void;
 extern ffi_type ffi_type_uint8;
 extern ffi_type ffi_type_sint8;
index 163c4a8..da52831 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   ffitest.c - Copyright (c) 1996, 1997, 1998  Cygnus Solutions
+   ffitest.c - Copyright (c) 1996, 1997, 1998, 2002  Red Hat, Inc.
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -49,6 +49,13 @@ static size_t my_strlen(char *s)
   return (strlen(s));
 }
 
+#ifdef X86_WIN32
+static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
+{
+  return (strlen(s));
+}
+#endif /* X86_WIN32 */
+
 static int promotion(signed char sc, signed short ss, 
                     unsigned char uc, unsigned short us)
 {
@@ -112,6 +119,25 @@ static float many(float f1,
   return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
 }
 
+#ifdef X86_WIN32
+static float __attribute__((stdcall)) stdcall_many(float f1,
+                                                  float f2,
+                                                  float f3,
+                                                  float f4,
+                                                  float f5,
+                                                  float f6,
+                                                  float f7,
+                                                  float f8,
+                                                  float f9,
+                                                  float f10,
+                                                  float f11,
+                                                  float f12,
+                                                  float f13)
+{
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+#endif /* X86_WIN32 */
+
 static double dblit(float f)
 {
   return f/3.0;
@@ -954,6 +980,67 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
   printf("Structure passing doesn't work on Win32.\n");
 #endif /* X86_WIN32 */
 
+#ifdef X86_WIN32
+  /* stdcall strlen tests */
+  {
+    args[0] = &ffi_type_pointer;
+    values[0] = (void*) &s;
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 1,
+                      &ffi_type_sint, args) == FFI_OK);
+
+    s = "a";
+    ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+    CHECK(rint == 1);
+
+    s = "1234567";
+    ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+    CHECK(rint == 7);
+
+    s = "1234567890123456789012345";
+    ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+    CHECK(rint == 25);
+
+    printf("stdcall strlen tests passed\n");
+  }
+
+  /* stdcall many arg tests */
+  {
+    float ff;
+    float fa[13];
+
+    for (ul = 0; ul < 13; ul++)
+      {
+       args[ul] = &ffi_type_float;
+       values[ul] = &fa[ul];
+       fa[ul] = (float) ul;
+      }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 13,
+                      &ffi_type_float, args) == FFI_OK);
+
+    /*@-usedef@*/
+    ff =  stdcall_many(fa[0], fa[1],
+              fa[2], fa[3],
+              fa[4], fa[5],
+              fa[6], fa[7],
+              fa[8], fa[9],
+              fa[10],fa[11],fa[12]);
+    /*@=usedef@*/
+
+    ffi_call(&cif, FFI_FN(stdcall_many), &f, values);
+
+    /*@-realcompare@*/
+    if (f - ff < FLT_EPSILON)
+    /*@=realcompare@*/
+       printf("stdcall many arg tests ok!\n");
+    else
+        CHECK(0);
+  }
+#endif /* X86_WIN32 */
+
 # if FFI_CLOSURES
   /* A simple closure test */
     {
index 7719325..68135f9 100644 (file)
@@ -1,5 +1,8 @@
 /* -----------------------------------------------------------------------
-   ffi.c - Copyright (c) 1996, 1998, 1999  Cygnus Solutions
+   ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
+           Copyright (c) 2002  Ranjit Mathew
+           Copyright (c) 2002  Bo Thorsen
+           Copyright (c) 2002  Roger Sayle
    
    x86 Foreign Function Interface 
 
@@ -148,6 +151,18 @@ extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
 /*@=declundef@*/
 /*@=exportheader@*/
 
+#ifdef X86_WIN32
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_STDCALL(void (*)(char *, extended_cif *),
+                         /*@out@*/ extended_cif *,
+                         unsigned, unsigned,
+                         /*@out@*/ unsigned *,
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+#endif /* X86_WIN32 */
+
 void ffi_call(/*@dependent@*/ ffi_cif *cif, 
              void (*fn)(), 
              /*@out@*/ void *rvalue, 
@@ -180,6 +195,14 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
                    cif->flags, ecif.rvalue, fn);
       /*@=usedef@*/
       break;
+#ifdef X86_WIN32
+    case FFI_STDCALL:
+      /*@-usedef@*/
+      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#endif /* X86_WIN32 */
     default:
       FFI_ASSERT(0);
       break;
@@ -448,6 +471,15 @@ ffi_call_SYSV(void (*)(char *, extended_cif *),
              /*@out@*/ unsigned *, 
              void (*fn)());
 
+#ifdef X86_WIN32
+extern void
+ffi_call_STDCALL(void (*)(char *, extended_cif *),
+             /*@out@*/ extended_cif *,
+             unsigned, unsigned,
+             /*@out@*/ unsigned *,
+             void (*fn)());
+#endif /* X86_WIN32 */
+
 void
 ffi_raw_call(/*@dependent@*/ ffi_cif *cif, 
             void (*fn)(), 
@@ -482,6 +514,14 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
                    cif->flags, ecif.rvalue, fn);
       /*@=usedef@*/
       break;
+#ifdef X86_WIN32
+    case FFI_STDCALL:
+      /*@-usedef@*/
+      ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#endif /* X86_WIN32 */
     default:
       FFI_ASSERT(0);
       break;
index 520d1fc..796af18 100644 (file)
@@ -1,5 +1,8 @@
 /* -----------------------------------------------------------------------
-   win32.S - Copyright (c) 1996, 1998, 2001  Cygnus Solutions
+   win32.S - Copyright (c) 1996, 1998, 2001, 2002  Red Hat, Inc.
+            Copyright (c) 2001  John Beniton
+            Copyright (c) 2002  Ranjit Mathew
+                       
  
    X86 Foreign Function Interface
  
@@ -52,7 +55,10 @@ _ffi_call_SYSV:
         # Return stack to previous state and call the function
         addl  $8,%esp
  
-        call  *28(%ebp)
+        # FIXME: Align the stack to a 128-bit boundary to avoid
+        # potential performance hits.
+
+       call  *28(%ebp)
  
         # Remove the space we pushed for the args
         movl  16(%ebp),%ecx
@@ -123,3 +129,98 @@ epilogue:
         ret
  
 .ffi_call_SYSV_end:
+
+        # This assumes we are using gas.
+        .balign 16
+.globl _ffi_call_STDCALL
+
+_ffi_call_STDCALL:
+        pushl %ebp
+        movl  %esp,%ebp
+
+        # Make room for all of the new args.
+        movl  16(%ebp),%ecx 
+        subl  %ecx,%esp
+
+        movl  %esp,%eax
+
+        # Place all of the ffi_prep_args in position
+        pushl 12(%ebp)
+        pushl %eax
+        call  *8(%ebp)
+
+        # Return stack to previous state and call the function
+        addl  $8,%esp
+
+        # FIXME: Align the stack to a 128-bit boundary to avoid
+        # potential performance hits.
+
+        call  *28(%ebp)
+
+        # stdcall functions pop arguments off the stack themselves
+
+        # Load %ecx with the return type code
+        movl  20(%ebp),%ecx
+
+        # If the return value pointer is NULL, assume no return value.
+        cmpl  $0,24(%ebp)
+        jne   sc_retint
+
+        # Even if there is no space for the return value, we are
+        # obliged to handle floating-point values.
+        cmpl  $FFI_TYPE_FLOAT,%ecx
+        jne   sc_noretval
+        fstp  %st(0)
+
+        jmp   sc_epilogue
+
+sc_retint:
+        cmpl  $FFI_TYPE_INT,%ecx
+        jne   sc_retfloat
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        jmp   sc_epilogue
+
+sc_retfloat:
+        cmpl  $FFI_TYPE_FLOAT,%ecx
+        jne   sc_retdouble
+         # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstps (%ecx)
+        jmp   sc_epilogue
+
+sc_retdouble:
+        cmpl  $FFI_TYPE_DOUBLE,%ecx
+        jne   sc_retlongdouble
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstpl (%ecx)
+        jmp   sc_epilogue
+
+sc_retlongdouble:
+        cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
+        jne   sc_retint64
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstpt (%ecx)
+        jmp   sc_epilogue
+
+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!
+
+sc_noretval:
+sc_epilogue:
+        movl %ebp,%esp
+        popl %ebp
+        ret
+
+.ffi_call_STDCALL_end: