From b4a6a566ff8a42840beca7b6a1e790d1b3cf1765 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Tue, 4 Jul 2006 12:30:22 +0000 Subject: Sync the darwin/x86 port libffi with the copy in PyObjC. This fixes a number of bugs in that port. The most annoying ones were due to some subtle differences between the document ABI and the actual implementation :-( (there are no python unittests that fail without this patch, but without it some of libffi's unittests fail). --- Modules/_ctypes/libffi/src/x86/darwin.S | 56 ++++++++++- Modules/_ctypes/libffi/src/x86/ffi_darwin.c | 144 +++++++++++++--------------- 2 files changed, 116 insertions(+), 84 deletions(-) diff --git a/Modules/_ctypes/libffi/src/x86/darwin.S b/Modules/_ctypes/libffi/src/x86/darwin.S index c5e55b5..d91bdc0 100644 --- a/Modules/_ctypes/libffi/src/x86/darwin.S +++ b/Modules/_ctypes/libffi/src/x86/darwin.S @@ -35,6 +35,13 @@ #include #include +#ifdef PyObjC_STRICT_DEBUGGING + /* XXX: Debugging of stack alignment, to be removed */ +#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0 +#else +#define ASSERT_STACK_ALIGNED +#endif + .text .globl _ffi_prep_args @@ -47,30 +54,41 @@ _ffi_call_SYSV: pushl %ebp .LCFI0: movl %esp,%ebp + subl $8,%esp + ASSERT_STACK_ALIGNED .LCFI1: /* Make room for all of the new args. */ movl 16(%ebp),%ecx subl %ecx,%esp + ASSERT_STACK_ALIGNED + movl %esp,%eax /* Place all of the ffi_prep_args in position */ + subl $8,%esp pushl 12(%ebp) pushl %eax call *8(%ebp) + ASSERT_STACK_ALIGNED + /* Return stack to previous state and call the function */ - addl $8,%esp + addl $16,%esp - call *28(%ebp) + ASSERT_STACK_ALIGNED - /* Remove the space we pushed for the args */ + call *28(%ebp) + + /* XXX: return returns return with 'ret $4', that upsets the stack! */ movl 16(%ebp),%ecx addl %ecx,%esp + /* 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 @@ -117,17 +135,47 @@ retlongdouble: retint64: cmpl $FFI_TYPE_SINT64,%ecx - jne retstruct + jne retstruct1b /* Load %ecx with the pointer to storage for the return value */ movl 24(%ebp),%ecx movl %eax,0(%ecx) movl %edx,4(%ecx) + jmp epilogue + +retstruct1b: + cmpl $FFI_TYPE_SINT8,%ecx + jne retstruct2b + movl 24(%ebp),%ecx + movb %al,0(%ecx) + jmp epilogue + +retstruct2b: + cmpl $FFI_TYPE_SINT16,%ecx + jne retstruct + movl 24(%ebp),%ecx + movw %ax,0(%ecx) + jmp epilogue retstruct: + cmpl $FFI_TYPE_STRUCT,%ecx + jne noretval /* Nothing to do! */ + subl $4,%esp + + ASSERT_STACK_ALIGNED + + addl $8,%esp + movl %ebp, %esp + popl %ebp + ret + noretval: epilogue: + ASSERT_STACK_ALIGNED + addl $8, %esp + + movl %ebp,%esp popl %ebp ret diff --git a/Modules/_ctypes/libffi/src/x86/ffi_darwin.c b/Modules/_ctypes/libffi/src/x86/ffi_darwin.c index 4f82b3a..c9742d8 100644 --- a/Modules/_ctypes/libffi/src/x86/ffi_darwin.c +++ b/Modules/_ctypes/libffi/src/x86/ffi_darwin.c @@ -140,7 +140,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) switch (cif->rtype->type) { case FFI_TYPE_VOID: -#if !defined(X86_WIN32) +#if !defined(X86_WIN32) && !defined(X86_DARWIN) case FFI_TYPE_STRUCT: #endif case FFI_TYPE_SINT64: @@ -154,7 +154,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) cif->flags = FFI_TYPE_SINT64; break; -#if defined X86_WIN32 +#if defined(X86_WIN32) || defined(X86_DARWIN) case FFI_TYPE_STRUCT: if (cif->rtype->size == 1) @@ -186,10 +186,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) } /* Darwin: The stack needs to be aligned to a multiple of 16 bytes */ -#if 0 +#if 1 cif->bytes = (cif->bytes + 15) & ~0xF; #endif + return FFI_OK; } @@ -221,7 +222,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, /*@dependent@*/ void **avalue) { extended_cif ecif; - int flags; ecif.cif = cif; ecif.avalue = avalue; @@ -238,20 +238,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, else ecif.rvalue = rvalue; - flags = cif->flags; - if (flags == FFI_TYPE_STRUCT) { - if (cif->rtype->size == 8) { - flags = FFI_TYPE_SINT64; - } else if (cif->rtype->size == 4) { - flags = FFI_TYPE_INT; - } else if (cif->rtype->size == 2) { - flags = FFI_TYPE_INT; - } else if (cif->rtype->size == 1) { - flags = FFI_TYPE_INT; - } - } - - switch (cif->abi) { case FFI_SYSV: @@ -260,8 +246,8 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, * block is a multiple of 16. Then add 8 to compensate for local variables * in ffi_call_SYSV. */ - ffi_call_SYSV(ffi_prep_args, &ecif, ALIGN(cif->bytes, 16) +8, - flags, ecif.rvalue, fn); + ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; #ifdef X86_WIN32 @@ -281,8 +267,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, /** private members **/ -static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, - void** args, ffi_cif* cif); static void ffi_closure_SYSV (ffi_closure *) __attribute__ ((regparm(1))); #if !FFI_NO_RAW_API @@ -290,6 +274,48 @@ static void ffi_closure_raw_SYSV (ffi_raw_closure *) __attribute__ ((regparm(1))); #endif +/*@-exportheader@*/ +static inline void +ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, + void **avalue, ffi_cif *cif) +/*@=exportheader@*/ +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if (retval_on_stack(cif->rtype)) { + *rvalue = *(void **) argp; + argp += 4; + } + + p_argv = avalue; + + for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + { + size_t z; + + /* Align if necessary */ + if ((sizeof(int) - 1) & (unsigned) argp) { + argp = (char *) ALIGN(argp, sizeof(int)); + } + + z = (*p_arg)->size; + + /* because we're little endian, this is what it turns into. */ + + *p_argv = (void*) argp; + + p_argv++; + argp += z; + } + + return; +} + /* This function is jumped to by the trampoline */ static void @@ -302,10 +328,10 @@ ffi_closure_SYSV (closure) // our various things... ffi_cif *cif; void **arg_area; - unsigned short rtype; void *resp = (void*)&res; void *args = __builtin_dwarf_cfa (); + cif = closure->cif; arg_area = (void**) alloca (cif->nargs * sizeof (void*)); @@ -319,94 +345,52 @@ ffi_closure_SYSV (closure) (closure->fun) (cif, resp, arg_area, closure->user_data); - rtype = cif->flags; - - if (!retval_on_stack(cif->rtype) && cif->flags == FFI_TYPE_STRUCT) { - if (cif->rtype->size == 8) { - rtype = FFI_TYPE_SINT64; - } else { - rtype = FFI_TYPE_INT; - } - } - /* now, do a generic return based on the value of rtype */ - if (rtype == FFI_TYPE_INT) + if (cif->flags == FFI_TYPE_INT) { asm ("movl (%0),%%eax" : : "r" (resp) : "eax"); } - else if (rtype == FFI_TYPE_FLOAT) + else if (cif->flags == FFI_TYPE_FLOAT) { asm ("flds (%0)" : : "r" (resp) : "st" ); } - else if (rtype == FFI_TYPE_DOUBLE) + else if (cif->flags == FFI_TYPE_DOUBLE) { asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); } - else if (rtype == FFI_TYPE_LONGDOUBLE) + else if (cif->flags == FFI_TYPE_LONGDOUBLE) { asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); } - else if (rtype == FFI_TYPE_SINT64) + else if (cif->flags == FFI_TYPE_SINT64) { asm ("movl 0(%0),%%eax;" "movl 4(%0),%%edx" : : "r"(resp) : "eax", "edx"); } -#ifdef X86_WIN32 - else if (rtype == FFI_TYPE_SINT8) /* 1-byte struct */ +#if defined(X86_WIN32) || defined(X86_DARWIN) + else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct */ { asm ("movsbl (%0),%%eax" : : "r" (resp) : "eax"); } - else if (rtype == FFI_TYPE_SINT16) /* 2-bytes struct */ + else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */ { asm ("movswl (%0),%%eax" : : "r" (resp) : "eax"); } #endif -} -/*@-exportheader@*/ -static void -ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, - void **avalue, ffi_cif *cif) -/*@=exportheader@*/ -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - argp = stack; - - if (retval_on_stack(cif->rtype)) { - *rvalue = *(void **) argp; - argp += 4; - } - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + else if (cif->flags == FFI_TYPE_STRUCT) { - size_t z; - - /* Align if necessary */ - if ((sizeof(int) - 1) & (unsigned) argp) { - argp = (char *) ALIGN(argp, sizeof(int)); - } - - z = (*p_arg)->size; - - /* because we're little endian, this is what it turns into. */ - - *p_argv = (void*) argp; - - p_argv++; - argp += z; + asm ("lea -8(%ebp),%esp;" + "pop %esi;" + "pop %edi;" + "pop %ebp;" + "ret $4"); } - - return; } + /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */ #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ -- cgit v0.12