* libffi stdcall closures
@ 2007-11-08 16:09 Timothy Wall
2007-11-08 19:11 ` Tom Tromey
0 siblings, 1 reply; 6+ messages in thread
From: Timothy Wall @ 2007-11-08 16:09 UTC (permalink / raw)
To: gcc-patches; +Cc: twall
I'm working on a patch for win32/x86 stdcall closures to support JNA
(http://jna.dev.java.net), a ctypes-like library for Java. I'm
working off of a libffi snapshot from the gcc trunk.
I've got the closure code working now, and I need some pointers on
adding a win32-only stdcall callback test to the testsuite (or a
general one if stdcall is supported elsewhere).
I'm running the testsuite under cygwin, which works except for about
4 failures unrelated to what I'm working on.
Oddly enough, some stdcall closures would work while others would not
(seems to be tied to the caller environment as opposed to the number
of closure arguments). Probably has to do with whether the caller
is maintaining a frame pointer or whether it relies entirely on the
stack pointer.
Timothy Wall
http://abbot.sf.net
PS Please CC me explicitly; I'm not subscribed to gcc-patches.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: libffi stdcall closures
2007-11-08 16:09 libffi stdcall closures Timothy Wall
@ 2007-11-08 19:11 ` Tom Tromey
2007-11-08 22:19 ` Timothy Wall
2007-11-09 1:07 ` Timothy Wall
0 siblings, 2 replies; 6+ messages in thread
From: Tom Tromey @ 2007-11-08 19:11 UTC (permalink / raw)
To: Timothy Wall; +Cc: gcc-patches
>>>>> "Timothy" == Timothy Wall <twall@users.sf.net> writes:
Timothy> I'm working on a patch for win32/x86 stdcall closures to support JNA
Timothy> (http://jna.dev.java.net), a ctypes-like library for Java. I'm
Timothy> working off of a libffi snapshot from the gcc trunk.
Nice. JNA looks cool.
BTW, I think I read somewhere that you have some standalone configure
changes for libffi...? We could put those in the separate libffi
repository if that would help you. I occasionally think it would be
nice to revive the standalone libffi -- but only if there's interest.
Timothy> I've got the closure code working now, and I need some pointers on
Timothy> adding a win32-only stdcall callback test to the testsuite (or a
Timothy> general one if stdcall is supported elsewhere).
libffi uses the dejagnu 'dg' code, so you should be able to just drop
your test cases into the test suite. If the test is platform-specific
I think you can use the "target" clause to dg-do. Grep for "target"
in gcc/testsuite/**/*.c to see uses.
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: libffi stdcall closures
2007-11-08 19:11 ` Tom Tromey
@ 2007-11-08 22:19 ` Timothy Wall
2007-11-09 1:07 ` Timothy Wall
1 sibling, 0 replies; 6+ messages in thread
From: Timothy Wall @ 2007-11-08 22:19 UTC (permalink / raw)
To: tromey; +Cc: gcc-patches
Ok, thanks, I got a test that runs only for w32. It also uncovered a
bug in the cygwin gcc I am using (3.4.4 cygming special); it pops
arguments for stdcall calls unless invoked in "-mno-cygwin" mode,
which is likely to screw up terminal output. Now I have to figure
out a way around a) the arg popping and b) a good way to verify the
stack is consistent before/after the call.
I'll have to check the config changes; they're probably pretty
minor. I know python has a couple of libffi snapshots, so they at
least might find a standalone libffi useful.
On Nov 8, 2007, at 12:48 PM, Tom Tromey wrote:
>>>>>> "Timothy" == Timothy Wall <twall@users.sf.net> writes:
>
> Timothy> I'm working on a patch for win32/x86 stdcall closures to
> support JNA
> Timothy> (http://jna.dev.java.net), a ctypes-like library for
> Java. I'm
> Timothy> working off of a libffi snapshot from the gcc trunk.
>
> Nice. JNA looks cool.
>
> BTW, I think I read somewhere that you have some standalone configure
> changes for libffi...? We could put those in the separate libffi
> repository if that would help you. I occasionally think it would be
> nice to revive the standalone libffi -- but only if there's interest.
>
> Timothy> I've got the closure code working now, and I need some
> pointers on
> Timothy> adding a win32-only stdcall callback test to the testsuite
> (or a
> Timothy> general one if stdcall is supported elsewhere).
>
> libffi uses the dejagnu 'dg' code, so you should be able to just drop
> your test cases into the test suite. If the test is platform-specific
> I think you can use the "target" clause to dg-do. Grep for "target"
> in gcc/testsuite/**/*.c to see uses.
>
> Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: libffi stdcall closures
2007-11-08 19:11 ` Tom Tromey
2007-11-08 22:19 ` Timothy Wall
@ 2007-11-09 1:07 ` Timothy Wall
2007-11-13 23:28 ` Tom Tromey
1 sibling, 1 reply; 6+ messages in thread
From: Timothy Wall @ 2007-11-09 1:07 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 498 bytes --]
Here's the patch for stdcall closures, including a basic test. The
diff is against the JNA repo; I can probably do one against a gcc
checkout if necessary.
BTW, the lack of support came up as people were trying to install
Java callbacks into various windows API functions (services, keyboard
hooks, etc). Some would work fine, others would crash. I wasn't
aware that libffi didn't have stdcall closure support since the few
simple tests and examples I wrote just happened to work.
[-- Attachment #2: diffs.txt --]
[-- Type: text/plain, Size: 6605 bytes --]
Index: libffi/ChangeLog
===================================================================
--- libffi/ChangeLog (revision 243)
+++ libffi/ChangeLog (working copy)
@@ -1,3 +1,12 @@
+2007-11-08 Timothy Wall <twall@users.sf.net>
+
+ * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall
+ closures.
+ * src/x86/ffitarget.h: Increase size of trampoline for stdcall
+ closures.
+ * src/x86/win32.S: Add assembly for stdcall closure.
+ * src/x86/ffi.c: Initialize stdcall closure trampoline.
+
2007-05-13 Release Manager
* GCC 4.2.0 released.
Index: libffi/src/x86/ffitarget.h
===================================================================
--- libffi/src/x86/ffitarget.h (revision 243)
+++ libffi/src/x86/ffitarget.h (working copy)
@@ -73,7 +73,11 @@
#define FFI_TRAMPOLINE_SIZE 24
#define FFI_NATIVE_RAW_API 0
#else
+#ifdef X86_WIN32
+#define FFI_TRAMPOLINE_SIZE 13
+#else
#define FFI_TRAMPOLINE_SIZE 10
+#endif
#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
#endif
Index: libffi/src/x86/win32.S
===================================================================
--- libffi/src/x86/win32.S (revision 243)
+++ libffi/src/x86/win32.S (working copy)
@@ -258,6 +258,22 @@
.ffi_call_STDCALL_end:
+ .globl _ffi_closure_STDCALL
+_ffi_closure_STDCALL:
+ pushl %ebp
+ movl %esp, %ebp
+ subl $40, %esp
+ leal -24(%ebp), %edx
+ movl %edx, -12(%ebp) /* resp */
+ leal 12(%ebp), %edx /* account for stub return address on stack */
+ movl %edx, 4(%esp) /* args */
+ leal -12(%ebp), %edx
+ movl %edx, (%esp) /* &resp */
+ call _ffi_closure_SYSV_inner
+ movl -12(%ebp), %ecx
+ jmp .Lcls_return_result
+.ffi_closure_STDCALL_end:
+
.globl _ffi_closure_SYSV
_ffi_closure_SYSV:
pushl %ebp
@@ -271,6 +287,7 @@
movl %edx, (%esp) /* &resp */
call _ffi_closure_SYSV_inner
movl -12(%ebp), %ecx
+.Lcls_return_result:
cmpl $FFI_TYPE_INT, %eax
je .Lcls_retint
cmpl $FFI_TYPE_FLOAT, %eax
Index: libffi/src/x86/ffi.c
===================================================================
--- libffi/src/x86/ffi.c (revision 243)
+++ libffi/src/x86/ffi.c (working copy)
@@ -227,6 +227,10 @@
__attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
__attribute__ ((regparm(1)));
+#ifdef X86_WIN32
+void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
+ __attribute__ ((regparm(1)));
+#endif
/* This function is jumped to by the trampoline */
@@ -302,13 +306,26 @@
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
- unsigned int __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \
+ unsigned int __dis = __fun - ((unsigned int) __tramp + 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 int __fun = (unsigned int)(FUN); \
+ unsigned int __ctx = (unsigned int)(CTX); \
+ unsigned int __dis = __fun - ((unsigned int) __tramp + 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 */
@@ -318,12 +335,24 @@
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
{
+#ifdef X86_WIN32
+ FFI_ASSERT (cif->abi == FFI_SYSV || cif->abi == FFI_STDCALL);
+#else
FFI_ASSERT (cif->abi == FFI_SYSV);
+#endif
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
&ffi_closure_SYSV, \
(void*)closure);
-
+
+#ifdef X86_WIN32
+ if (cif->abi == FFI_STDCALL) {
+ FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], \
+ &ffi_closure_STDCALL, \
+ (void*)closure, cif->bytes);
+ }
+#endif
+
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
Index: libffi/testsuite/libffi.call/closure_stdcall.c
===================================================================
--- libffi/testsuite/libffi.call/closure_stdcall.c (revision 0)
+++ libffi/testsuite/libffi.call/closure_stdcall.c (revision 376)
@@ -0,0 +1,72 @@
+/* Area: closure_call (stdcall convention)
+ Purpose: Check handling when caller expects stdcall callee
+ Limitations: none.
+ PR: none.
+ Originator: <twalljava@dev.java.net> */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+#include "ffitest.h"
+
+static void
+closure_test_stdcall(ffi_cif* cif __UNUSED__, void* resp, void** args,
+ void* userdata)
+{
+ *(ffi_arg*)resp =
+ (int)*(int *)args[0] + (int)(*(int *)args[1])
+ + (int)(*(int *)args[2]) + (int)(*(int *)args[3])
+ + (int)(long)userdata;
+
+ 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);
+
+int main (void)
+{
+ ffi_cif cif;
+#ifndef USING_MMAP
+ static ffi_closure cl;
+#endif
+ ffi_closure *pcl;
+ ffi_type * cl_arg_types[17];
+ int res;
+ void* sp_pre;
+ void* sp_post;
+ char buf[1024];
+
+#ifdef USING_MMAP
+ pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+ pcl = &cl;
+#endif
+
+ cl_arg_types[0] = &ffi_type_uint;
+ cl_arg_types[1] = &ffi_type_uint;
+ cl_arg_types[2] = &ffi_type_uint;
+ cl_arg_types[3] = &ffi_type_uint;
+ cl_arg_types[4] = NULL;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 4,
+ &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+ CHECK(ffi_prep_closure(pcl, &cif, closure_test_stdcall,
+ (void *) 3 /* userdata */) == FFI_OK);
+
+ asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
+ res = (*(closure_test_type0)pcl)(0, 1, 2, 3);
+ asm volatile (" movl %%esp,%0" : "=g" (sp_post));
+ /* { 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" } */
+ exit(0);
+}
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: libffi stdcall closures
2007-11-09 1:07 ` Timothy Wall
@ 2007-11-13 23:28 ` Tom Tromey
2007-11-13 23:32 ` Timothy Wall
0 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2007-11-13 23:28 UTC (permalink / raw)
To: Timothy Wall; +Cc: gcc-patches
>>>>> "Timothy" == Timothy Wall <twalljava@dev.java.net> writes:
Timothy> Here's the patch for stdcall closures, including a basic test. The
Timothy> diff is against the JNA repo; I can probably do one against a gcc
Timothy> checkout if necessary.
I'm not really an x86 expert, so perhaps a port maintainer could look
it over. The test case also looked good at first blush, but Andreas
is really the person for that...
I have a couple nits to pick, but nothing major.
Timothy> BTW, the lack of support came up as people were trying to install
Timothy> Java callbacks into various windows API functions (services, keyboard
Timothy> hooks, etc). Some would work fine, others would crash. I wasn't
Timothy> aware that libffi didn't have stdcall closure support since the few
Timothy> simple tests and examples I wrote just happened to work.
FWIW there are other areas where you may run into problems. The
biggest one is varargs -- libffi basically doesn't support this at
all. I'm sure there are more obscure ones, too, involving any new ABI
additions... maybe vectors, or decimal float, or I don't know what.
Timothy> +#ifdef X86_WIN32
Timothy> + if (cif->abi == FFI_STDCALL) {
Timothy> + FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], \
Timothy> + &ffi_closure_STDCALL, \
Timothy> + (void*)closure, cif->bytes);
Timothy> + }
Timothy> +#endif
You don't need the backslashes here. I see them elsewhere in the
file, but they are bogus. Also the "{" should be on its own line.
Also, it looks to me as though there's a missing 'else' in
here... shouldn't we call either FFI_INIT_TRAMPOLINE_STDCALL or
FFI_INIT_TRAMPOLINE, but not both?
thanks,
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: libffi stdcall closures
2007-11-13 23:28 ` Tom Tromey
@ 2007-11-13 23:32 ` Timothy Wall
0 siblings, 0 replies; 6+ messages in thread
From: Timothy Wall @ 2007-11-13 23:32 UTC (permalink / raw)
To: tromey; +Cc: gcc-patches
On Nov 13, 2007, at 4:08 PM, Tom Tromey wrote:
>>>>>> "Timothy" == Timothy Wall <twalljava@dev.java.net> writes:
>
> Timothy> Here's the patch for stdcall closures, including a basic
> test. The
> Timothy> diff is against the JNA repo; I can probably do one
> against a gcc
> Timothy> checkout if necessary.
>
> I'm not really an x86 expert, so perhaps a port maintainer could look
> it over. The test case also looked good at first blush, but Andreas
> is really the person for that...
Should I ping him directly?
>
> I have a couple nits to pick, but nothing major.
>
> FWIW there are other areas where you may run into problems. The
> biggest one is varargs -- libffi basically doesn't support this at
> all. I'm sure there are more obscure ones, too, involving any new ABI
> additions... maybe vectors, or decimal float, or I don't know what.
Do you mean varargs out or varargs in closures? I'm not too worried
about varargs in closures, and varargs calls through libffi seem to
work ok in the platforms we've tried so far.
>
> Timothy> +#ifdef X86_WIN32
> Timothy> + if (cif->abi == FFI_STDCALL) {
> Timothy> + FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], \
> Timothy> + &ffi_closure_STDCALL, \
> Timothy> + (void*)closure, cif-
> >bytes);
> Timothy> + }
> Timothy> +#endif
>
> You don't need the backslashes here. I see them elsewhere in the
> file, but they are bogus. Also the "{" should be on its own line.
>
> Also, it looks to me as though there's a missing 'else' in
> here... shouldn't we call either FFI_INIT_TRAMPOLINE_STDCALL or
> FFI_INIT_TRAMPOLINE, but not both?
That's just me trying to avoid intersecting conditional code with
logic constructs.
Following is a better construct, dropping the somewhat useless
ASSERTions:
> if (cif->abi == FFI_SYSV)
> {
> FFI_INIT_TRAMPOLINE (&closure->tramp[0],
> &ffi_closure_SYSV,
> (void*)closure);
> }
> #ifdef X86_WIN32
> else if (cif->abi == FFI_STDCALL)
> {
> FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
> &ffi_closure_STDCALL,
> (void*)closure, cif->bytes);
> }
> #endif
> else
> {
> return FFI_BAD_ABI;
> }
>
I'm looking over the JNA standalone libffi config changes and will
post those separately.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-11-13 22:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-08 16:09 libffi stdcall closures Timothy Wall
2007-11-08 19:11 ` Tom Tromey
2007-11-08 22:19 ` Timothy Wall
2007-11-09 1:07 ` Timothy Wall
2007-11-13 23:28 ` Tom Tromey
2007-11-13 23:32 ` Timothy Wall
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).