* 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).