In MacOSX 10.4.5, ffi_call can't pass floating-point values to a function which has variable argument list.
=== Reproduce steps: (1) compile the test program % cat vaarg.c #include <stdio.h> #include <ffi.h> int main() { ffi_cif cif; ffi_type *args[2]; void *values[1]; double v = 0.5; int rc; char *fmt = "%lf\n"; args[0] = &ffi_type_pointer; values[0] = &fmt; args[1] = &ffi_type_double; values[1] = &v; if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint, args) == FFI_OK) { ffi_call(&cif, (void*)printf, &rc, values); } return 0; } % gcc -v -save-temps -o vaarg vaarg.c -I../src/libffi/include/ ../src/libffi/.libs/libffi.a Using built-in specs. Target: powerpc-apple-darwin8 Configured with: /private/var/tmp/gcc/gcc-5247.obj~4/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --build=powerpc-apple-darwin8 --host=powerpc-apple-darwin8 --target=powerpc-apple-darwin8 Thread model: posix gcc version 4.0.1 (Apple Computer, Inc. build 5247) /usr/libexec/gcc/powerpc-apple-darwin8/4.0.1/cc1 -E -quiet -v -I../src/libffi/include/ -D__DYNAMIC__ vaarg.c -fPIC -fpch-preprocess -o vaarg.i ignoring nonexistent directory "/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/../../../../powerpc-apple-darwin8/include" #include "..." search starts here: #include <...> search starts here: ../src/libffi/include/ /usr/local/include /usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include /usr/include /System/Library/Frameworks /Library/Frameworks End of search list. /usr/libexec/gcc/powerpc-apple-darwin8/4.0.1/cc1 -fpreprocessed vaarg.i -fPIC -quiet -dumpbase vaarg.c -auxbase vaarg -version -o vaarg.s GNU C version 4.0.1 (Apple Computer, Inc. build 5247) (powerpc-apple-darwin8) compiled by GNU C version 4.0.1 (Apple Computer, Inc. build 5247). GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 293c7bb043389dbe08b10e2d17bba0c4 as -arch ppc -o vaarg.o vaarg.s /usr/libexec/gcc/powerpc-apple-darwin8/4.0.1/collect2 -dynamic -arch ppc -weak_reference_mismatches non-weak -o vaarg -lcrt1.o /usr/lib/gcc/powerpc-apple-darwin8/4.0.1/crt2.o -L/usr/lib/gcc/powerpc-apple-darwin8/4.0.1 -L/usr/lib/gcc/powerpc-apple-darwin8/4.0.1 -L/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/../../.. vaarg.o ../src/libffi/.libs/libffi.a -lgcc -lSystemStubs -lSystem (2) run it % ./vaarg -0.000000 === Expected Results: % ./vaarg 0.500000 === Patches For a function which has variable argument list, floating-point values should be put in the stack even if fparg_count < NUM_FPR_ARG_REGISTERS. URL: http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/Articles/32bitPowerPC.html#//apple_ref/doc/uid/TP40002438-DontLinkElementID_524797a So I make the patch and works well in my environment. % diff -c ffi_darwin.c.orig ffi_darwin.c *** ffi_darwin.c.orig Sat Mar 18 21:23:17 2006 --- ffi_darwin.c Sat Mar 18 22:45:24 2006 *************** *** 130,138 **** the size of the floating-point parameter are skipped. */ case FFI_TYPE_FLOAT: double_tmp = *(float *)*p_argv; ! if (fparg_count >= NUM_FPR_ARG_REGISTERS) ! *(double *)next_arg = double_tmp; ! else *fpr_base++ = double_tmp; next_arg++; fparg_count++; --- 130,137 ---- the size of the floating-point parameter are skipped. */ case FFI_TYPE_FLOAT: double_tmp = *(float *)*p_argv; ! *(double *)next_arg = double_tmp; ! if (fparg_count < NUM_FPR_ARG_REGISTERS) *fpr_base++ = double_tmp; next_arg++; fparg_count++; *************** *** 141,149 **** case FFI_TYPE_DOUBLE: double_tmp = *(double *)*p_argv; ! if (fparg_count >= NUM_FPR_ARG_REGISTERS) ! *(double *)next_arg = double_tmp; ! else *fpr_base++ = double_tmp; next_arg += 2; fparg_count++; --- 140,147 ---- case FFI_TYPE_DOUBLE: double_tmp = *(double *)*p_argv; ! *(double *)next_arg = double_tmp; ! if (fparg_count < NUM_FPR_ARG_REGISTERS) *fpr_base++ = double_tmp; next_arg += 2; fparg_count++; *************** *** 154,169 **** case FFI_TYPE_LONGDOUBLE: double_tmp = ((double *)*p_argv)[0]; ! if (fparg_count >= NUM_FPR_ARG_REGISTERS) ! *(double *)next_arg = double_tmp; ! else *fpr_base++ = double_tmp; next_arg += 2; fparg_count++; double_tmp = ((double *)*p_argv)[1]; ! if (fparg_count >= NUM_FPR_ARG_REGISTERS) ! *(double *)next_arg = double_tmp; ! else *fpr_base++ = double_tmp; next_arg += 2; fparg_count++; --- 152,165 ---- case FFI_TYPE_LONGDOUBLE: double_tmp = ((double *)*p_argv)[0]; ! *(double *)next_arg = double_tmp; ! if (fparg_count < NUM_FPR_ARG_REGISTERS) *fpr_base++ = double_tmp; next_arg += 2; fparg_count++; double_tmp = ((double *)*p_argv)[1]; ! *(double *)next_arg = double_tmp; ! if (fparg_count < NUM_FPR_ARG_REGISTERS) *fpr_base++ = double_tmp; next_arg += 2; fparg_count++; -- Summary: ffi_call can't pass floating-point values to a function which has variable argument list. Product: gcc Version: 4.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libffi AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: naoki at koguro dot net GCC build triplet: powerpc-apple-darwin8.5.0 GCC host triplet: powerpc-apple-darwin8.5.0 GCC target triplet: powerpc-apple-darwin8.5.0 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26744