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++;
libffi does not support variable arguments at all.
Confirmed, this is an enhancement because this is no support at all in libffi for var args.
Been fixed since at least r0-93927 which added testcases for this.