Bug 26744 - vararg functions support in libffi is not supported
Summary: vararg functions support in libffi is not supported
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libffi (show other bugs)
Version: 4.1.0
: P3 enhancement
Target Milestone: 4.5.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-03-18 13:50 UTC by KOGURO, Naoki
Modified: 2021-09-15 08:53 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-03-20 08:08:56


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description KOGURO, Naoki 2006-03-18 13:50:14 UTC
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++;
Comment 1 Andrew Pinski 2006-03-18 14:46:34 UTC
libffi does not support variable arguments at all.
Comment 2 Andrew Pinski 2006-03-20 08:08:56 UTC
Confirmed, this is an enhancement because this is no support at all in libffi for var args.
Comment 3 Andrew Pinski 2021-09-15 08:53:04 UTC
Been fixed since at least r0-93927 which added testcases for this.