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 all, I've finished my port of libffi to x86/msvc. There are three patches attached, against 3.0.9. Anthony, if these look okay to you, could you please apply? Details: These avoid hacks to the build system by using Timothy Wall's idea of a wrapper script, 'cc.sh', which acts like gcc but translates commandline args and calls cl/ml appropriately. (I've attached it in case anyone wants to test; I don't think it should be merged, but if we can get it to be generic enough then perhaps it could be.) Patches are built and tested on i686-pc-linux-gnu, i686-pc-mingw32 (with MSVC), and i386-apple-darwin9.2.0, using Mozilla's testsuite. This tests ffi_call extensively and ffi_closure_SYSV somewhat, but does not test the raw API. (Any assistance in doing this would be greatly appreciated.) For MSVC, libffi was configured with configure --enable-shared --enable-static CC=path/to/cc.sh LD=link CPP=\"cl -nologo -EP\" Patch descriptions are below. The first patch consolidates the stack space allocation code; it's currently fragmented between ffi_prep_cif and ffi_prep_cif_machdep depending on X86, X86_DARWIN, or X86_WIN64, which made it somewhat hard to read. The second merges ffi_call_SYSV and ffi_call_STDCALL since they're identical. The third fixes a few MSVC syntax errors and adds the assembly routines. The assembly for MSVC is a direct translation of existing win32 assembly, with the exception of sint8/uint8/sint16/uint16 return type handling. Zero- or sign-extending these into a 4-byte register or memory location is unnecessary, and in the case of ffi_call, wrong - it means we're writing 4 bytes into a memory slot that may only hold 1 or 2 bytes. MSVC does not extend when compiling a C function that returns 1 or 2 bytes. (I can write a followup patch to change the other x86 platforms, as appropriate.) [libffi-part1-x86-stack-alloc-machdep-1] 2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to ffi_prep_cif_machdep for x86. * src/x86/ffi.c (ffi_prep_cif_machdep): To here. [libffi-part2-ffi_call_win32-1] 2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new function ffi_call_win32 on X86_WIN32. * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32. (ffi_call_STDCALL): Remove. [libffi-part3-msvc-port-1] 2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/x86/win32.S: Port assembly routines to MSVC and #ifdef. * src/x86/ffi.c: Tweak function declaration and remove excess parens. * include/ffi.h.in: Add __declspec(align(8)) to typedef struct ffi_closure.
2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new function ffi_call_win32 on X86_WIN32. * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32. (ffi_call_STDCALL): Remove. diff --git a/libffi/ChangeLog b/libffi/ChangeLog --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,8 +1,14 @@ +2010-01-12 Daniel Witte <dwitte@mozilla.com> + * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new + function ffi_call_win32 on X86_WIN32. + * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32. + (ffi_call_STDCALL): Remove. + 2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to ffi_prep_cif_machdep for x86. * src/x86/ffi.c (ffi_prep_cif_machdep): To here. 2009-12-28 David Edelsohn <edelsohn@gnu.org> * src/powerpc/ffi_darwin.c (ffi_prep_args): Copy abi and nargs to diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c --- a/libffi/src/x86/ffi.c +++ b/libffi/src/x86/ffi.c @@ -240,28 +240,27 @@ ffi_status ffi_prep_cif_machdep(ffi_cif #ifdef X86_DARWIN cif->bytes = (cif->bytes + 15) & ~0xF; #endif return FFI_OK; } -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); - -#ifdef X86_WIN32 -extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); - -#endif /* X86_WIN32 */ #ifdef X86_WIN64 extern int ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); +#elif defined(X86_WIN32) +extern void +ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, + unsigned, unsigned, unsigned *, void (*fn)(void)); +#else +extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, + unsigned, unsigned, unsigned *, void (*fn)(void)); #endif void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { extended_cif ecif; ecif.cif = cif; ecif.avalue = avalue; @@ -309,28 +308,28 @@ void ffi_call(ffi_cif *cif, void (*fn)(v memcpy(local, avalue[i], size); avalue[i] = local; } } ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); } break; +#elif defined(X86_WIN32) + case FFI_SYSV: + case FFI_STDCALL: + ffi_call_win32(ffi_prep_args, &ecif, cif->bytes, cif->flags, + ecif.rvalue, fn); + break; #else case FFI_SYSV: ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); break; -#ifdef X86_WIN32 - case FFI_STDCALL: - ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; -#endif /* X86_WIN32 */ -#endif /* X86_WIN64 */ +#endif default: FFI_ASSERT(0); break; } } /** private members **/ @@ -615,26 +614,16 @@ ffi_prep_args_raw(char *stack, extended_ memcpy (stack, ecif->avalue, ecif->cif->bytes); } /* we borrow this routine from libffi (it must be changed, though, to * actually call the function passed in the first argument. as of * libffi-1.20, this is not the case.) */ -extern void -ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, - unsigned, unsigned *, void (*fn)(void)); - -#ifdef X86_WIN32 -extern void -ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned, - unsigned, unsigned *, void (*fn)(void)); -#endif /* X86_WIN32 */ - void ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) { extended_cif ecif; void **avalue = (void **)fake_avalue; ecif.cif = cif; ecif.avalue = avalue; @@ -648,26 +637,28 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(vo ecif.rvalue = alloca(cif->rtype->size); } else ecif.rvalue = rvalue; switch (cif->abi) { +#ifdef X86_WIN32 + case FFI_SYSV: + case FFI_STDCALL: + ffi_call_win32(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, + ecif.rvalue, fn); + break; +#else case FFI_SYSV: ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); break; -#ifdef X86_WIN32 - case FFI_STDCALL: - ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; -#endif /* X86_WIN32 */ +#endif default: FFI_ASSERT(0); break; } } #endif diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S --- a/libffi/src/x86/win32.S +++ b/libffi/src/x86/win32.S @@ -31,19 +31,19 @@ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> .text # This assumes we are using gas. .balign 16 - .globl _ffi_call_SYSV - .def _ffi_call_SYSV; .scl 2; .type 32; .endef -_ffi_call_SYSV: + .globl _ffi_call_win32 + .def _ffi_call_win32; .scl 2; .type 32; .endef +_ffi_call_win32: .LFB1: pushl %ebp .LCFI0: movl %esp,%ebp .LCFI1: # Make room for all of the new args. movl 16(%ebp),%ecx subl %ecx,%esp @@ -56,18 +56,20 @@ _ffi_call_SYSV: call *8(%ebp) # Return stack to previous state and call the function addl $8,%esp # FIXME: Align the stack to a 128-bit boundary to avoid # potential performance hits. - call *28(%ebp) + call *28(%ebp) + # stdcall functions pop arguments off the stack themselves + # Load %ecx with the return type code movl 20(%ebp),%ecx # If the return value pointer is NULL, assume no return value. cmpl $0,24(%ebp) jne 0f # Even if there is no space for the return value, we are @@ -176,174 +178,21 @@ 1: .Lretstruct: # Nothing to do! .Lnoretval: .Lepilogue: movl %ebp,%esp popl %ebp ret -.ffi_call_SYSV_end: +.ffi_call_win32_end: .LFE1: # This assumes we are using gas. .balign 16 - .globl _ffi_call_STDCALL - .def _ffi_call_STDCALL; .scl 2; .type 32; .endef -_ffi_call_STDCALL: -.LFB2: - pushl %ebp -.LCFI2: - movl %esp,%ebp -.LCFI3: - # Make room for all of the new args. - movl 16(%ebp),%ecx - subl %ecx,%esp - - movl %esp,%eax - - # Place all of the ffi_prep_args in position - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - # Return stack to previous state and call the function - addl $8,%esp - - # FIXME: Align the stack to a 128-bit boundary to avoid - # potential performance hits. - - call *28(%ebp) - - # stdcall functions pop arguments off the stack themselves - - # Load %ecx with the return type code - movl 20(%ebp),%ecx - - # If the return value pointer is NULL, assume no return value. - cmpl $0,24(%ebp) - jne 0f - - # Even if there is no space for the return value, we are - # obliged to handle floating-point values. - cmpl $FFI_TYPE_FLOAT,%ecx - jne .Lsc_noretval - fstp %st(0) - - jmp .Lsc_epilogue - -0: - call 1f - # Do not insert anything here between the call and the jump table. -.Lsc_store_table: - .long .Lsc_noretval /* FFI_TYPE_VOID */ - .long .Lsc_retint /* FFI_TYPE_INT */ - .long .Lsc_retfloat /* FFI_TYPE_FLOAT */ - .long .Lsc_retdouble /* FFI_TYPE_DOUBLE */ - .long .Lsc_retlongdouble /* FFI_TYPE_LONGDOUBLE */ - .long .Lsc_retuint8 /* FFI_TYPE_UINT8 */ - .long .Lsc_retsint8 /* FFI_TYPE_SINT8 */ - .long .Lsc_retuint16 /* FFI_TYPE_UINT16 */ - .long .Lsc_retsint16 /* FFI_TYPE_SINT16 */ - .long .Lsc_retint /* FFI_TYPE_UINT32 */ - .long .Lsc_retint /* FFI_TYPE_SINT32 */ - .long .Lsc_retint64 /* FFI_TYPE_UINT64 */ - .long .Lsc_retint64 /* FFI_TYPE_SINT64 */ - .long .Lsc_retstruct /* FFI_TYPE_STRUCT */ - .long .Lsc_retint /* FFI_TYPE_POINTER */ - .long .Lsc_retstruct1b /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lsc_retstruct2b /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lsc_retstruct4b /* FFI_TYPE_SMALL_STRUCT_4B */ - -1: - add %ecx, %ecx - add %ecx, %ecx - add (%esp),%ecx - add $4, %esp - jmp *(%ecx) - - /* Sign/zero extend as appropriate. */ -.Lsc_retsint8: - movsbl %al, %eax - jmp .Lsc_retint - -.Lsc_retsint16: - movswl %ax, %eax - jmp .Lsc_retint - -.Lsc_retuint8: - movzbl %al, %eax - jmp .Lsc_retint - -.Lsc_retuint16: - movzwl %ax, %eax - jmp .Lsc_retint - -.Lsc_retint: - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - jmp .Lsc_epilogue - -.Lsc_retfloat: - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstps (%ecx) - jmp .Lsc_epilogue - -.Lsc_retdouble: - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp .Lsc_epilogue - -.Lsc_retlongdouble: - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp .Lsc_epilogue - -.Lsc_retint64: - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp .Lsc_epilogue - -.Lsc_retstruct1b: - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movb %al,0(%ecx) - jmp .Lsc_epilogue - -.Lsc_retstruct2b: - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movw %ax,0(%ecx) - jmp .Lsc_epilogue - -.Lsc_retstruct4b: - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - jmp .Lsc_epilogue - -.Lsc_retstruct: - # Nothing to do! - -.Lsc_noretval: -.Lsc_epilogue: - movl %ebp,%esp - popl %ebp - ret -.ffi_call_STDCALL_end: -.LFE2: - - # This assumes we are using gas. - .balign 16 .globl _ffi_closure_SYSV .def _ffi_closure_SYSV; .scl 2; .type 32; .endef _ffi_closure_SYSV: .LFB3: pushl %ebp .LCFI4: movl %esp, %ebp .LCFI5: @@ -737,48 +586,16 @@ 1: .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ .byte 0x5 /* .uleb128 0x5 */ /* End of DW_CFA_xxx CFI instructions. */ .align 4 .LEFDE1: -.LSFDE2: - .long .LEFDE2-.LASFDE2 /* FDE Length */ -.LASFDE2: - .long .LASFDE2-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB2-. /* FDE initial location */ -#else - .long .LFB2 -#endif - .long .LFE2-.LFB2 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI2-.LFB2 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI3-.LCFI2 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE2: - - .LSFDE3: .long .LEFDE3-.LASFDE3 /* FDE Length */ .LASFDE3: .long .LASFDE3-.Lframe1 /* FDE CIE offset */ #if defined __PIC__ && defined HAVE_AS_X86_PCREL .long .LFB3-. /* FDE initial location */ #else .long .LFB3
2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/x86/win32.S: Port assembly routines to MSVC and #ifdef. * src/x86/ffi.c: Tweak function declaration and remove excess parens. * include/ffi.h.in: Add __declspec(align(8)) to typedef struct ffi_closure. diff --git a/libffi/ChangeLog b/libffi/ChangeLog --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,8 +1,13 @@ +2010-01-12 Daniel Witte <dwitte@mozilla.com> + * src/x86/win32.S: Port assembly routines to MSVC and #ifdef. + * src/x86/ffi.c: Tweak function declaration and remove excess parens. + * include/ffi.h.in: Add __declspec(align(8)) to typedef struct ffi_closure. + 2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new function ffi_call_win32 on X86_WIN32. * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32. (ffi_call_STDCALL): Remove. 2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in --- a/libffi/include/ffi.h.in +++ b/libffi/include/ffi.h.in @@ -246,16 +246,19 @@ void ffi_java_raw_call (ffi_cif *cif, void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); size_t ffi_java_raw_size (ffi_cif *cif); /* ---- Definitions for closures ----------------------------------------- */ #if FFI_CLOSURES +#ifdef _MSC_VER +__declspec(align(8)) +#endif typedef struct { char tramp[FFI_TRAMPOLINE_SIZE]; ffi_cif *cif; void (*fun)(ffi_cif*,void*,void**,void*); void *user_data; #ifdef __GNUC__ } ffi_closure __attribute__((aligned (8))); #else diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c --- a/libffi/src/x86/ffi.c +++ b/libffi/src/x86/ffi.c @@ -329,16 +329,18 @@ void ffi_call(ffi_cif *cif, void (*fn)(v FFI_ASSERT(0); break; } } /** private members **/ +/* The following __attribute__((regparm(1))) decorations will have no effect + on MSVC - standard cdecl convention applies. */ static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, void** args, ffi_cif* cif); void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *) __attribute__ ((regparm(1))); unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *) __attribute__ ((regparm(1))); void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *) __attribute__ ((regparm(1))); @@ -377,21 +379,18 @@ ffi_closure_win64_inner (ffi_closure *cl result types except for floats; we have to 'mov xmm0, rax' in the caller to correct this. TODO: structure sizes of 3 5 6 7 are returned by reference, too!!! */ return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp; } #else -unsigned int FFI_HIDDEN -ffi_closure_SYSV_inner (closure, respp, args) - ffi_closure *closure; - void **respp; - void *args; +unsigned int FFI_HIDDEN __attribute__ ((regparm(1))) +ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args) { /* our various things... */ ffi_cif *cif; void **arg_area; cif = closure->cif; arg_area = (void**) alloca (cif->nargs * sizeof (void*)); @@ -492,39 +491,39 @@ ffi_prep_incoming_args_SYSV(char *stack, *(unsigned char *) &__tramp[26] = 0x41; \ *(unsigned char *) &__tramp[27] = 0xff; \ *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \ } /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */ #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ -({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ +{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ unsigned int __fun = (unsigned int)(FUN); \ unsigned int __ctx = (unsigned int)(CTX); \ unsigned int __dis = __fun - (__ctx + 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 char *__tramp = (unsigned char*)(TRAMP); \ unsigned int __fun = (unsigned int)(FUN); \ unsigned int __ctx = (unsigned int)(CTX); \ unsigned int __dis = __fun - (__ctx + 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 */ ffi_status ffi_prep_closure_loc (ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S --- a/libffi/src/x86/win32.S +++ b/libffi/src/x86/win32.S @@ -1,12 +1,13 @@ /* ----------------------------------------------------------------------- win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc. Copyright (c) 2001 John Beniton Copyright (c) 2002 Ranjit Mathew + Copyright (c) 2009 Daniel Witte X86 Foreign Function Interface Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, @@ -26,17 +27,374 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> - + +#ifdef _MSC_VER + +.386 +.MODEL FLAT, C + +EXTRN ffi_closure_SYSV_inner:NEAR + +_TEXT SEGMENT + +ffi_call_win32 PROC NEAR, + ffi_prep_args : NEAR PTR DWORD, + ecif : NEAR PTR DWORD, + cif_bytes : DWORD, + cif_flags : DWORD, + rvalue : NEAR PTR DWORD, + fn : NEAR PTR DWORD + + ;; Make room for all of the new args. + mov ecx, cif_bytes + sub esp, ecx + + mov eax, esp + + ;; Place all of the ffi_prep_args in position + push ecif + push eax + call ffi_prep_args + + ;; Return stack to previous state and call the function + add esp, 8 + + call fn + + ;; cdecl: we restore esp in the epilogue, so there's no need to + ;; remove the space we pushed for the args. + ;; stdcall: the callee has already cleaned the stack. + + ;; Load ecx with the return type code + mov ecx, cif_flags + + ;; If the return value pointer is NULL, assume no return value. + cmp rvalue, 0 + jne ca_jumptable + + ;; Even if there is no space for the return value, we are + ;; obliged to handle floating-point values. + cmp ecx, FFI_TYPE_FLOAT + jne ca_epilogue + fstp st(0) + + jmp ca_epilogue + +ca_jumptable: + jmp [ca_jumpdata + 4 * ecx] +ca_jumpdata: + ;; Do not insert anything here between label and jump table. + dd offset ca_epilogue ;; FFI_TYPE_VOID + dd offset ca_retint ;; FFI_TYPE_INT + dd offset ca_retfloat ;; FFI_TYPE_FLOAT + dd offset ca_retdouble ;; FFI_TYPE_DOUBLE + dd offset ca_retlongdouble ;; FFI_TYPE_LONGDOUBLE + dd offset ca_retint8 ;; FFI_TYPE_UINT8 + dd offset ca_retint8 ;; FFI_TYPE_SINT8 + dd offset ca_retint16 ;; FFI_TYPE_UINT16 + dd offset ca_retint16 ;; FFI_TYPE_SINT16 + dd offset ca_retint ;; FFI_TYPE_UINT32 + dd offset ca_retint ;; FFI_TYPE_SINT32 + dd offset ca_retint64 ;; FFI_TYPE_UINT64 + dd offset ca_retint64 ;; FFI_TYPE_SINT64 + dd offset ca_epilogue ;; FFI_TYPE_STRUCT + dd offset ca_retint ;; FFI_TYPE_POINTER + dd offset ca_retint8 ;; FFI_TYPE_SMALL_STRUCT_1B + dd offset ca_retint16 ;; FFI_TYPE_SMALL_STRUCT_2B + dd offset ca_retint ;; FFI_TYPE_SMALL_STRUCT_4B + +ca_retint8: + ;; Load %ecx with the pointer to storage for the return value + mov ecx, rvalue + mov [ecx + 0], al + jmp ca_epilogue + +ca_retint16: + ;; Load %ecx with the pointer to storage for the return value + mov ecx, rvalue + mov [ecx + 0], ax + jmp ca_epilogue + +ca_retint: + ;; Load %ecx with the pointer to storage for the return value + mov ecx, rvalue + mov [ecx + 0], eax + jmp ca_epilogue + +ca_retint64: + ;; Load %ecx with the pointer to storage for the return value + mov ecx, rvalue + mov [ecx + 0], eax + mov [ecx + 4], edx + jmp ca_epilogue + +ca_retfloat: + ;; Load %ecx with the pointer to storage for the return value + mov ecx, rvalue + fstp DWORD PTR [ecx] + jmp ca_epilogue + +ca_retdouble: + ;; Load %ecx with the pointer to storage for the return value + mov ecx, rvalue + fstp QWORD PTR [ecx] + jmp ca_epilogue + +ca_retlongdouble: + ;; Load %ecx with the pointer to storage for the return value + mov ecx, rvalue + fstp TBYTE PTR [ecx] + jmp ca_epilogue + +ca_epilogue: + ;; Epilogue code is autogenerated. + ret +ffi_call_win32 ENDP + +ffi_closure_SYSV PROC NEAR FORCEFRAME + ;; the ffi_closure ctx is passed in eax by the trampoline. + + sub esp, 40 + lea edx, [ebp - 24] + mov [ebp - 12], edx ;; resp + lea edx, [ebp + 8] + mov [esp + 8], edx ;; args + lea edx, [ebp - 12] + mov [esp + 4], edx ;; &resp + mov [esp], eax ;; closure + call ffi_closure_SYSV_inner + mov ecx, [ebp - 12] + +cs_jumptable: + jmp [cs_jumpdata + 4 * eax] +cs_jumpdata: + ;; Do not insert anything here between the label and jump table. + dd offset cs_epilogue ;; FFI_TYPE_VOID + dd offset cs_retint ;; FFI_TYPE_INT + dd offset cs_retfloat ;; FFI_TYPE_FLOAT + dd offset cs_retdouble ;; FFI_TYPE_DOUBLE + dd offset cs_retlongdouble ;; FFI_TYPE_LONGDOUBLE + dd offset cs_retint8 ;; FFI_TYPE_UINT8 + dd offset cs_retint8 ;; FFI_TYPE_SINT8 + dd offset cs_retint16 ;; FFI_TYPE_UINT16 + dd offset cs_retint16 ;; FFI_TYPE_SINT16 + dd offset cs_retint ;; FFI_TYPE_UINT32 + dd offset cs_retint ;; FFI_TYPE_SINT32 + dd offset cs_retint64 ;; FFI_TYPE_UINT64 + dd offset cs_retint64 ;; FFI_TYPE_SINT64 + dd offset cs_retstruct ;; FFI_TYPE_STRUCT + dd offset cs_retint ;; FFI_TYPE_POINTER + dd offset cs_retint8 ;; FFI_TYPE_SMALL_STRUCT_1B + dd offset cs_retint16 ;; FFI_TYPE_SMALL_STRUCT_2B + dd offset cs_retint ;; FFI_TYPE_SMALL_STRUCT_4B + +cs_retint8: + mov al, [ecx] + jmp cs_epilogue + +cs_retint16: + mov ax, [ecx] + jmp cs_epilogue + +cs_retint: + mov eax, [ecx] + jmp cs_epilogue + +cs_retint64: + mov eax, [ecx + 0] + mov edx, [ecx + 4] + jmp cs_epilogue + +cs_retfloat: + fld DWORD PTR [ecx] + jmp cs_epilogue + +cs_retdouble: + fld QWORD PTR [ecx] + jmp cs_epilogue + +cs_retlongdouble: + fld TBYTE PTR [ecx] + jmp cs_epilogue + +cs_retstruct: + ;; Caller expects us to pop struct return value pointer hidden arg. + ;; Epilogue code is autogenerated. + ret 4 + +cs_epilogue: + ;; Epilogue code is autogenerated. + ret +ffi_closure_SYSV ENDP + +#if !FFI_NO_RAW_API + +#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3) +#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) +#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) +#define CIF_FLAGS_OFFSET 20 + +ffi_closure_raw_SYSV PROC NEAR USES esi + ;; the ffi_closure ctx is passed in eax by the trampoline. + + sub esp, 40 + mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif + mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data + mov [esp + 12], edx ;; user_data + lea edx, [ebp + 8] + mov [esp + 8], edx ;; raw_args + lea edx, [ebp - 24] + mov [esp + 4], edx ;; &res + mov [esp], esi ;; cif + call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET] ;; closure->fun + mov eax, [esi + CIF_FLAGS_OFFSET] ;; cif->flags + lea ecx, [ebp - 24] + +cr_jumptable: + jmp [cr_jumpdata + 4 * eax] +cr_jumpdata: + ;; Do not insert anything here between the label and jump table. + dd offset cr_epilogue ;; FFI_TYPE_VOID + dd offset cr_retint ;; FFI_TYPE_INT + dd offset cr_retfloat ;; FFI_TYPE_FLOAT + dd offset cr_retdouble ;; FFI_TYPE_DOUBLE + dd offset cr_retlongdouble ;; FFI_TYPE_LONGDOUBLE + dd offset cr_retint8 ;; FFI_TYPE_UINT8 + dd offset cr_retint8 ;; FFI_TYPE_SINT8 + dd offset cr_retint16 ;; FFI_TYPE_UINT16 + dd offset cr_retint16 ;; FFI_TYPE_SINT16 + dd offset cr_retint ;; FFI_TYPE_UINT32 + dd offset cr_retint ;; FFI_TYPE_SINT32 + dd offset cr_retint64 ;; FFI_TYPE_UINT64 + dd offset cr_retint64 ;; FFI_TYPE_SINT64 + dd offset cr_epilogue ;; FFI_TYPE_STRUCT + dd offset cr_retint ;; FFI_TYPE_POINTER + dd offset cr_retint8 ;; FFI_TYPE_SMALL_STRUCT_1B + dd offset cr_retint16 ;; FFI_TYPE_SMALL_STRUCT_2B + dd offset cr_retint ;; FFI_TYPE_SMALL_STRUCT_4B + +cr_retint8: + mov al, [ecx] + jmp cr_epilogue + +cr_retint16: + mov ax, [ecx] + jmp cr_epilogue + +cr_retint: + mov eax, [ecx] + jmp cr_epilogue + +cr_retint64: + mov eax, [ecx + 0] + mov edx, [ecx + 4] + jmp cr_epilogue + +cr_retfloat: + fld DWORD PTR [ecx] + jmp cr_epilogue + +cr_retdouble: + fld QWORD PTR [ecx] + jmp cr_epilogue + +cr_retlongdouble: + fld TBYTE PTR [ecx] + jmp cr_epilogue + +cr_epilogue: + ;; Epilogue code is autogenerated. + ret +ffi_closure_raw_SYSV ENDP + +#endif /* !FFI_NO_RAW_API */ + +ffi_closure_STDCALL PROC NEAR FORCEFRAME + ;; the ffi_closure ctx is passed in eax by the trampoline. + + sub esp, 40 + lea edx, [ebp - 24] + mov [ebp - 12], edx ;; resp + lea edx, [ebp + 12] ;; account for stub return address on stack + mov [esp + 8], edx ;; args + lea edx, [ebp - 12] + mov [esp + 4], edx ;; &resp + mov [esp], eax ;; closure + call ffi_closure_SYSV_inner + mov ecx, [ebp - 12] + +cd_jumptable: + jmp [cd_jumpdata + 4 * eax] +cd_jumpdata: + ;; Do not insert anything here between the label and jump table. + dd offset cd_epilogue ;; FFI_TYPE_VOID + dd offset cd_retint ;; FFI_TYPE_INT + dd offset cd_retfloat ;; FFI_TYPE_FLOAT + dd offset cd_retdouble ;; FFI_TYPE_DOUBLE + dd offset cd_retlongdouble ;; FFI_TYPE_LONGDOUBLE + dd offset cd_retint8 ;; FFI_TYPE_UINT8 + dd offset cd_retint8 ;; FFI_TYPE_SINT8 + dd offset cd_retint16 ;; FFI_TYPE_UINT16 + dd offset cd_retint16 ;; FFI_TYPE_SINT16 + dd offset cd_retint ;; FFI_TYPE_UINT32 + dd offset cd_retint ;; FFI_TYPE_SINT32 + dd offset cd_retint64 ;; FFI_TYPE_UINT64 + dd offset cd_retint64 ;; FFI_TYPE_SINT64 + dd offset cd_epilogue ;; FFI_TYPE_STRUCT + dd offset cd_retint ;; FFI_TYPE_POINTER + dd offset cd_retint8 ;; FFI_TYPE_SMALL_STRUCT_1B + dd offset cd_retint16 ;; FFI_TYPE_SMALL_STRUCT_2B + dd offset cd_retint ;; FFI_TYPE_SMALL_STRUCT_4B + +cd_retint8: + mov al, [ecx] + jmp cd_epilogue + +cd_retint16: + mov ax, [ecx] + jmp cd_epilogue + +cd_retint: + mov eax, [ecx] + jmp cd_epilogue + +cd_retint64: + mov eax, [ecx + 0] + mov edx, [ecx + 4] + jmp cd_epilogue + +cd_retfloat: + fld DWORD PTR [ecx] + jmp cd_epilogue + +cd_retdouble: + fld QWORD PTR [ecx] + jmp cd_epilogue + +cd_retlongdouble: + fld TBYTE PTR [ecx] + jmp cd_epilogue + +cd_epilogue: + ;; Epilogue code is autogenerated. + ret +ffi_closure_STDCALL ENDP + +_TEXT ENDS +END + +#else + .text # This assumes we are using gas. .balign 16 .globl _ffi_call_win32 .def _ffi_call_win32; .scl 2; .type 32; .endef _ffi_call_win32: .LFB1: @@ -687,8 +1045,11 @@ 1: .byte 0x4 /* DW_CFA_advance_loc4 */ .long .LCFI10-.LCFI9 .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ .byte 0x5 /* .uleb128 0x5 */ /* End of DW_CFA_xxx CFI instructions. */ .align 4 .LEFDE5: + +#endif /* !_MSC_VER */ +
Attachment:
cc.sh
Description: application/shellscript
2010-01-12 Daniel Witte <dwitte@mozilla.com> * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to ffi_prep_cif_machdep for x86. * src/x86/ffi.c (ffi_prep_cif_machdep): To here. diff --git a/libffi/ChangeLog b/libffi/ChangeLog --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,8 +1,13 @@ +2010-01-12 Daniel Witte <dwitte@mozilla.com> + * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code to + ffi_prep_cif_machdep for x86. + * src/x86/ffi.c (ffi_prep_cif_machdep): To here. + 2009-12-28 David Edelsohn <edelsohn@gnu.org> * src/powerpc/ffi_darwin.c (ffi_prep_args): Copy abi and nargs to local variables. (aix_adjust_aggregate_sizes): New function. (ffi_prep_cif_machdep): Call it. 2009-12-26 Andreas Tobler <a.tobler@schweiz.org> diff --git a/libffi/src/prep_cif.c b/libffi/src/prep_cif.c --- a/libffi/src/prep_cif.c +++ b/libffi/src/prep_cif.c @@ -104,42 +104,39 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ff /* Initialize the return type if necessary */ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) return FFI_BAD_TYPEDEF; /* Perform a sanity check on the return type */ FFI_ASSERT_VALID_TYPE(cif->rtype); - /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ -#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA + /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */ +#if !defined M68K && !defined __i386__ && !defined __x86_64__ && !defined S390 && !defined PA /* Make space for the return structure pointer */ if (cif->rtype->type == FFI_TYPE_STRUCT #ifdef SPARC && (cif->abi != FFI_V9 || cif->rtype->size > 32) #endif -#ifdef X86_DARWIN - && (cif->rtype->size > 8) -#endif ) bytes = STACK_ARG_SIZE(sizeof(void*)); #endif for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) { /* Initialize any uninitialized aggregate type definitions */ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) return FFI_BAD_TYPEDEF; /* Perform a sanity check on the argument type, do this check after the initialization. */ FFI_ASSERT_VALID_TYPE(*ptr); -#if !defined __x86_64__ && !defined S390 && !defined PA +#if !defined __i386__ && !defined __x86_64__ && !defined S390 && !defined PA #ifdef SPARC if (((*ptr)->type == FFI_TYPE_STRUCT && ((*ptr)->size > 16 || cif->abi != FFI_V9)) || ((*ptr)->type == FFI_TYPE_LONGDOUBLE && cif->abi != FFI_V9)) bytes += sizeof(void*); else #endif diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c --- a/libffi/src/x86/ffi.c +++ b/libffi/src/x86/ffi.c @@ -143,34 +143,33 @@ void ffi_prep_args(char *stack, extended } return; } /* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { + unsigned int i; + ffi_type **ptr; + /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_VOID: -#ifdef X86 - case FFI_TYPE_STRUCT: -#endif #if defined(X86) || defined (X86_WIN32) || defined(X86_FREEBSD) || defined(X86_DARWIN) || defined(X86_WIN64) case FFI_TYPE_UINT8: case FFI_TYPE_UINT16: case FFI_TYPE_SINT8: case FFI_TYPE_SINT16: #endif #ifdef X86_WIN64 case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: #endif - case FFI_TYPE_SINT64: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: #ifndef X86_WIN64 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE case FFI_TYPE_LONGDOUBLE: #endif #endif @@ -179,18 +178,18 @@ ffi_status ffi_prep_cif_machdep(ffi_cif case FFI_TYPE_UINT64: #ifdef X86_WIN64 case FFI_TYPE_POINTER: #endif cif->flags = FFI_TYPE_SINT64; break; + case FFI_TYPE_STRUCT: #ifndef X86 - case FFI_TYPE_STRUCT: if (cif->rtype->size == 1) { cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */ } else if (cif->rtype->size == 2) { cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */ } @@ -202,58 +201,52 @@ ffi_status ffi_prep_cif_machdep(ffi_cif cif->flags = FFI_TYPE_INT; /* same as int type */ #endif } else if (cif->rtype->size == 8) { cif->flags = FFI_TYPE_SINT64; /* same as int64 type */ } else +#endif { cif->flags = FFI_TYPE_STRUCT; -#ifdef X86_WIN64 // allocate space for return value pointer cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG); -#endif } break; -#endif default: #ifdef X86_WIN64 cif->flags = FFI_TYPE_SINT64; break; case FFI_TYPE_INT: cif->flags = FFI_TYPE_SINT32; #else cif->flags = FFI_TYPE_INT; #endif break; } + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) + { + if (((*ptr)->alignment - 1) & cif->bytes) + cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment); + cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG); + } + +#ifdef X86_WIN64 + // ensure space for storing four registers + cif->bytes += 4 * sizeof(ffi_arg); +#endif + #ifdef X86_DARWIN cif->bytes = (cif->bytes + 15) & ~0xF; #endif -#ifdef X86_WIN64 - { - unsigned int i; - ffi_type **ptr; - - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - if (((*ptr)->alignment - 1) & cif->bytes) - cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment); - cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG); - } - } - // ensure space for storing four registers - cif->bytes += 4 * sizeof(ffi_arg); -#endif - return FFI_OK; } extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); #ifdef X86_WIN32 extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |