This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi, this patch adds missing support of the X86_WIN32 calling-convention for thiscall-closures. ?As thiscall-convention can be only used in C++ for class-member calls, the assumption that first argument gets passed in register is always valid. ?As it is either the "this" pointer, or the structure-aggregate-return-pointer. This patch is necessary to fix on gcc's trunk the PR 51500 completely. ChangeLog 2012-01-31 ?Kai Tietz ?<ktietz@redhat.com> ? ? ? ?* src/prep_cif.c (ffi_prep_cif): Allow for X86_WIN32 ? ? ? ?also FFI_THISCALL. ? ? ? ?* src/x86/ffi.c (ffi_closure_THISCALL): Add prototype. ? ? ? ?(FFI_INIT_TRAMPOLINE_THISCALL): New trampoline code. ? ? ? ?(ffi_prep_closure_loc): Add FFI_THISCALL support. ? ? ? ?* src/x86/ffitarget.h (FFI_TRAMPOLINE_SIZE): Adjust size. ? ? ? ?* src/x86/win32.S (ffi_closure_THISCALL): New closure code ? ? ? ?for thiscall-calling convention. ? ? ? ?* testsuite/libffi.call/closure_thiscall.c: New test. Regression tested for i686-w64-mingw32, i686-pc-cygwin, and x86_64-unknown-linux-gnu. ?Ok for apply? Regards, Kai Index: gcc/libffi/src/prep_cif.c =================================================================== --- gcc.orig/libffi/src/prep_cif.c +++ gcc/libffi/src/prep_cif.c @@ -93,7 +93,12 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ff ? ffi_type **ptr; ? FFI_ASSERT(cif != NULL); +#ifndef X86_WIN32 ? FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); +#else + ?FFI_ASSERT(abi > FFI_FIRST_ABI && abi <= FFI_DEFAULT_ABI + ? ? ? ? ? ?|| abi == FFI_THISCALL); +#endif ? cif->abi = abi; ? cif->arg_types = atypes; Index: gcc/libffi/src/x86/ffi.c =================================================================== --- gcc.orig/libffi/src/x86/ffi.c +++ gcc/libffi/src/x86/ffi.c @@ -449,6 +449,8 @@ void FFI_HIDDEN ffi_closure_raw_SYSV (ff ?#ifdef X86_WIN32 ?void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *) ? ? ?__attribute__ ((regparm(1))); +void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *) + ? ? __attribute__ ((regparm(1))); ?#endif ?#ifdef X86_WIN64 ?void FFI_HIDDEN ffi_closure_win64 (ffi_closure *); @@ -608,6 +610,24 @@ ffi_prep_incoming_args_SYSV(char *stack, ? ?*(unsigned int*) ?&__tramp[6] = __dis; /* jmp __fun ?*/ \ ?} +#define FFI_INIT_TRAMPOLINE_THISCALL(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 - (__ctx + 22); ?\ + ? unsigned short __size = (unsigned short)(SIZE); \ + ? *(unsigned int *) &__tramp[0] = 0x8924048b; /* mov (%esp), %eax */ \ + ? *(unsigned int *) &__tramp[4] = 0xec83240c; /* mov %ecx, (%esp) */ \ + ? *(unsigned int *) &__tramp[8] = 0x24048904; /* sub $4,(%esp) */ \ + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* mov %eax, (%esp) */ \ + ? *(unsigned char*) &__tramp[12] = 0xb8; \ + ? *(unsigned int*) ?&__tramp[13] = __ctx; /* movl __ctx, %eax */ \ + ? *(unsigned char *) ?&__tramp[17] = 0xe8; \ + ? *(unsigned int*) ?&__tramp[18] = __dis; /* call __fun ?*/ \ + ? *(unsigned char*) ?&__tramp[22] = 0xc2; /* ret ?*/ \ + ? *(unsigned short*) ?&__tramp[23] = __size; /* ret __size ?*/ \ + } + ?#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) ?\ ?{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ ? ?unsigned int ?__fun = (unsigned int)(FUN); \ @@ -650,6 +670,13 @@ ffi_prep_closure_loc (ffi_closure* closu ? ? ? ? ? ? ? ? ? ? ? ? ? ?(void*)codeloc); ? ? } ?#ifdef X86_WIN32 + ?else if (cif->abi == FFI_THISCALL) + ? ?{ + ? ? ?FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &ffi_closure_THISCALL, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (void*)codeloc, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cif->bytes); + ? ?} ? else if (cif->abi == FFI_STDCALL) ? ? { ? ? ? FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], Index: gcc/libffi/src/x86/ffitarget.h =================================================================== --- gcc.orig/libffi/src/x86/ffitarget.h +++ gcc/libffi/src/x86/ffitarget.h @@ -103,7 +103,7 @@ typedef enum ffi_abi { ?#define FFI_NATIVE_RAW_API 0 ?#else ?#ifdef X86_WIN32 -#define FFI_TRAMPOLINE_SIZE 13 +#define FFI_TRAMPOLINE_SIZE 25 ?#else ?#ifdef X86_WIN64 ?#define FFI_TRAMPOLINE_SIZE 29 Index: gcc/libffi/src/x86/win32.S =================================================================== --- gcc.orig/libffi/src/x86/win32.S +++ gcc/libffi/src/x86/win32.S @@ -170,6 +170,16 @@ ca_epilogue: ? ? ? ? ret ?ffi_call_win32 ENDP +ffi_closure_THISCALL PROC NEAR FORCEFRAME + ? ? ? push ? ?ebp + ? ? ? mov ? ? ebp, esp + ? ? ? sub ? ? esp, 40 + ? ? ? lea ? ? edx, [ebp -24] + ? ? ? mov ? ? [ebp - 12], edx /* resp */ + ? ? ? lea ? ? edx, [ebp + 12] ?/* account for stub return address on stack */ + ? ? ? jmp ? ? stub +ffi_closure_THISCALL ENDP + ?ffi_closure_SYSV PROC NEAR FORCEFRAME ? ? ;; the ffi_closure ctx is passed in eax by the trampoline. @@ -177,6 +187,7 @@ ffi_closure_SYSV PROC NEAR FORCEFRAME ? ? ? ? lea ?edx, [ebp - 24] ? ? ? ? mov ?[ebp - 12], edx ? ? ? ? ;; resp ? ? ? ? lea ?edx, [ebp + 8] +stub: ? ? ? ? mov ?[esp + 8], edx ? ? ? ? ?;; args ? ? ? ? lea ?edx, [ebp - 12] ? ? ? ? mov ?[esp + 4], edx ? ? ? ? ?;; &resp @@ -573,6 +584,19 @@ _ffi_call_win32: ? ? ? ? popl %ebp ? ? ? ? ret ?.ffi_call_win32_end: + ? ? ? ?.balign 16 + ? ? ? .globl ?_ffi_closure_THISCALL +#ifndef __OS2__ + ? ? ? .def ? ?_ffi_closure_THISCALL; ?.scl ? ?2; ? ? ?.type ? 32; ? ? .endef +#endif +_ffi_closure_THISCALL: + ? ? ? 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 */ + ? ? ? jmp ? ? .stub ?.LFE1: ? ? ? ? # This assumes we are using gas. @@ -591,6 +615,7 @@ _ffi_closure_SYSV: ? ? ? ?leal ? ?-24(%ebp), %edx ? ? ? ?movl ? ?%edx, -12(%ebp) /* resp */ ? ? ? ?leal ? ?8(%ebp), %edx +.stub: ? ? ? ?movl ? ?%edx, 4(%esp) ? /* args = __builtin_dwarf_cfa () */ ? ? ? ?leal ? ?-12(%ebp), %edx ? ? ? ?movl ? ?%edx, (%esp) ? ?/* &resp */ Index: gcc/libffi/testsuite/libffi.call/closure_thiscall.c =================================================================== --- /dev/null +++ gcc/libffi/testsuite/libffi.call/closure_thiscall.c @@ -0,0 +1,64 @@ +/* Area: ? ? ? closure_call (thiscall convention) + ? Purpose: ? ?Check handling when caller expects thiscall callee + ? Limitations: ? ? ? ?none. + ? PR: ? ? ? ? none. + ? Originator: <ktietz@redhat.com> */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ +#include "ffitest.h" + +static void +closure_test_thiscall(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)(intptr_t)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 (__thiscall *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; + ?void* sp_pre; + ?void* sp_post; + ?char buf[1024]; + + ?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_THISCALL, 4, + ? ? ? ? ? ? ? ? ? ?&ffi_type_sint, cl_arg_types) == FFI_OK); + + ?CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_thiscall, + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (void *) 3 /* userdata */, code) == FFI_OK); + + ?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)); + ?/* { 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); +} -- |? (\_/) This is Bunny. Copy and paste | (='.'=) Bunny into your signature to help | (")_(") him gain world domination
Attachment:
pr51500_libffi_tc_closure.txt
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |