Add Tim Wall's x86 windows patch.
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
2008-01-31 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.
|
||||||
|
|
||||||
2008-01-30 H.J. Lu <hongjiu.lu@intel.com>
|
2008-01-30 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
PR libffi/34612
|
PR libffi/34612
|
||||||
|
|||||||
@@ -235,6 +235,10 @@ unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
|
|||||||
__attribute__ ((regparm(1)));
|
__attribute__ ((regparm(1)));
|
||||||
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
|
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
|
||||||
__attribute__ ((regparm(1)));
|
__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 */
|
/* This function is jumped to by the trampoline */
|
||||||
|
|
||||||
@@ -317,6 +321,19 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
|
|||||||
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
|
*(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 + FFI_TRAMPOLINE_SIZE); \
|
||||||
|
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 */
|
/* the cif must already be prep'ed */
|
||||||
|
|
||||||
@@ -327,11 +344,24 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|||||||
void *user_data,
|
void *user_data,
|
||||||
void *codeloc)
|
void *codeloc)
|
||||||
{
|
{
|
||||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
if (cif->abi == FFI_SYSV)
|
||||||
|
{
|
||||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
FFI_INIT_TRAMPOLINE (&closure->tramp[0],
|
||||||
&ffi_closure_SYSV, \
|
&ffi_closure_SYSV,
|
||||||
codeloc);
|
(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;
|
||||||
|
}
|
||||||
|
|
||||||
closure->cif = cif;
|
closure->cif = cif;
|
||||||
closure->user_data = user_data;
|
closure->user_data = user_data;
|
||||||
@@ -353,7 +383,9 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
if (cif->abi != FFI_SYSV) {
|
||||||
|
return FFI_BAD_ABI;
|
||||||
|
}
|
||||||
|
|
||||||
// we currently don't support certain kinds of arguments for raw
|
// we currently don't support certain kinds of arguments for raw
|
||||||
// closures. This should be implemented by a separate assembly language
|
// closures. This should be implemented by a separate assembly language
|
||||||
|
|||||||
@@ -77,7 +77,11 @@ typedef enum ffi_abi {
|
|||||||
#define FFI_TRAMPOLINE_SIZE 24
|
#define FFI_TRAMPOLINE_SIZE 24
|
||||||
#define FFI_NATIVE_RAW_API 0
|
#define FFI_NATIVE_RAW_API 0
|
||||||
#else
|
#else
|
||||||
|
#ifdef X86_WIN32
|
||||||
|
#define FFI_TRAMPOLINE_SIZE 13
|
||||||
|
#else
|
||||||
#define FFI_TRAMPOLINE_SIZE 10
|
#define FFI_TRAMPOLINE_SIZE 10
|
||||||
|
#endif
|
||||||
#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
|
#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -258,6 +258,22 @@ sc_epilogue:
|
|||||||
|
|
||||||
.ffi_call_STDCALL_end:
|
.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
|
.globl _ffi_closure_SYSV
|
||||||
_ffi_closure_SYSV:
|
_ffi_closure_SYSV:
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
@@ -271,6 +287,7 @@ _ffi_closure_SYSV:
|
|||||||
movl %edx, (%esp) /* &resp */
|
movl %edx, (%esp) /* &resp */
|
||||||
call _ffi_closure_SYSV_inner
|
call _ffi_closure_SYSV_inner
|
||||||
movl -12(%ebp), %ecx
|
movl -12(%ebp), %ecx
|
||||||
|
.Lcls_return_result:
|
||||||
cmpl $FFI_TYPE_INT, %eax
|
cmpl $FFI_TYPE_INT, %eax
|
||||||
je .Lcls_retint
|
je .Lcls_retint
|
||||||
cmpl $FFI_TYPE_FLOAT, %eax
|
cmpl $FFI_TYPE_FLOAT, %eax
|
||||||
|
|||||||
72
libffi/testsuite/libffi.call/closure_stdcall.c
Normal file
72
libffi/testsuite/libffi.call/closure_stdcall.c
Normal file
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user