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

Reply via email to