From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8422 invoked by alias); 8 Nov 2007 23:26:12 -0000 Received: (qmail 8413 invoked by uid 22791); 8 Nov 2007 23:26:11 -0000 X-Spam-Check-By: sourceware.org Received: from mx10.gnu.org (HELO mx10.gnu.org) (199.232.76.166) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 08 Nov 2007 23:26:04 +0000 Received: from vms044pub.verizon.net ([206.46.252.44]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1IqGkm-0000Cx-Tb for gcc-patches@gcc.gnu.org; Thu, 08 Nov 2007 18:25:41 -0500 Received: from [172.16.1.34] ([72.85.201.226]) by vms044.mailsrvcs.net (Sun Java System Messaging Server 6.2-6.01 (built Apr 3 2006)) with ESMTPA id <0JR7008ONNP9M090@vms044.mailsrvcs.net> for gcc-patches@gcc.gnu.org; Thu, 08 Nov 2007 17:24:46 -0600 (CST) Date: Fri, 09 Nov 2007 01:07:00 -0000 From: Timothy Wall Subject: Re: libffi stdcall closures In-reply-to: To: gcc-patches@gcc.gnu.org Message-id: <6F9E5081-D1B5-4D4C-9FC1-D90D22709C9D@dev.java.net> MIME-version: 1.0 (Apple Message framework v752.2) X-Mailer: Apple Mail (2.752.2) Content-type: multipart/mixed; boundary=Apple-Mail-3--638764077 References: <8269E7B3-A99E-42AC-9314-2613A1C26ABF@users.sf.net> X-detected-kernel: by monty-python.gnu.org: Solaris 9.1 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-11/txt/msg00496.txt.bz2 --Apple-Mail-3--638764077 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed Content-length: 498 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. --Apple-Mail-3--638764077 Content-Transfer-Encoding: 7bit Content-Type: text/plain; x-unix-mode=0664; name=diffs.txt Content-Disposition: attachment; filename=diffs.txt Content-length: 6605 Index: libffi/ChangeLog =================================================================== --- libffi/ChangeLog (revision 243) +++ libffi/ChangeLog (working copy) @@ -1,3 +1,12 @@ +2007-11-08 Timothy Wall + + * 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: */ + +/* { 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); +} --Apple-Mail-3--638764077--