diff options
author | Thomas Heller <theller@ctypes.org> | 2009-02-03 17:07:40 (GMT) |
---|---|---|
committer | Thomas Heller <theller@ctypes.org> | 2009-02-03 17:07:40 (GMT) |
commit | 7757d7bb510f820b49b085293e8bf8b244723853 (patch) | |
tree | 4fac101036bca2ddfca5b04fa8cbe89ae883f725 /Modules | |
parent | 1797b7dbbcc6d9db1ad51ca7e771f5a7e37299f5 (diff) | |
download | cpython-7757d7bb510f820b49b085293e8bf8b244723853.zip cpython-7757d7bb510f820b49b085293e8bf8b244723853.tar.gz cpython-7757d7bb510f820b49b085293e8bf8b244723853.tar.bz2 |
This refactoring should make it easier to add new calling conventions.
Replace ffi_call_STDCALL and ffi_call_SYSV by a ffi_call_x86 function
that cleans up the stack when FFI_SYSV is used, and does nothing for
FFI_STDCALL.
Remove libffi_msvc\win32.S, which is out of date and also unused; it
was only used for building ctypes with the MingW compiler.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/libffi_msvc/ffi.c | 37 | ||||
-rw-r--r-- | Modules/_ctypes/libffi_msvc/win32.S | 243 | ||||
-rw-r--r-- | Modules/_ctypes/libffi_msvc/win32.c | 149 |
3 files changed, 29 insertions, 400 deletions
diff --git a/Modules/_ctypes/libffi_msvc/ffi.c b/Modules/_ctypes/libffi_msvc/ffi.c index 279b66b..763d179 100644 --- a/Modules/_ctypes/libffi_msvc/ffi.c +++ b/Modules/_ctypes/libffi_msvc/ffi.c @@ -148,27 +148,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) } #ifdef _WIN32 -/*@-declundef@*/ -/*@-exportheader@*/ -extern int -ffi_call_SYSV(void (*)(char *, extended_cif *), - /*@out@*/ extended_cif *, - unsigned, unsigned, - /*@out@*/ unsigned *, - void (*fn)()); -/*@=declundef@*/ -/*@=exportheader@*/ - -/*@-declundef@*/ -/*@-exportheader@*/ extern int -ffi_call_STDCALL(void (*)(char *, extended_cif *), - /*@out@*/ extended_cif *, - unsigned, unsigned, - /*@out@*/ unsigned *, - void (*fn)()); -/*@=declundef@*/ -/*@=exportheader@*/ +ffi_call_x86(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); #endif #ifdef _WIN64 @@ -209,17 +194,9 @@ ffi_call(/*@dependent@*/ ffi_cif *cif, { #if !defined(_WIN64) case FFI_SYSV: - /*@-usedef@*/ - return ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - /*@=usedef@*/ - break; - case FFI_STDCALL: - /*@-usedef@*/ - return ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - /*@=usedef@*/ + return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); break; #else case FFI_SYSV: diff --git a/Modules/_ctypes/libffi_msvc/win32.S b/Modules/_ctypes/libffi_msvc/win32.S deleted file mode 100644 index cc82ab9..0000000 --- a/Modules/_ctypes/libffi_msvc/win32.S +++ /dev/null @@ -1,243 +0,0 @@ -/* ----------------------------------------------------------------------- - win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc. - Copyright (c) 2001 John Beniton - Copyright (c) 2002 Ranjit Mathew - - - 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, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, 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> - -.text - -.globl ffi_prep_args - - # This assumes we are using gas. - .balign 16 -.globl _ffi_call_SYSV - -_ffi_call_SYSV: - pushl %ebp - movl %esp,%ebp - - #THe: save previous %esi, and store the current stack pointer in %esi - pushl %esi - movl %esp,%esi - - # 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) - - # Remove the space we pushed for the args - movl 16(%ebp),%ecx - addl %ecx,%esp - - sub %esp,%esi # calculate stack pointer difference - - # 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 retint - - # Even if there is no space for the return value, we are - # obliged to handle floating-point values. - cmpl $FFI_TYPE_FLOAT,%ecx - jne noretval - fstp %st(0) - - jmp epilogue - -retint: - cmpl $FFI_TYPE_INT,%ecx - jne retfloat - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - jmp epilogue - -retfloat: - cmpl $FFI_TYPE_FLOAT,%ecx - jne retdouble - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstps (%ecx) - jmp epilogue - -retdouble: - cmpl $FFI_TYPE_DOUBLE,%ecx - jne retlongdouble - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp epilogue - -retlongdouble: - cmpl $FFI_TYPE_LONGDOUBLE,%ecx - jne retint64 - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp epilogue - -retint64: - cmpl $FFI_TYPE_SINT64,%ecx - jne retstruct - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - -retstruct: - # Nothing to do! - -noretval: -epilogue: - movl %esi,%eax # return the stack pointer detlta in %eax - popl %esi # restore previous %esi - movl %ebp,%esp - popl %ebp - ret - -.ffi_call_SYSV_end: - - # This assumes we are using gas. - .balign 16 -.globl _ffi_call_STDCALL - -_ffi_call_STDCALL: - pushl %ebp - movl %esp,%ebp - - #THe: save previous %esi, and store the current stack pointer in %esi - pushl %esi - movl %esp,%esi - - # 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) - - sub %esp,%esi # difference in stack - - # 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 sc_retint - - # Even if there is no space for the return value, we are - # obliged to handle floating-point values. - cmpl $FFI_TYPE_FLOAT,%ecx - jne sc_noretval - fstp %st(0) - - jmp sc_epilogue - -sc_retint: - cmpl $FFI_TYPE_INT,%ecx - jne sc_retfloat - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - jmp sc_epilogue - -sc_retfloat: - cmpl $FFI_TYPE_FLOAT,%ecx - jne sc_retdouble - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstps (%ecx) - jmp sc_epilogue - -sc_retdouble: - cmpl $FFI_TYPE_DOUBLE,%ecx - jne sc_retlongdouble - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp sc_epilogue - -sc_retlongdouble: - cmpl $FFI_TYPE_LONGDOUBLE,%ecx - jne sc_retint64 - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp sc_epilogue - -sc_retint64: - cmpl $FFI_TYPE_SINT64,%ecx - jne sc_retstruct - # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - -sc_retstruct: - # Nothing to do! - -sc_noretval: -sc_epilogue: - movl %esi,%eax # return the stack difference - popl %esi # restore previous %esi value - movl %ebp,%esp - popl %ebp - ret - -.ffi_call_STDCALL_end: diff --git a/Modules/_ctypes/libffi_msvc/win32.c b/Modules/_ctypes/libffi_msvc/win32.c index 0670c8c..d1149a8 100644 --- a/Modules/_ctypes/libffi_msvc/win32.c +++ b/Modules/_ctypes/libffi_msvc/win32.c @@ -29,21 +29,21 @@ /* theller: almost verbatim translation from gas syntax to MSVC inline assembler code. */ -/* theller: ffi_call_SYSV and ffi_call_STDCALL now return an integer - the - difference of the stack pointer before and after the function call. If - everything is ok, zero is returned. If stdcall functions are passed the - wrong number of arguments, the difference will be nonzero. */ +/* theller: ffi_call_x86 now returns an integer - the difference of the stack + pointer before and after the function call. If everything is ok, zero is + returned. If stdcall functions are passed the wrong number of arguments, + the difference will be nonzero. */ #include <ffi.h> #include <ffi_common.h> __declspec(naked) int -ffi_call_SYSV(void (* prepfunc)(char *, extended_cif *), /* 8 */ - extended_cif *ecif, /* 12 */ - unsigned bytes, /* 16 */ - unsigned flags, /* 20 */ - unsigned *rvalue, /* 24 */ - void (*fn)()) /* 28 */ +ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */ + extended_cif *ecif, /* 12 */ + unsigned bytes, /* 16 */ + unsigned flags, /* 20 */ + unsigned *rvalue, /* 24 */ + void (*fn)()) /* 28 */ { _asm { push ebp @@ -69,125 +69,20 @@ ffi_call_SYSV(void (* prepfunc)(char *, extended_cif *), /* 8 */ // FIXME: Align the stack to a 128-bit boundary to avoid // potential performance hits. call [ebp + 28] -// Remove the space we pushed for the args - mov ecx, [ebp + 16] - add esp, ecx - -// XXX ASSERT THAT ESP IS THE SAME NOW THAN BEFORE! - sub esi, esp - -// Load %ecx with the return type code - mov ecx, [ebp + 20] - -// If the return value pointer is NULL, assume no return value. -/* - Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction, - otherwise only one BYTE will be compared (instead of a DWORD)! - */ - cmp DWORD PTR [ebp + 24], 0 - jne sc_retint - -// Even if there is no space for the return value, we are -// obliged to handle floating-point values. - cmp ecx, FFI_TYPE_FLOAT - jne sc_noretval -// fstp %st(0) - fstp st(0) - - jmp sc_epilogue - -sc_retint: - cmp ecx, FFI_TYPE_INT - jne sc_retfloat -// # Load %ecx with the pointer to storage for the return value - mov ecx, [ebp + 24] - mov [ecx + 0], eax - jmp sc_epilogue - -sc_retfloat: - cmp ecx, FFI_TYPE_FLOAT - jne sc_retdouble -// Load %ecx with the pointer to storage for the return value - mov ecx, [ebp+24] -// fstps (%ecx) - fstp DWORD PTR [ecx] - jmp sc_epilogue -sc_retdouble: - cmp ecx, FFI_TYPE_DOUBLE - jne sc_retlongdouble -// movl 24(%ebp),%ecx - mov ecx, [ebp+24] - fstp QWORD PTR [ecx] - jmp sc_epilogue - - jmp sc_retlongdouble // avoid warning about unused label -sc_retlongdouble: - cmp ecx, FFI_TYPE_LONGDOUBLE - jne sc_retint64 -// Load %ecx with the pointer to storage for the return value - mov ecx, [ebp+24] -// fstpt (%ecx) - fstp QWORD PTR [ecx] /* XXX ??? */ - jmp sc_epilogue - -sc_retint64: - cmp ecx, FFI_TYPE_SINT64 - jne sc_retstruct -// Load %ecx with the pointer to storage for the return value - mov ecx, [ebp+24] - mov [ecx+0], eax - mov [ecx+4], edx - -sc_retstruct: -// Nothing to do! - -sc_noretval: -sc_epilogue: - mov eax, esi - pop esi // NEW restore: must be preserved across function calls - mov esp, ebp - pop ebp - ret - } -} - -__declspec(naked) int -ffi_call_STDCALL(void (* prepfunc)(char *, extended_cif *), /* 8 */ - extended_cif *ecif, /* 12 */ - unsigned bytes, /* 16 */ - unsigned flags, /* 20 */ - unsigned *rvalue, /* 24 */ - void (*fn)()) /* 28 */ -{ - _asm { - push ebp - mov ebp, esp - - push esi // NEW: this register must be preserved across function calls - -// XXX SAVE ESP NOW! - mov esi, esp - -// Make room for all of the new args. - mov ecx, [ebp+16] - sub esp, ecx +// Load ecif->cif->abi + mov ecx, [ebp + 12] + mov ecx, [ecx]ecif.cif + mov ecx, [ecx]ecif.cif.abi - mov eax, esp - -// Place all of the ffi_prep_args in position - push [ebp + 12] // ecif - push eax - call [ebp + 8] // prepfunc - -// Return stack to previous state and call the function - add esp, 8 -// FIXME: Align the stack to a 128-bit boundary to avoid -// potential performance hits. - call [ebp + 28] -// stdcall functions pop arguments off the stack themselves - -// XXX IS ESP NOW THE SAME AS BEFORE? + cmp ecx, FFI_STDCALL + je noclean +// STDCALL: Remove the space we pushed for the args + mov ecx, [ebp + 16] + add esp, ecx +// CDECL: Caller has already cleaned the stack +noclean: +// Check that esp has the same value as before! sub esi, esp // Load %ecx with the return type code |