This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Libffi problem on darwin (MacOSX)
- From: Ronald Oussoren <oussoren at cistron dot nl>
- To: Andreas Tobler <toa at pop dot agri dot ch>
- Cc: Dale Johannesen <dalej at apple dot com>, gcc at gcc dot gnu dot org
- Date: Sat, 17 May 2003 08:03:26 +0200
- Subject: Re: Libffi problem on darwin (MacOSX)
On Saturday, May 17, 2003, at 07:52 Europe/Amsterdam, Andreas Tobler
wrote:
Dale Johannesen wrote:
On Friday, May 16, 2003, at 01:55 PM, Ronald Oussoren wrote:
We're using libffi closures in the Objective-C method tables to
forward calls from Objective-C to python. This is working fine for
basic calls, but gives wrong results when structs are passed. It
looks like a mismatch between the compiler and libffi:
ffi_closure_helper_DARWIN in libffi_darwin.c seems to assume that
structs are passed "by reference" (line 615), while the compiler
passes small structs entirely in registers (see assembly code emited
by the following C snippet):
I'm not familiar with libffi, but I can confirm that the compiler is
doing the
right thing, and it's the same thing it's always done. It looks like
ffi_prep_args
and ffi_prep_cif_machdep correctly understand that structs are passed
by value, so
this is just a bug in ffi_closure_helper_DARWIN.
Hey great, people are using libffi on darwin-ppc.
And were very glad this is available on darwin-ppc, libffi is a very
usefull library.
I guess this is born on my camp. I'll have a look at, as soon as time
allows here.
It is possible that I didn't finish the libffi regarding structures
since I didn't need it for libjava work. So, you could be right.
I just noticed that this might well be stupidity on my part, I tried to
write a minimal program that demonstrates the problem and that runs
without problems. Our real code builds ffi_cifs and ffi_closures at
runtime, and maybe that code is bogus.
Sorry about the inconvenience,
Ronald
--- example.c ---
#include "ffi.h"
#include <stdio.h>
struct foobar {
float a;
int b;
};
void callee(struct foobar a1, int a2)
{
printf("%g@%d %d\n", a1.a, a1.b, a2);
}
void stub(ffi_cif* cif, void* resp, void** args, void* userdata)
{
struct foobar a1;
int a2;
a1 = *(struct foobar*)(args[0]);
a2 = *(int*)(args[1]);
callee(a1, a2);
}
int main(void)
{
ffi_type* foobar_fields[3];
ffi_type foobar_type;
ffi_cif cif;
ffi_closure cl;
ffi_status rv;
void* args[4];
ffi_type* arg_types[3];
struct foobar g = { 1.0, 2.0 };
int fourtytwo = 42;
foobar_type.size = 0;
foobar_type.alignment = 0;
foobar_type.type = FFI_TYPE_STRUCT;
foobar_type.elements = foobar_fields;
foobar_fields[0] = &ffi_type_float;
foobar_fields[1] = &ffi_type_sint;
foobar_fields[2] = NULL;
arg_types[0] = &foobar_type;
arg_types[1] = &ffi_type_sint;
arg_types[2] = NULL;
rv = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_void, arg_types);
if (rv != FFI_OK) {
printf("ffi cif: %d\n", rv);
abort();
}
printf ("Direct call:");
callee(g, fourtytwo);
printf("FFI call:");
args[0] = &g;
args[1] = &fourtytwo;
args[2] = NULL;
ffi_call(&cif, FFI_FN(callee), NULL, args);
printf("FFI closure call:");
rv = ffi_prep_closure(&cl, &cif, stub, NULL);
if (rv != FFI_OK) {
printf("ffi cl: %d\n", rv);
abort();
}
((void(*)(struct foobar, int))(&cl))(g, fourtytwo);
return 0;
}