public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
* Re: [patch] port libffi to x86/msvc
       [not found] <1961299951.120059.1263581161934.JavaMail.root@cm-mail03.mozilla.org>
@ 2010-01-15 18:46 ` Dan Witte
  2010-02-23 17:36   ` Mladen Turk
  0 siblings, 1 reply; 12+ messages in thread
From: Dan Witte @ 2010-01-15 18:46 UTC (permalink / raw)
  To: libffi-discuss

[-- Attachment #1: Type: text/plain, Size: 901 bytes --]

> Thanks Dan -- I've checked this in.  I've also add the cc.sh script 
> (renamed it to msvcc.sh), and updated the README file explaining to
> use 
> it.  It would be great if you could double check my work.

Awesome, thanks! Checked the diff and it looks good. For the wrapper script, a couple things:

diff --git a/README b/README
+path/to/configure --enable-shared --enable-static \
+	CC=path/to/msvcc.sh LD=link \
+	CPP=\"cl -nologo -EP\"

The '--enable-shared --enable-static' aren't necessary, I just happened to use them, so you may want to change that.

Secondly, I put cc.sh under a Mozilla tri-license, because, well, that's what we use 'round here, and Timothy said any license is fine. But if you'd prefer it under a BSD license for consistency, I don't mind.

Finally, I made a mistake in the testsuite patch I sent. So if you were going to apply it, better use this one. :)

Thanks,
Dan.

[-- Attachment #2: libffi-part4-msvc-testsuite-2.diff --]
[-- Type: text/x-patch, Size: 5414 bytes --]

2010-01-14  Daniel Witte  <dwitte@mozilla.com>
  * testsuite/libffi.call/: Fix various tests to work with MSVC on X86_WIN32.

diff --git a/libffi/ChangeLog b/libffi/ChangeLog
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,8 +1,11 @@
+2010-01-14  Daniel Witte  <dwitte@mozilla.com>
+  * testsuite/libffi.call/: Fix various tests to work with MSVC on X86_WIN32.
+
 2010-01-12  Daniel Witte  <dwitte@mozilla.com>
   * src/x86/win32.S: Port assembly routines to MSVC and #ifdef.
   * src/x86/ffi.c: Tweak function declaration and remove excess parens.
   * include/ffi.h.in: Add __declspec(align(8)) to typedef struct ffi_closure.
 
 2010-01-12  Daniel Witte  <dwitte@mozilla.com>
   * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new
   function ffi_call_win32 on X86_WIN32.
diff --git a/libffi/testsuite/libffi.call/closure_stdcall.c b/libffi/testsuite/libffi.call/closure_stdcall.c
--- a/libffi/testsuite/libffi.call/closure_stdcall.c
+++ b/libffi/testsuite/libffi.call/closure_stdcall.c
@@ -18,17 +18,17 @@ closure_test_stdcall(ffi_cif* cif __UNUS
 
   printf("%d %d %d %d: %d\n",
 	 (int)*(int *)args[0], (int)(*(int *)args[1]),
 	 (int)(*(int *)args[2]), (int)(*(int *)args[3]),
          (int)*(ffi_arg *)resp);
 
 }
 
-typedef int (__stdcall *closure_test_type0)(int, int, int, int);
+typedef int (__STDCALL__ *closure_test_type0)(int, int, int, int);
 
 int main (void)
 {
   ffi_cif cif;
   void *code;
   ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
   ffi_type * cl_arg_types[17];
   int res;
@@ -44,19 +44,27 @@ int main (void)
 
   /* Initialize the cif */
   CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 4,
 		     &ffi_type_sint, cl_arg_types) == FFI_OK);
 
   CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_stdcall,
                              (void *) 3 /* userdata */, code) == FFI_OK);
 
+#if defined(__GNUC__)
   asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
   res = (*(closure_test_type0)code)(0, 1, 2, 3);
   asm volatile (" movl %%esp,%0" : "=g" (sp_post));
+#elif defined (_MSC_VER)
+  __asm { mov sp_pre, esp }
+  res = (*(closure_test_type0)code)(0, 1, 2, 3);
+  __asm { mov sp_post, esp }
+#else
+#error "Unknown compiler!"
+#endif
   /* { dg-output "0 1 2 3: 9" } */
 
   printf("res: %d\n",res);
   /* { dg-output "\nres: 9" } */
 
   sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
   printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
   /* { dg-output "\nstack pointer match" } */
diff --git a/libffi/testsuite/libffi.call/ffitest.h b/libffi/testsuite/libffi.call/ffitest.h
--- a/libffi/testsuite/libffi.call/ffitest.h
+++ b/libffi/testsuite/libffi.call/ffitest.h
@@ -20,16 +20,26 @@
 /* Define __UNUSED__ that also other compilers than gcc can run the tests.  */
 #undef __UNUSED__
 #if defined(__GNUC__)
 #define __UNUSED__ __attribute__((__unused__))
 #else
 #define __UNUSED__
 #endif
 
+/* Define __STDCALL__ for various compilers.  */
+#undef __STDCALL__
+#if defined(__GNUC__)
+#define __STDCALL__ __attribute__((stdcall))
+#elif defined (_MSC_VER)
+#define __STDCALL__ __stdcall
+#else
+#define __STDCALL__
+#endif
+
 /* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
    file open.  */
 #ifdef HAVE_MMAP_ANON
 # undef HAVE_MMAP_DEV_ZERO
 
 # include <sys/mman.h>
 # ifndef MAP_FAILED
 #  define MAP_FAILED -1
diff --git a/libffi/testsuite/libffi.call/many_win32.c b/libffi/testsuite/libffi.call/many_win32.c
--- a/libffi/testsuite/libffi.call/many_win32.c
+++ b/libffi/testsuite/libffi.call/many_win32.c
@@ -4,29 +4,29 @@
    PR:		none.
    Originator:	From the original ffitest.c  */
 
 /* { 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,
-						   float f3,
-						   float f4,
-						   float f5,
-						   float f6,
-						   float f7,
-						   float f8,
-						   float f9,
-						   float f10,
-						   float f11,
-						   float f12,
-						   float f13)
+static float __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);
 }
 
 int main (void)
 {
   ffi_cif cif;
   ffi_type *args[13];
diff --git a/libffi/testsuite/libffi.call/strlen_win32.c b/libffi/testsuite/libffi.call/strlen_win32.c
--- a/libffi/testsuite/libffi.call/strlen_win32.c
+++ b/libffi/testsuite/libffi.call/strlen_win32.c
@@ -3,17 +3,17 @@
    Limitations:	none.
    PR:		none.
    Originator:	From the original ffitest.c  */
 
 /* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
 
 #include "ffitest.h"
 
-static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
+static size_t __STDCALL__ my_stdcall_strlen(char *s)
 {
   return (strlen(s));
 }
 
 int main (void)
 {
   ffi_cif cif;
   ffi_type *args[MAX_ARGS];

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-01-15 18:46 ` [patch] port libffi to x86/msvc Dan Witte
@ 2010-02-23 17:36   ` Mladen Turk
  2010-02-23 22:33     ` Dan Witte
  0 siblings, 1 reply; 12+ messages in thread
From: Mladen Turk @ 2010-02-23 17:36 UTC (permalink / raw)
  To: libffi-discuss

On 01/15/2010 07:46 PM, Dan Witte wrote:
 >> Thanks Dan -- I've checked this in.  I've also add the cc.sh script
 >
 > The '--enable-shared --enable-static' aren't necessary, I just happened to use them, so you may want to change that.
 >

Just tried the build and the msvcc.sh breaks by the backslash chars,
so additional backslashes are needed since they are unescaped once
during eval and second time durig actual shell exec.
This ends up with cl failing with 'cannot find srcdebug.c'
which is actually src\debug.c unescaped.

diff --git a/msvcc.sh b/msvcc.sh
index 8301839..d841a3e 100755
--- a/msvcc.sh
+++ b/msvcc.sh
@@ -176,6 +176,7 @@ if [ -n "$assembly" ]; then
      #mv *.obj $outdir
  else
      args="$md $args"
+    args="$(echo $args | sed 's%\\%\\\\\\\\%g')"
      echo "$cl $args"
      eval "\"$cl\" $args"
      result=$?


Finally, the produced libffi-5.dll doesn't have any exported
symbols so it's basically unusable.
IMHO the real msvc makefile would be needed and all
externs should be LIBFFI_DECLARE(type)

eg.

#ifdef(WIN32)
#define  LIBFFI_DECLARE(type)      __declspec(dllexport) type __stdcall
#define  LIBFFI_DECLARE_DATA       __declspec(dllexport)
#else
#define  LIBFFI_DECLARE(type)      __attribute__ ((visibility("default")) type
#define  LIBFFI_DECLARE_DATA       extern
#endif

... or something like that

and then

LIBFFI_DECLARE_DATA ffi_type ffi_type_void;
...
LIBFFI_DECLARE(void) ffi_raw_call ...

etc.

Without dllexport there is not much sense creating dll or windows build
using msvc thought.

 > Secondly, I put cc.sh under a Mozilla tri-license, because, well, that's what we use 'round here, and Timothy said any license is fine. But if you'd prefer it under a BSD license for consistency, I don't mind.
 >

Shouldn't that match the LICENSE file?
IMHO mixing licenses in the same package might be confusing.


Regards
-- 
^TM

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-02-23 17:36   ` Mladen Turk
@ 2010-02-23 22:33     ` Dan Witte
  2010-02-24 15:53       ` Anthony Green
  0 siblings, 1 reply; 12+ messages in thread
From: Dan Witte @ 2010-02-23 22:33 UTC (permalink / raw)
  To: Mladen Turk; +Cc: libffi-discuss

----- "Mladen Turk" <mturk@redhat.com> wrote:

>  > Secondly, I put cc.sh under a Mozilla tri-license, because, well,
> that's what we use 'round here, and Timothy said any license is fine.
> But if you'd prefer it under a BSD license for consistency, I don't
> mind.
>  >
> 
> Shouldn't that match the LICENSE file?
> IMHO mixing licenses in the same package might be confusing.

I'm fine with that, feel free to relicense. :)

Dan.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-02-23 22:33     ` Dan Witte
@ 2010-02-24 15:53       ` Anthony Green
  0 siblings, 0 replies; 12+ messages in thread
From: Anthony Green @ 2010-02-24 15:53 UTC (permalink / raw)
  To: libffi-discuss

On 02/23/2010 05:33 PM, Dan Witte wrote:
> ----- "Mladen Turk"<mturk@redhat.com>  wrote:
>
>    
>>   >  Secondly, I put cc.sh under a Mozilla tri-license, because, well,
>> that's what we use 'round here, and Timothy said any license is fine.
>> But if you'd prefer it under a BSD license for consistency, I don't
>> mind.
>>   >
>>
>> Shouldn't that match the LICENSE file?
>> IMHO mixing licenses in the same package might be confusing.
>>      
> I'm fine with that, feel free to relicense. :)
>
> Dan.
>    
Thanks Dan - I'll make the change.

AG

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-01-13 23:41 ` Dan Witte
  2010-01-14  2:21   ` Timothy Wall
  2010-01-14 17:24   ` Anthony Green
@ 2010-01-15 16:34   ` Anthony Green
  2 siblings, 0 replies; 12+ messages in thread
From: Anthony Green @ 2010-01-15 16:34 UTC (permalink / raw)
  To: Dan Witte; +Cc: libffi-discuss

On 01/13/2010 06:40 PM, Dan Witte wrote:
> I've finished my port of libffi to x86/msvc. There are three patches attached, against 3.0.9. Anthony, if these look okay to you, could you please apply?
>    

Thanks Dan -- I've checked this in.  I've also add the cc.sh script 
(renamed it to msvcc.sh), and updated the README file explaining to use 
it.  It would be great if you could double check my work.

Thanks,

Anthony Green
650 352-3402

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
       [not found] <1233161867.115183.1263521983853.JavaMail.root@cm-mail03.mozilla.org>
@ 2010-01-15  2:20 ` Dan Witte
  0 siblings, 0 replies; 12+ messages in thread
From: Dan Witte @ 2010-01-15  2:20 UTC (permalink / raw)
  To: Anthony Green; +Cc: libffi-discuss

[-- Attachment #1: Type: text/plain, Size: 1038 bytes --]

> On 01/14/2010 12:24 PM, Anthony Green wrote:
> 
> Ignore me.  You did run the testsuite.  I assume that there were no 
> unexpected failures, correct?
> 
> AG

Right - on existing platforms. I've run Mozilla's ffi_call testsuite on i686-pc-linux-gnu, x86_64-unknown-linux-gnu, i686-pc-mingw32 (with MSVC), and i386-apple-darwin9.2.0. It passes on all those. I've run libffi's testsuite on i686-pc-linux-gnu, x86_64-unknown-linux-gnu, and i386-apple-darwin9.2.0. No unexpected failures.

libffi's testsuite will need a patch for i686-pc-mingw32 with MSVC, attached. I didn't have any luck running the testsuite, for lack of getting the dejagnu stuff set up correctly. However, the Mozilla testsuite covers basically the same stuff, including some testing of the closure API. We test ffi_call for SYSV and STDCALL functions thoroughly, including small struct return values. So I'm pretty confident things are working.

I haven't tested i686-pc-mingw32 with gcc. If anyone can help with that, it would be most appreciated. :)

Thanks,
Dan.

[-- Attachment #2: libffi-part4-msvc-testsuite.diff --]
[-- Type: text/x-patch, Size: 5414 bytes --]

2010-01-14  Daniel Witte  <dwitte@mozilla.com>
  * testsuite/libffi.call/: Fix various tests to work with MSVC on X86_WIN32.

diff --git a/libffi/ChangeLog b/libffi/ChangeLog
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,8 +1,11 @@
+2010-01-14  Daniel Witte  <dwitte@mozilla.com>
+  * testsuite/libffi.call/: Fix various tests to work with MSVC on X86_WIN32.
+
 2010-01-12  Daniel Witte  <dwitte@mozilla.com>
   * src/x86/win32.S: Port assembly routines to MSVC and #ifdef.
   * src/x86/ffi.c: Tweak function declaration and remove excess parens.
   * include/ffi.h.in: Add __declspec(align(8)) to typedef struct ffi_closure.
 
 2010-01-12  Daniel Witte  <dwitte@mozilla.com>
   * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new
   function ffi_call_win32 on X86_WIN32.
diff --git a/libffi/testsuite/libffi.call/closure_stdcall.c b/libffi/testsuite/libffi.call/closure_stdcall.c
--- a/libffi/testsuite/libffi.call/closure_stdcall.c
+++ b/libffi/testsuite/libffi.call/closure_stdcall.c
@@ -18,17 +18,17 @@ closure_test_stdcall(ffi_cif* cif __UNUS
 
   printf("%d %d %d %d: %d\n",
 	 (int)*(int *)args[0], (int)(*(int *)args[1]),
 	 (int)(*(int *)args[2]), (int)(*(int *)args[3]),
          (int)*(ffi_arg *)resp);
 
 }
 
-typedef int (__stdcall *closure_test_type0)(int, int, int, int);
+typedef int (FFI_STDCALL *closure_test_type0)(int, int, int, int);
 
 int main (void)
 {
   ffi_cif cif;
   void *code;
   ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
   ffi_type * cl_arg_types[17];
   int res;
@@ -44,19 +44,27 @@ int main (void)
 
   /* Initialize the cif */
   CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 4,
 		     &ffi_type_sint, cl_arg_types) == FFI_OK);
 
   CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_stdcall,
                              (void *) 3 /* userdata */, code) == FFI_OK);
 
+#if defined(__GNUC__)
   asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
   res = (*(closure_test_type0)code)(0, 1, 2, 3);
   asm volatile (" movl %%esp,%0" : "=g" (sp_post));
+#elif defined (_MSC_VER)
+  __asm { mov sp_pre, esp }
+  res = (*(closure_test_type0)code)(0, 1, 2, 3);
+  __asm { mov sp_post, esp }
+#else
+#error "Unknown compiler!"
+#endif
   /* { dg-output "0 1 2 3: 9" } */
 
   printf("res: %d\n",res);
   /* { dg-output "\nres: 9" } */
 
   sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
   printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
   /* { dg-output "\nstack pointer match" } */
diff --git a/libffi/testsuite/libffi.call/ffitest.h b/libffi/testsuite/libffi.call/ffitest.h
--- a/libffi/testsuite/libffi.call/ffitest.h
+++ b/libffi/testsuite/libffi.call/ffitest.h
@@ -20,16 +20,26 @@
 /* Define __UNUSED__ that also other compilers than gcc can run the tests.  */
 #undef __UNUSED__
 #if defined(__GNUC__)
 #define __UNUSED__ __attribute__((__unused__))
 #else
 #define __UNUSED__
 #endif
 
+/* Define FFI_STDCALL for various compilers.  */
+#undef FFI_STDCALL
+#if defined(__GNUC__)
+#define FFI_STDCALL __attribute__((stdcall))
+#elif defined (_MSC_VER)
+#define FFI_STDCALL __stdcall
+#else
+#define FFI_STDCALL
+#endif
+
 /* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
    file open.  */
 #ifdef HAVE_MMAP_ANON
 # undef HAVE_MMAP_DEV_ZERO
 
 # include <sys/mman.h>
 # ifndef MAP_FAILED
 #  define MAP_FAILED -1
diff --git a/libffi/testsuite/libffi.call/many_win32.c b/libffi/testsuite/libffi.call/many_win32.c
--- a/libffi/testsuite/libffi.call/many_win32.c
+++ b/libffi/testsuite/libffi.call/many_win32.c
@@ -4,29 +4,29 @@
    PR:		none.
    Originator:	From the original ffitest.c  */
 
 /* { 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,
-						   float f3,
-						   float f4,
-						   float f5,
-						   float f6,
-						   float f7,
-						   float f8,
-						   float f9,
-						   float f10,
-						   float f11,
-						   float f12,
-						   float f13)
+static float FFI_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);
 }
 
 int main (void)
 {
   ffi_cif cif;
   ffi_type *args[13];
diff --git a/libffi/testsuite/libffi.call/strlen_win32.c b/libffi/testsuite/libffi.call/strlen_win32.c
--- a/libffi/testsuite/libffi.call/strlen_win32.c
+++ b/libffi/testsuite/libffi.call/strlen_win32.c
@@ -3,17 +3,17 @@
    Limitations:	none.
    PR:		none.
    Originator:	From the original ffitest.c  */
 
 /* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
 
 #include "ffitest.h"
 
-static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
+static size_t FFI_STDCALL my_stdcall_strlen(char *s)
 {
   return (strlen(s));
 }
 
 int main (void)
 {
   ffi_cif cif;
   ffi_type *args[MAX_ARGS];

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-01-14 17:24   ` Anthony Green
@ 2010-01-14 17:27     ` Anthony Green
  0 siblings, 0 replies; 12+ messages in thread
From: Anthony Green @ 2010-01-14 17:27 UTC (permalink / raw)
  To: Dan Witte; +Cc: libffi-discuss

On 01/14/2010 12:24 PM, Anthony Green wrote:
> On 01/13/2010 06:40 PM, Dan Witte wrote:
>> Hi all,
>>
>> I've finished my port of libffi to x86/msvc. There are three patches 
>> attached, against 3.0.9. Anthony, if these look okay to you, could 
>> you please apply?
>
> Thanks Dan.   Is there any way for you to run the testsuite?

Ignore me.  You did run the testsuite.  I assume that there were no 
unexpected failures, correct?

AG



>
> Thanks,
>
> AG
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-01-13 23:41 ` Dan Witte
  2010-01-14  2:21   ` Timothy Wall
@ 2010-01-14 17:24   ` Anthony Green
  2010-01-14 17:27     ` Anthony Green
  2010-01-15 16:34   ` Anthony Green
  2 siblings, 1 reply; 12+ messages in thread
From: Anthony Green @ 2010-01-14 17:24 UTC (permalink / raw)
  To: Dan Witte; +Cc: libffi-discuss

On 01/13/2010 06:40 PM, Dan Witte wrote:
> Hi all,
>
> I've finished my port of libffi to x86/msvc. There are three patches attached, against 3.0.9. Anthony, if these look okay to you, could you please apply?
>    

Thanks Dan.   Is there any way for you to run the testsuite?

Thanks,

AG

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-01-14  4:17     ` Dan Witte
@ 2010-01-14 12:49       ` Timothy Wall
  0 siblings, 0 replies; 12+ messages in thread
From: Timothy Wall @ 2010-01-14 12:49 UTC (permalink / raw)
  To: Dan Witte; +Cc: libffi-discuss


On Jan 13, 2010, at 11:17 PM, Dan Witte wrote:

>> I haven't looked at the patch yet, but ffi_call_SYSV and
>> ffi_call_STDCALL are not identical, since stdcall must pop its own
>> args from the stack.  I think I originally wrote it to share code
>> between two functions, with only a little bit on the ends for  
>> stdcall,
>>
>> but someone added some debug/stack metadata that required the two
>> functions be distinct, thus the duplicated code.
>
> Hmm. Both functions save 'esp' on entry, and restore it on exit, so  
> whether the caller or callee pops the args doesn't matter, and both  
> functions can be identical. Is this correct?
>
> (Looking at history, in an older libffi release, they were different  
> and the SYSV variant adjusted 'esp' appropriately after the foreign  
> call. But this was dropped when 'esp' was saved & restored.)
>
> I have no idea what the eh_frame stuff is doing, so if the two  
> functions need to be distinct for that reason, I can produce a new  
> patch. Presumably the functions can still be merged for MSVC, just  
> not for gcc. Should I do that?

I may be thinking of the closure code.  At any rate, if the code is  
truly identical, and the stdcall tests still pass (and they actually  
cover what you're changing), then there's no reason not to remove the  
duplicate code.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-01-14  2:21   ` Timothy Wall
@ 2010-01-14  4:17     ` Dan Witte
  2010-01-14 12:49       ` Timothy Wall
  0 siblings, 1 reply; 12+ messages in thread
From: Dan Witte @ 2010-01-14  4:17 UTC (permalink / raw)
  To: Timothy Wall; +Cc: libffi-discuss

> I haven't looked at the patch yet, but ffi_call_SYSV and  
> ffi_call_STDCALL are not identical, since stdcall must pop its own  
> args from the stack.  I think I originally wrote it to share code  
> between two functions, with only a little bit on the ends for stdcall,
>  
> but someone added some debug/stack metadata that required the two  
> functions be distinct, thus the duplicated code.

Hmm. Both functions save 'esp' on entry, and restore it on exit, so whether the caller or callee pops the args doesn't matter, and both functions can be identical. Is this correct?

(Looking at history, in an older libffi release, they were different and the SYSV variant adjusted 'esp' appropriately after the foreign call. But this was dropped when 'esp' was saved & restored.)

I have no idea what the eh_frame stuff is doing, so if the two functions need to be distinct for that reason, I can produce a new patch. Presumably the functions can still be merged for MSVC, just not for gcc. Should I do that?

Thanks,
Dan.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] port libffi to x86/msvc
  2010-01-13 23:41 ` Dan Witte
@ 2010-01-14  2:21   ` Timothy Wall
  2010-01-14  4:17     ` Dan Witte
  2010-01-14 17:24   ` Anthony Green
  2010-01-15 16:34   ` Anthony Green
  2 siblings, 1 reply; 12+ messages in thread
From: Timothy Wall @ 2010-01-14  2:21 UTC (permalink / raw)
  To: Dan Witte; +Cc: libffi-discuss


On Jan 13, 2010, at 6:40 PM, Dan Witte wrote:

>
> Patch descriptions are below. The first patch consolidates the stack  
> space allocation code; it's currently fragmented between  
> ffi_prep_cif and ffi_prep_cif_machdep depending on X86, X86_DARWIN,  
> or X86_WIN64, which made it somewhat hard to read. The second merges  
> ffi_call_SYSV and ffi_call_STDCALL since they're identical. The  
> third fixes a few MSVC syntax errors and adds the assembly routines.

I haven't looked at the patch yet, but ffi_call_SYSV and  
ffi_call_STDCALL are not identical, since stdcall must pop its own  
args from the stack.  I think I originally wrote it to share code  
between two functions, with only a little bit on the ends for stdcall,  
but someone added some debug/stack metadata that required the two  
functions be distinct, thus the duplicated code.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch] port libffi to x86/msvc
       [not found] <1180535804.107543.1263423246934.JavaMail.root@cm-mail03.mozilla.org>
@ 2010-01-13 23:41 ` Dan Witte
  2010-01-14  2:21   ` Timothy Wall
                     ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Dan Witte @ 2010-01-13 23:41 UTC (permalink / raw)
  To: libffi-discuss; +Cc: Anthony Green

[-- Attachment #1: Type: text/plain, Size: 2696 bytes --]

Hi all,

I've finished my port of libffi to x86/msvc. There are three patches attached, against 3.0.9. Anthony, if these look okay to you, could you please apply?

Details:
These avoid hacks to the build system by using Timothy Wall's idea of a wrapper script, 'cc.sh', which acts like gcc but translates commandline args and calls cl/ml appropriately. (I've attached it in case anyone wants to test; I don't think it should be merged, but if we can get it to be generic enough then perhaps it could be.) Patches are built and tested on i686-pc-linux-gnu, i686-pc-mingw32 (with MSVC), and i386-apple-darwin9.2.0, using Mozilla's testsuite. This tests ffi_call extensively and ffi_closure_SYSV somewhat, but does not test the raw API. (Any assistance in doing this would be greatly appreciated.)

For MSVC, libffi was configured with
configure --enable-shared --enable-static CC=path/to/cc.sh LD=link CPP=\"cl -nologo -EP\"

Patch descriptions are below. The first patch consolidates the stack space allocation code; it's currently fragmented between ffi_prep_cif and ffi_prep_cif_machdep depending on X86, X86_DARWIN, or X86_WIN64, which made it somewhat hard to read. The second merges ffi_call_SYSV and ffi_call_STDCALL since they're identical. The third fixes a few MSVC syntax errors and adds the assembly routines.

The assembly for MSVC is a direct translation of existing win32 assembly, with the exception of sint8/uint8/sint16/uint16 return type handling. Zero- or sign-extending these into a 4-byte register or memory location is unnecessary, and in the case of ffi_call, wrong - it means we're writing 4 bytes into a memory slot that may only hold 1 or 2 bytes. MSVC does not extend when compiling a C function that returns 1 or 2 bytes. (I can write a followup patch to change the other x86 platforms, as appropriate.)

[libffi-part1-x86-stack-alloc-machdep-1]
    2010-01-12  Daniel Witte  <dwitte@mozilla.com>
      * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to
      ffi_prep_cif_machdep for x86.
      * src/x86/ffi.c (ffi_prep_cif_machdep): To here.

[libffi-part2-ffi_call_win32-1]
    2010-01-12  Daniel Witte  <dwitte@mozilla.com>
      * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new
      function ffi_call_win32 on X86_WIN32.
      * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32.
      (ffi_call_STDCALL): Remove.

[libffi-part3-msvc-port-1]
    2010-01-12  Daniel Witte  <dwitte@mozilla.com>
      * src/x86/win32.S: Port assembly routines to MSVC and #ifdef.
      * src/x86/ffi.c: Tweak function declaration and remove excess parens.
      * include/ffi.h.in: Add __declspec(align(8)) to typedef struct ffi_closure.

[-- Attachment #2: libffi-part2-ffi_call_win32-1.diff --]
[-- Type: text/x-patch, Size: 11936 bytes --]

2010-01-12  Daniel Witte  <dwitte@mozilla.com>
  * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new
  function ffi_call_win32 on X86_WIN32.
  * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32.
  (ffi_call_STDCALL): Remove.

diff --git a/libffi/ChangeLog b/libffi/ChangeLog
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,8 +1,14 @@
+2010-01-12  Daniel Witte  <dwitte@mozilla.com>
+  * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new
+  function ffi_call_win32 on X86_WIN32.
+  * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32.
+  (ffi_call_STDCALL): Remove.
+
 2010-01-12  Daniel Witte  <dwitte@mozilla.com>
   * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to
   ffi_prep_cif_machdep for x86.
   * src/x86/ffi.c (ffi_prep_cif_machdep): To here.
 
 2009-12-28  David Edelsohn  <edelsohn@gnu.org>
 
 	* src/powerpc/ffi_darwin.c (ffi_prep_args): Copy abi and nargs to
diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c
--- a/libffi/src/x86/ffi.c
+++ b/libffi/src/x86/ffi.c
@@ -240,28 +240,27 @@ ffi_status ffi_prep_cif_machdep(ffi_cif 
 
 #ifdef X86_DARWIN
   cif->bytes = (cif->bytes + 15) & ~0xF;
 #endif
 
   return FFI_OK;
 }
 
-extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
-                          unsigned, unsigned, unsigned *, void (*fn)(void));
-
-#ifdef X86_WIN32
-extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
-                          unsigned, unsigned, unsigned *, void (*fn)(void));
-
-#endif /* X86_WIN32 */
 #ifdef X86_WIN64
 extern int
 ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
                unsigned, unsigned, unsigned *, void (*fn)(void));
+#elif defined(X86_WIN32)
+extern void
+ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
+               unsigned, unsigned, unsigned *, void (*fn)(void));
+#else
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+                          unsigned, unsigned, unsigned *, void (*fn)(void));
 #endif
 
 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 {
   extended_cif ecif;
 
   ecif.cif = cif;
   ecif.avalue = avalue;
@@ -309,28 +308,28 @@ void ffi_call(ffi_cif *cif, void (*fn)(v
               memcpy(local, avalue[i], size);
               avalue[i] = local;
             }
         }
         ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
                        cif->flags, ecif.rvalue, fn);
       }
       break;
+#elif defined(X86_WIN32)
+    case FFI_SYSV:
+    case FFI_STDCALL:
+      ffi_call_win32(ffi_prep_args, &ecif, cif->bytes, cif->flags,
+                     ecif.rvalue, fn);
+      break;
 #else
     case FFI_SYSV:
       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
                     fn);
       break;
-#ifdef X86_WIN32
-    case FFI_STDCALL:
-      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
-                       ecif.rvalue, fn);
-      break;
-#endif /* X86_WIN32 */
-#endif /* X86_WIN64 */
+#endif
     default:
       FFI_ASSERT(0);
       break;
     }
 }
 
 
 /** private members **/
@@ -615,26 +614,16 @@ ffi_prep_args_raw(char *stack, extended_
   memcpy (stack, ecif->avalue, ecif->cif->bytes);
 }
 
 /* we borrow this routine from libffi (it must be changed, though, to
  * actually call the function passed in the first argument.  as of
  * libffi-1.20, this is not the case.)
  */
 
-extern void
-ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, 
-              unsigned, unsigned *, void (*fn)(void));
-
-#ifdef X86_WIN32
-extern void
-ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
-                 unsigned, unsigned *, void (*fn)(void));
-#endif /* X86_WIN32 */
-
 void
 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
 {
   extended_cif ecif;
   void **avalue = (void **)fake_avalue;
 
   ecif.cif = cif;
   ecif.avalue = avalue;
@@ -648,26 +637,28 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(vo
       ecif.rvalue = alloca(cif->rtype->size);
     }
   else
     ecif.rvalue = rvalue;
     
   
   switch (cif->abi) 
     {
+#ifdef X86_WIN32
+    case FFI_SYSV:
+    case FFI_STDCALL:
+      ffi_call_win32(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
+                     ecif.rvalue, fn);
+      break;
+#else
     case FFI_SYSV:
       ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
                     ecif.rvalue, fn);
       break;
-#ifdef X86_WIN32
-    case FFI_STDCALL:
-      ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
-                       ecif.rvalue, fn);
-      break;
-#endif /* X86_WIN32 */
+#endif
     default:
       FFI_ASSERT(0);
       break;
     }
 }
 
 #endif
 
diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S
--- a/libffi/src/x86/win32.S
+++ b/libffi/src/x86/win32.S
@@ -31,19 +31,19 @@
 #define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
  
 	.text
  
         # This assumes we are using gas.
         .balign 16
-	.globl	_ffi_call_SYSV
-	.def	_ffi_call_SYSV;	.scl	2;	.type	32;	.endef
-_ffi_call_SYSV:
+	.globl	_ffi_call_win32
+	.def	_ffi_call_win32;	.scl	2;	.type	32;	.endef
+_ffi_call_win32:
 .LFB1:
         pushl %ebp
 .LCFI0:
         movl  %esp,%ebp
 .LCFI1:
         # Make room for all of the new args.
         movl  16(%ebp),%ecx                                                     
         subl  %ecx,%esp
@@ -56,18 +56,20 @@ _ffi_call_SYSV:
         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)
+        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   0f
  
         # Even if there is no space for the return value, we are
@@ -176,174 +178,21 @@ 1:
 .Lretstruct:
         # Nothing to do!
  
 .Lnoretval:
 .Lepilogue:
         movl %ebp,%esp
         popl %ebp
         ret
-.ffi_call_SYSV_end:
+.ffi_call_win32_end:
 .LFE1:
 
         # This assumes we are using gas.
         .balign 16
-	.globl	_ffi_call_STDCALL
-	.def	_ffi_call_STDCALL;	.scl	2;	.type	32;	.endef
-_ffi_call_STDCALL:
-.LFB2:
-        pushl %ebp
-.LCFI2:
-        movl  %esp,%ebp
-.LCFI3:
-        # 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   0f
-
-        # Even if there is no space for the return value, we are
-        # obliged to handle floating-point values.
-        cmpl  $FFI_TYPE_FLOAT,%ecx
-        jne   .Lsc_noretval
-        fstp  %st(0)
-
-        jmp   .Lsc_epilogue
-
-0:
-	call	1f
-	# Do not insert anything here between the call and the jump table.
-.Lsc_store_table:
-	.long	.Lsc_noretval		/* FFI_TYPE_VOID */
-	.long	.Lsc_retint		/* FFI_TYPE_INT */
-	.long	.Lsc_retfloat		/* FFI_TYPE_FLOAT */
-	.long	.Lsc_retdouble		/* FFI_TYPE_DOUBLE */
-	.long	.Lsc_retlongdouble	/* FFI_TYPE_LONGDOUBLE */
-	.long	.Lsc_retuint8		/* FFI_TYPE_UINT8 */
-	.long	.Lsc_retsint8		/* FFI_TYPE_SINT8 */
-	.long	.Lsc_retuint16		/* FFI_TYPE_UINT16 */
-	.long	.Lsc_retsint16		/* FFI_TYPE_SINT16 */
-	.long	.Lsc_retint		/* FFI_TYPE_UINT32 */
-	.long	.Lsc_retint		/* FFI_TYPE_SINT32 */
-	.long	.Lsc_retint64		/* FFI_TYPE_UINT64 */
-	.long	.Lsc_retint64		/* FFI_TYPE_SINT64 */
-	.long	.Lsc_retstruct		/* FFI_TYPE_STRUCT */
-	.long	.Lsc_retint		/* FFI_TYPE_POINTER */
-	.long	.Lsc_retstruct1b	/* FFI_TYPE_SMALL_STRUCT_1B */
-	.long	.Lsc_retstruct2b	/* FFI_TYPE_SMALL_STRUCT_2B */
-	.long	.Lsc_retstruct4b	/* FFI_TYPE_SMALL_STRUCT_4B */
-
-1:
-	add	%ecx, %ecx
-	add	%ecx, %ecx
-	add	(%esp),%ecx
-	add	$4, %esp
-	jmp	*(%ecx)
-
-	/* Sign/zero extend as appropriate.  */
-.Lsc_retsint8:
-	movsbl	%al, %eax
-	jmp	.Lsc_retint
-
-.Lsc_retsint16:
-	movswl	%ax, %eax
-	jmp	.Lsc_retint
-
-.Lsc_retuint8:
-	movzbl	%al, %eax
-	jmp	.Lsc_retint
-
-.Lsc_retuint16:
-	movzwl	%ax, %eax
-	jmp	.Lsc_retint
-
-.Lsc_retint:
-        # Load %ecx with the pointer to storage for the return value
-        movl  24(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        jmp   .Lsc_epilogue
-
-.Lsc_retfloat:
-         # Load %ecx with the pointer to storage for the return value
-        movl  24(%ebp),%ecx
-        fstps (%ecx)
-        jmp   .Lsc_epilogue
-
-.Lsc_retdouble:
-        # Load %ecx with the pointer to storage for the return value
-        movl  24(%ebp),%ecx
-        fstpl (%ecx)
-        jmp   .Lsc_epilogue
-
-.Lsc_retlongdouble:
-        # Load %ecx with the pointer to storage for the return value
-        movl  24(%ebp),%ecx
-        fstpt (%ecx)
-        jmp   .Lsc_epilogue
-
-.Lsc_retint64:
-        # Load %ecx with the pointer to storage for the return value
-        movl  24(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        movl  %edx,4(%ecx)
-	jmp   .Lsc_epilogue
-
-.Lsc_retstruct1b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  24(%ebp),%ecx
-        movb  %al,0(%ecx)
-        jmp   .Lsc_epilogue
-
-.Lsc_retstruct2b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  24(%ebp),%ecx
-        movw  %ax,0(%ecx)
-        jmp   .Lsc_epilogue
-
-.Lsc_retstruct4b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  24(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        jmp   .Lsc_epilogue
-
-.Lsc_retstruct:
-        # Nothing to do!
-
-.Lsc_noretval:
-.Lsc_epilogue:
-        movl %ebp,%esp
-        popl %ebp
-        ret
-.ffi_call_STDCALL_end:
-.LFE2:
-
-        # This assumes we are using gas.
-        .balign 16
 	.globl	_ffi_closure_SYSV
 	.def	_ffi_closure_SYSV;	.scl	2;	.type	32;	.endef
 _ffi_closure_SYSV:
 .LFB3:
 	pushl	%ebp
 .LCFI4:
 	movl	%esp, %ebp
 .LCFI5:
@@ -737,48 +586,16 @@ 1:
 	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
 	.byte	0x5	/* .uleb128 0x5 */
 
 	/* End of DW_CFA_xxx CFI instructions.  */
 	.align 4
 .LEFDE1:
 
 
-.LSFDE2:
-	.long	.LEFDE2-.LASFDE2	/* FDE Length */
-.LASFDE2:
-	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-	.long	.LFB2-.	/* FDE initial location */
-#else
-	.long	.LFB2
-#endif
-	.long	.LFE2-.LFB2	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	/* DW_CFA_xxx CFI instructions go here.  */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI2-.LFB2
-	.byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-	.byte	0x2	/* .uleb128 0x2 */
-
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI3-.LCFI2
-	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-	.byte	0x5	/* .uleb128 0x5 */
-
-	/* End of DW_CFA_xxx CFI instructions.  */
-	.align 4
-.LEFDE2:
-
-
 .LSFDE3:
 	.long	.LEFDE3-.LASFDE3	/* FDE Length */
 .LASFDE3:
 	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
 	.long	.LFB3-.	/* FDE initial location */
 #else
 	.long	.LFB3

[-- Attachment #3: libffi-part3-msvc-port-1.diff --]
[-- Type: text/x-patch, Size: 18092 bytes --]

2010-01-12  Daniel Witte  <dwitte@mozilla.com>
  * src/x86/win32.S: Port assembly routines to MSVC and #ifdef.
  * src/x86/ffi.c: Tweak function declaration and remove excess parens.
  * include/ffi.h.in: Add __declspec(align(8)) to typedef struct ffi_closure.

diff --git a/libffi/ChangeLog b/libffi/ChangeLog
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,8 +1,13 @@
+2010-01-12  Daniel Witte  <dwitte@mozilla.com>
+  * src/x86/win32.S: Port assembly routines to MSVC and #ifdef.
+  * src/x86/ffi.c: Tweak function declaration and remove excess parens.
+  * include/ffi.h.in: Add __declspec(align(8)) to typedef struct ffi_closure.
+
 2010-01-12  Daniel Witte  <dwitte@mozilla.com>
   * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new
   function ffi_call_win32 on X86_WIN32.
   * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32.
   (ffi_call_STDCALL): Remove.
 
 2010-01-12  Daniel Witte  <dwitte@mozilla.com>
   * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to
diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in
--- a/libffi/include/ffi.h.in
+++ b/libffi/include/ffi.h.in
@@ -246,16 +246,19 @@ void ffi_java_raw_call (ffi_cif *cif,
 void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
 void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
 size_t ffi_java_raw_size (ffi_cif *cif);
 
 /* ---- Definitions for closures ----------------------------------------- */
 
 #if FFI_CLOSURES
 
+#ifdef _MSC_VER
+__declspec(align(8))
+#endif
 typedef struct {
   char tramp[FFI_TRAMPOLINE_SIZE];
   ffi_cif   *cif;
   void     (*fun)(ffi_cif*,void*,void**,void*);
   void      *user_data;
 #ifdef __GNUC__
 } ffi_closure __attribute__((aligned (8)));
 #else
diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c
--- a/libffi/src/x86/ffi.c
+++ b/libffi/src/x86/ffi.c
@@ -329,16 +329,18 @@ void ffi_call(ffi_cif *cif, void (*fn)(v
       FFI_ASSERT(0);
       break;
     }
 }
 
 
 /** private members **/
 
+/* The following __attribute__((regparm(1))) decorations will have no effect
+   on MSVC - standard cdecl convention applies. */
 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
                                          void** args, ffi_cif* cif);
 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
      __attribute__ ((regparm(1)));
 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
      __attribute__ ((regparm(1)));
 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
      __attribute__ ((regparm(1)));
@@ -377,21 +379,18 @@ ffi_closure_win64_inner (ffi_closure *cl
      result types except for floats; we have to 'mov xmm0, rax' in the
      caller to correct this.
      TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
   */
   return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
 }
 
 #else
-unsigned int FFI_HIDDEN
-ffi_closure_SYSV_inner (closure, respp, args)
-     ffi_closure *closure;
-     void **respp;
-     void *args;
+unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
+ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
 {
   /* our various things...  */
   ffi_cif       *cif;
   void         **arg_area;
 
   cif         = closure->cif;
   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
 
@@ -492,39 +491,39 @@ ffi_prep_incoming_args_SYSV(char *stack,
    *(unsigned char *)  &__tramp[26] = 0x41; \
    *(unsigned char *)  &__tramp[27] = 0xff; \
    *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
  }
 
 /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
 
 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
-({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
    unsigned int  __fun = (unsigned int)(FUN); \
    unsigned int  __ctx = (unsigned int)(CTX); \
    unsigned int  __dis = __fun - (__ctx + 10);  \
    *(unsigned char*) &__tramp[0] = 0xb8; \
    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
    *(unsigned char *)  &__tramp[5] = 0xe9; \
    *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
- })
+ }
 
 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
-({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
    unsigned int  __fun = (unsigned int)(FUN); \
    unsigned int  __ctx = (unsigned int)(CTX); \
    unsigned int  __dis = __fun - (__ctx + 10); \
    unsigned short __size = (unsigned short)(SIZE); \
    *(unsigned char*) &__tramp[0] = 0xb8; \
    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
    *(unsigned char *)  &__tramp[5] = 0xe8; \
    *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
    *(unsigned char *)  &__tramp[10] = 0xc2; \
    *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
- })
+ }
 
 /* the cif must already be prep'ed */
 
 ffi_status
 ffi_prep_closure_loc (ffi_closure* closure,
                       ffi_cif* cif,
                       void (*fun)(ffi_cif*,void*,void**,void*),
                       void *user_data,
diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S
--- a/libffi/src/x86/win32.S
+++ b/libffi/src/x86/win32.S
@@ -1,12 +1,13 @@
 /* -----------------------------------------------------------------------
    win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009  Red Hat, Inc.
 	     Copyright (c) 2001  John Beniton
 	     Copyright (c) 2002  Ranjit Mathew
+	     Copyright (c) 2009  Daniel Witte
 			
  
    X86 Foreign Function Interface
  
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    ``Software''), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
@@ -26,17 +27,374 @@
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
    -----------------------------------------------------------------------
    */
  
 #define LIBFFI_ASM
 #include <fficonfig.h>
 #include <ffi.h>
- 
+
+#ifdef _MSC_VER
+
+.386
+.MODEL FLAT, C
+
+EXTRN ffi_closure_SYSV_inner:NEAR
+
+_TEXT SEGMENT
+
+ffi_call_win32 PROC NEAR,
+    ffi_prep_args : NEAR PTR DWORD,
+    ecif          : NEAR PTR DWORD,
+    cif_bytes     : DWORD,
+    cif_flags     : DWORD,
+    rvalue        : NEAR PTR DWORD,
+    fn            : NEAR PTR DWORD
+
+        ;; Make room for all of the new args.
+        mov  ecx, cif_bytes
+        sub  esp, ecx
+
+        mov  eax, esp
+
+        ;; Place all of the ffi_prep_args in position
+        push ecif
+        push eax
+        call ffi_prep_args
+
+        ;; Return stack to previous state and call the function
+        add  esp, 8
+
+        call fn
+
+        ;; cdecl:   we restore esp in the epilogue, so there's no need to
+        ;;          remove the space we pushed for the args.
+        ;; stdcall: the callee has already cleaned the stack.
+
+        ;; Load ecx with the return type code
+        mov  ecx, cif_flags
+
+        ;; If the return value pointer is NULL, assume no return value.
+        cmp  rvalue, 0
+        jne  ca_jumptable
+
+        ;; Even if there is no space for the return value, we are
+        ;; obliged to handle floating-point values.
+        cmp  ecx, FFI_TYPE_FLOAT
+        jne  ca_epilogue
+        fstp st(0)
+
+        jmp  ca_epilogue
+
+ca_jumptable:
+        jmp  [ca_jumpdata + 4 * ecx]
+ca_jumpdata:
+        ;; Do not insert anything here between label and jump table.
+        dd offset ca_epilogue       ;; FFI_TYPE_VOID
+        dd offset ca_retint         ;; FFI_TYPE_INT
+        dd offset ca_retfloat       ;; FFI_TYPE_FLOAT
+        dd offset ca_retdouble      ;; FFI_TYPE_DOUBLE
+        dd offset ca_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
+        dd offset ca_retint8        ;; FFI_TYPE_UINT8
+        dd offset ca_retint8        ;; FFI_TYPE_SINT8
+        dd offset ca_retint16       ;; FFI_TYPE_UINT16
+        dd offset ca_retint16       ;; FFI_TYPE_SINT16
+        dd offset ca_retint         ;; FFI_TYPE_UINT32
+        dd offset ca_retint         ;; FFI_TYPE_SINT32
+        dd offset ca_retint64       ;; FFI_TYPE_UINT64
+        dd offset ca_retint64       ;; FFI_TYPE_SINT64
+        dd offset ca_epilogue       ;; FFI_TYPE_STRUCT
+        dd offset ca_retint         ;; FFI_TYPE_POINTER
+        dd offset ca_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
+        dd offset ca_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
+        dd offset ca_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
+
+ca_retint8:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        mov   [ecx + 0], al
+        jmp   ca_epilogue
+
+ca_retint16:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        mov   [ecx + 0], ax
+        jmp   ca_epilogue
+
+ca_retint:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        mov   [ecx + 0], eax
+        jmp   ca_epilogue
+
+ca_retint64:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        mov   [ecx + 0], eax
+        mov   [ecx + 4], edx
+        jmp   ca_epilogue
+
+ca_retfloat:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        fstp  DWORD PTR [ecx]
+        jmp   ca_epilogue
+
+ca_retdouble:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        fstp  QWORD PTR [ecx]
+        jmp   ca_epilogue
+
+ca_retlongdouble:
+        ;; Load %ecx with the pointer to storage for the return value
+        mov   ecx, rvalue
+        fstp  TBYTE PTR [ecx]
+        jmp   ca_epilogue
+
+ca_epilogue:
+        ;; Epilogue code is autogenerated.
+        ret
+ffi_call_win32 ENDP
+
+ffi_closure_SYSV PROC NEAR FORCEFRAME
+    ;; the ffi_closure ctx is passed in eax by the trampoline.
+
+        sub  esp, 40
+        lea  edx, [ebp - 24]
+        mov  [ebp - 12], edx         ;; resp
+        lea  edx, [ebp + 8]
+        mov  [esp + 8], edx          ;; args
+        lea  edx, [ebp - 12]
+        mov  [esp + 4], edx          ;; &resp
+        mov  [esp], eax              ;; closure
+        call ffi_closure_SYSV_inner
+        mov  ecx, [ebp - 12]
+
+cs_jumptable:
+        jmp  [cs_jumpdata + 4 * eax]
+cs_jumpdata:
+        ;; Do not insert anything here between the label and jump table.
+        dd offset cs_epilogue       ;; FFI_TYPE_VOID
+        dd offset cs_retint         ;; FFI_TYPE_INT
+        dd offset cs_retfloat       ;; FFI_TYPE_FLOAT
+        dd offset cs_retdouble      ;; FFI_TYPE_DOUBLE
+        dd offset cs_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
+        dd offset cs_retint8        ;; FFI_TYPE_UINT8
+        dd offset cs_retint8        ;; FFI_TYPE_SINT8
+        dd offset cs_retint16       ;; FFI_TYPE_UINT16
+        dd offset cs_retint16       ;; FFI_TYPE_SINT16
+        dd offset cs_retint         ;; FFI_TYPE_UINT32
+        dd offset cs_retint         ;; FFI_TYPE_SINT32
+        dd offset cs_retint64       ;; FFI_TYPE_UINT64
+        dd offset cs_retint64       ;; FFI_TYPE_SINT64
+        dd offset cs_retstruct      ;; FFI_TYPE_STRUCT
+        dd offset cs_retint         ;; FFI_TYPE_POINTER
+        dd offset cs_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
+        dd offset cs_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
+        dd offset cs_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
+
+cs_retint8:
+        mov   al, [ecx]
+        jmp   cs_epilogue
+
+cs_retint16:
+        mov   ax, [ecx]
+        jmp   cs_epilogue
+
+cs_retint:
+        mov   eax, [ecx]
+        jmp   cs_epilogue
+
+cs_retint64:
+        mov   eax, [ecx + 0]
+        mov   edx, [ecx + 4]
+        jmp   cs_epilogue
+
+cs_retfloat:
+        fld   DWORD PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retdouble:
+        fld   QWORD PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retlongdouble:
+        fld   TBYTE PTR [ecx]
+        jmp   cs_epilogue
+
+cs_retstruct:
+        ;; Caller expects us to pop struct return value pointer hidden arg.
+        ;; Epilogue code is autogenerated.
+        ret	4
+
+cs_epilogue:
+        ;; Epilogue code is autogenerated.
+        ret
+ffi_closure_SYSV ENDP
+
+#if !FFI_NO_RAW_API
+
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#define CIF_FLAGS_OFFSET 20
+
+ffi_closure_raw_SYSV PROC NEAR USES esi
+    ;; the ffi_closure ctx is passed in eax by the trampoline.
+
+        sub  esp, 40
+        mov  esi, [eax + RAW_CLOSURE_CIF_OFFSET]        ;; closure->cif
+        mov  edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET]  ;; closure->user_data
+        mov  [esp + 12], edx                            ;; user_data
+        lea  edx, [ebp + 8]
+        mov  [esp + 8], edx                             ;; raw_args
+        lea  edx, [ebp - 24]
+        mov  [esp + 4], edx                             ;; &res
+        mov  [esp], esi                                 ;; cif
+        call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET]   ;; closure->fun
+        mov  eax, [esi + CIF_FLAGS_OFFSET]              ;; cif->flags
+        lea  ecx, [ebp - 24]
+
+cr_jumptable:
+        jmp  [cr_jumpdata + 4 * eax]
+cr_jumpdata:
+        ;; Do not insert anything here between the label and jump table.
+        dd offset cr_epilogue       ;; FFI_TYPE_VOID
+        dd offset cr_retint         ;; FFI_TYPE_INT
+        dd offset cr_retfloat       ;; FFI_TYPE_FLOAT
+        dd offset cr_retdouble      ;; FFI_TYPE_DOUBLE
+        dd offset cr_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
+        dd offset cr_retint8        ;; FFI_TYPE_UINT8
+        dd offset cr_retint8        ;; FFI_TYPE_SINT8
+        dd offset cr_retint16       ;; FFI_TYPE_UINT16
+        dd offset cr_retint16       ;; FFI_TYPE_SINT16
+        dd offset cr_retint         ;; FFI_TYPE_UINT32
+        dd offset cr_retint         ;; FFI_TYPE_SINT32
+        dd offset cr_retint64       ;; FFI_TYPE_UINT64
+        dd offset cr_retint64       ;; FFI_TYPE_SINT64
+        dd offset cr_epilogue       ;; FFI_TYPE_STRUCT
+        dd offset cr_retint         ;; FFI_TYPE_POINTER
+        dd offset cr_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
+        dd offset cr_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
+        dd offset cr_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
+
+cr_retint8:
+        mov   al, [ecx]
+        jmp   cr_epilogue
+
+cr_retint16:
+        mov   ax, [ecx]
+        jmp   cr_epilogue
+
+cr_retint:
+        mov   eax, [ecx]
+        jmp   cr_epilogue
+
+cr_retint64:
+        mov   eax, [ecx + 0]
+        mov   edx, [ecx + 4]
+        jmp   cr_epilogue
+
+cr_retfloat:
+        fld   DWORD PTR [ecx]
+        jmp   cr_epilogue
+
+cr_retdouble:
+        fld   QWORD PTR [ecx]
+        jmp   cr_epilogue
+
+cr_retlongdouble:
+        fld   TBYTE PTR [ecx]
+        jmp   cr_epilogue
+
+cr_epilogue:
+        ;; Epilogue code is autogenerated.
+        ret
+ffi_closure_raw_SYSV ENDP
+
+#endif /* !FFI_NO_RAW_API */
+
+ffi_closure_STDCALL PROC NEAR FORCEFRAME
+    ;; the ffi_closure ctx is passed in eax by the trampoline.
+
+        sub  esp, 40
+        lea  edx, [ebp - 24]
+        mov  [ebp - 12], edx         ;; resp
+        lea  edx, [ebp + 12]         ;; account for stub return address on stack
+        mov  [esp + 8], edx          ;; args
+        lea  edx, [ebp - 12]
+        mov  [esp + 4], edx          ;; &resp
+        mov  [esp], eax              ;; closure
+        call ffi_closure_SYSV_inner
+        mov  ecx, [ebp - 12]
+
+cd_jumptable:
+        jmp  [cd_jumpdata + 4 * eax]
+cd_jumpdata:
+        ;; Do not insert anything here between the label and jump table.
+        dd offset cd_epilogue       ;; FFI_TYPE_VOID
+        dd offset cd_retint         ;; FFI_TYPE_INT
+        dd offset cd_retfloat       ;; FFI_TYPE_FLOAT
+        dd offset cd_retdouble      ;; FFI_TYPE_DOUBLE
+        dd offset cd_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
+        dd offset cd_retint8        ;; FFI_TYPE_UINT8
+        dd offset cd_retint8        ;; FFI_TYPE_SINT8
+        dd offset cd_retint16       ;; FFI_TYPE_UINT16
+        dd offset cd_retint16       ;; FFI_TYPE_SINT16
+        dd offset cd_retint         ;; FFI_TYPE_UINT32
+        dd offset cd_retint         ;; FFI_TYPE_SINT32
+        dd offset cd_retint64       ;; FFI_TYPE_UINT64
+        dd offset cd_retint64       ;; FFI_TYPE_SINT64
+        dd offset cd_epilogue       ;; FFI_TYPE_STRUCT
+        dd offset cd_retint         ;; FFI_TYPE_POINTER
+        dd offset cd_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
+        dd offset cd_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
+        dd offset cd_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
+
+cd_retint8:
+        mov   al, [ecx]
+        jmp   cd_epilogue
+
+cd_retint16:
+        mov   ax, [ecx]
+        jmp   cd_epilogue
+
+cd_retint:
+        mov   eax, [ecx]
+        jmp   cd_epilogue
+
+cd_retint64:
+        mov   eax, [ecx + 0]
+        mov   edx, [ecx + 4]
+        jmp   cd_epilogue
+
+cd_retfloat:
+        fld   DWORD PTR [ecx]
+        jmp   cd_epilogue
+
+cd_retdouble:
+        fld   QWORD PTR [ecx]
+        jmp   cd_epilogue
+
+cd_retlongdouble:
+        fld   TBYTE PTR [ecx]
+        jmp   cd_epilogue
+
+cd_epilogue:
+        ;; Epilogue code is autogenerated.
+        ret
+ffi_closure_STDCALL ENDP
+
+_TEXT ENDS
+END
+
+#else
+
 	.text
  
         # This assumes we are using gas.
         .balign 16
 	.globl	_ffi_call_win32
 	.def	_ffi_call_win32;	.scl	2;	.type	32;	.endef
 _ffi_call_win32:
 .LFB1:
@@ -687,8 +1045,11 @@ 1:
 	.byte	0x4	/* DW_CFA_advance_loc4 */
 	.long	.LCFI10-.LCFI9
 	.byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
 	.byte	0x5	/* .uleb128 0x5 */
 
 	/* End of DW_CFA_xxx CFI instructions.  */
 	.align 4
 .LEFDE5:
+
+#endif /* !_MSC_VER */
+

[-- Attachment #4: cc.sh --]
[-- Type: application/x-shellscript, Size: 4669 bytes --]

[-- Attachment #5: libffi-part1-x86-stack-alloc-machdep-1.diff --]
[-- Type: text/x-patch, Size: 5978 bytes --]

2010-01-12  Daniel Witte  <dwitte@mozilla.com>
  * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to
  ffi_prep_cif_machdep for x86.
  * src/x86/ffi.c (ffi_prep_cif_machdep): To here.

diff --git a/libffi/ChangeLog b/libffi/ChangeLog
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,8 +1,13 @@
+2010-01-12  Daniel Witte  <dwitte@mozilla.com>
+  * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to
+  ffi_prep_cif_machdep for x86.
+  * src/x86/ffi.c (ffi_prep_cif_machdep): To here.
+
 2009-12-28  David Edelsohn  <edelsohn@gnu.org>
 
 	* src/powerpc/ffi_darwin.c (ffi_prep_args): Copy abi and nargs to
 	local variables.
 	(aix_adjust_aggregate_sizes): New function.
 	(ffi_prep_cif_machdep): Call it.
 
 2009-12-26  Andreas Tobler  <a.tobler@schweiz.org>
diff --git a/libffi/src/prep_cif.c b/libffi/src/prep_cif.c
--- a/libffi/src/prep_cif.c
+++ b/libffi/src/prep_cif.c
@@ -104,42 +104,39 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ff
 
   /* Initialize the return type if necessary */
   if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
     return FFI_BAD_TYPEDEF;
 
   /* Perform a sanity check on the return type */
   FFI_ASSERT_VALID_TYPE(cif->rtype);
 
-  /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
-#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
+  /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
+#if !defined M68K && !defined __i386__ && !defined __x86_64__ && !defined S390 && !defined PA
   /* Make space for the return structure pointer */
   if (cif->rtype->type == FFI_TYPE_STRUCT
 #ifdef SPARC
       && (cif->abi != FFI_V9 || cif->rtype->size > 32)
 #endif
-#ifdef X86_DARWIN
-      && (cif->rtype->size > 8)
-#endif
      )
     bytes = STACK_ARG_SIZE(sizeof(void*));
 #endif
 
   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
     {
 
       /* Initialize any uninitialized aggregate type definitions */
       if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
 	return FFI_BAD_TYPEDEF;
 
       /* Perform a sanity check on the argument type, do this
 	 check after the initialization.  */
       FFI_ASSERT_VALID_TYPE(*ptr);
 
-#if !defined __x86_64__ && !defined S390 && !defined PA
+#if !defined __i386__ && !defined __x86_64__ && !defined S390 && !defined PA
 #ifdef SPARC
       if (((*ptr)->type == FFI_TYPE_STRUCT
 	   && ((*ptr)->size > 16 || cif->abi != FFI_V9))
 	  || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
 	      && cif->abi != FFI_V9))
 	bytes += sizeof(void*);
       else
 #endif
diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c
--- a/libffi/src/x86/ffi.c
+++ b/libffi/src/x86/ffi.c
@@ -143,34 +143,33 @@ void ffi_prep_args(char *stack, extended
     }
   
   return;
 }
 
 /* Perform machine dependent cif processing */
 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 {
+  unsigned int i;
+  ffi_type **ptr;
+
   /* Set the return type flag */
   switch (cif->rtype->type)
     {
     case FFI_TYPE_VOID:
-#ifdef X86
-    case FFI_TYPE_STRUCT:
-#endif
 #if defined(X86) || defined (X86_WIN32) || defined(X86_FREEBSD) || defined(X86_DARWIN) || defined(X86_WIN64)
     case FFI_TYPE_UINT8:
     case FFI_TYPE_UINT16:
     case FFI_TYPE_SINT8:
     case FFI_TYPE_SINT16:
 #endif
 #ifdef X86_WIN64
     case FFI_TYPE_UINT32:
     case FFI_TYPE_SINT32:
 #endif
-
     case FFI_TYPE_SINT64:
     case FFI_TYPE_FLOAT:
     case FFI_TYPE_DOUBLE:
 #ifndef X86_WIN64
 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
     case FFI_TYPE_LONGDOUBLE:
 #endif
 #endif
@@ -179,18 +178,18 @@ ffi_status ffi_prep_cif_machdep(ffi_cif 
 
     case FFI_TYPE_UINT64:
 #ifdef X86_WIN64
     case FFI_TYPE_POINTER:
 #endif
       cif->flags = FFI_TYPE_SINT64;
       break;
 
+    case FFI_TYPE_STRUCT:
 #ifndef X86
-    case FFI_TYPE_STRUCT:
       if (cif->rtype->size == 1)
         {
           cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
         }
       else if (cif->rtype->size == 2)
         {
           cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
         }
@@ -202,58 +201,52 @@ ffi_status ffi_prep_cif_machdep(ffi_cif 
           cif->flags = FFI_TYPE_INT; /* same as int type */
 #endif
         }
       else if (cif->rtype->size == 8)
         {
           cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
         }
       else
+#endif
         {
           cif->flags = FFI_TYPE_STRUCT;
-#ifdef X86_WIN64
           // allocate space for return value pointer
           cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
-#endif
         }
       break;
-#endif
 
     default:
 #ifdef X86_WIN64
       cif->flags = FFI_TYPE_SINT64;
       break;
     case FFI_TYPE_INT:
       cif->flags = FFI_TYPE_SINT32;
 #else
       cif->flags = FFI_TYPE_INT;
 #endif
       break;
     }
 
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      if (((*ptr)->alignment - 1) & cif->bytes)
+        cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
+      cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
+    }
+
+#ifdef X86_WIN64
+  // ensure space for storing four registers
+  cif->bytes += 4 * sizeof(ffi_arg);
+#endif
+
 #ifdef X86_DARWIN
   cif->bytes = (cif->bytes + 15) & ~0xF;
 #endif
 
-#ifdef X86_WIN64
-  {
-    unsigned int i;
-    ffi_type **ptr;
-
-    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
-      {
-        if (((*ptr)->alignment - 1) & cif->bytes)
-          cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
-        cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
-      }
-  }
-  // ensure space for storing four registers
-  cif->bytes += 4 * sizeof(ffi_arg);
-#endif
-
   return FFI_OK;
 }
 
 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
                           unsigned, unsigned, unsigned *, void (*fn)(void));
 
 #ifdef X86_WIN32
 extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-02-24 15:53 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1961299951.120059.1263581161934.JavaMail.root@cm-mail03.mozilla.org>
2010-01-15 18:46 ` [patch] port libffi to x86/msvc Dan Witte
2010-02-23 17:36   ` Mladen Turk
2010-02-23 22:33     ` Dan Witte
2010-02-24 15:53       ` Anthony Green
     [not found] <1233161867.115183.1263521983853.JavaMail.root@cm-mail03.mozilla.org>
2010-01-15  2:20 ` Dan Witte
     [not found] <1180535804.107543.1263423246934.JavaMail.root@cm-mail03.mozilla.org>
2010-01-13 23:41 ` Dan Witte
2010-01-14  2:21   ` Timothy Wall
2010-01-14  4:17     ` Dan Witte
2010-01-14 12:49       ` Timothy Wall
2010-01-14 17:24   ` Anthony Green
2010-01-14 17:27     ` Anthony Green
2010-01-15 16:34   ` Anthony Green

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).