Commit b4a6a566 authored by Ronald Oussoren's avatar Ronald Oussoren

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).
parent 74c3ea0a
......@@ -35,6 +35,13 @@
#include <fficonfig.h>
#include <ffi.h>
#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
......
......@@ -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) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment