| Patch libffi to fix bug 550602, bug 538216, bug545634, bug 594611, bug 605421 |
| and bug 631928. |
| |
| diff --git a/js/src/ctypes/libffi/Makefile.in b/js/src/ctypes/libffi/Makefile.in |
| --- a/js/src/ctypes/libffi/Makefile.in |
| +++ b/js/src/ctypes/libffi/Makefile.in |
| @@ -199,17 +199,17 @@ LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIB |
| CCLD = $(CC) |
| LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ |
| --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ |
| $(LDFLAGS) -o $@ |
| SOURCES = $(libffi_la_SOURCES) $(nodist_libffi_la_SOURCES) \ |
| $(libffi_convenience_la_SOURCES) \ |
| $(nodist_libffi_convenience_la_SOURCES) |
| DIST_SOURCES = $(libffi_la_SOURCES) $(libffi_convenience_la_SOURCES) |
| -INFO_DEPS = $(srcdir)/doc/libffi.info |
| +INFO_DEPS = |
| am__TEXINFO_TEX_DIR = $(srcdir) |
| DVIS = doc/libffi.dvi |
| PDFS = doc/libffi.pdf |
| PSS = doc/libffi.ps |
| HTMLS = doc/libffi.html |
| TEXINFOS = doc/libffi.texi |
| TEXI2DVI = texi2dvi |
| TEXI2PDF = $(TEXI2DVI) --pdf --batch |
| @@ -986,57 +986,57 @@ distclean-compile: |
| @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi.Plo@am__quote@ |
| @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi64.Plo@am__quote@ |
| @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/freebsd.Plo@am__quote@ |
| @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/sysv.Plo@am__quote@ |
| @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/unix64.Plo@am__quote@ |
| @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win32.Plo@am__quote@ |
| @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win64.Plo@am__quote@ |
| |
| -.S.o: |
| +%.o: %.S |
| @am__fastdepCCAS_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ |
| @am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ |
| @am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po |
| @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
| @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
| @am__fastdepCCAS_FALSE@ $(CPPASCOMPILE) -c -o $@ $< |
| |
| -.S.obj: |
| +%.obj: %.S |
| @am__fastdepCCAS_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ |
| @am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ |
| @am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po |
| @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
| @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
| @am__fastdepCCAS_FALSE@ $(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` |
| |
| -.S.lo: |
| +%.lo: %.S |
| @am__fastdepCCAS_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ |
| @am__fastdepCCAS_TRUE@ $(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ |
| @am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo |
| @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ |
| @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
| @am__fastdepCCAS_FALSE@ $(LTCPPASCOMPILE) -c -o $@ $< |
| |
| -.c.o: |
| +%.o: %.c |
| @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ |
| @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ |
| @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po |
| @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
| @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
| @am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< |
| |
| -.c.obj: |
| +%.obj: %.c |
| @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ |
| @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ |
| @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po |
| @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
| @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
| @am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` |
| |
| -.c.lo: |
| +%.lo: %.c |
| @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ |
| @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ |
| @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo |
| @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ |
| @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
| @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< |
| |
| mostlyclean-libtool: |
| @@ -1129,17 +1129,17 @@ doc/libffi.html: doc/libffi.texi $(srcdi |
| -@rm -f vti.tmp |
| @cp $(srcdir)/doc/version.texi $@ |
| |
| mostlyclean-vti: |
| -rm -f vti.tmp |
| |
| maintainer-clean-vti: |
| @MAINTAINER_MODE_TRUE@ -rm -f $(srcdir)/doc/stamp-vti $(srcdir)/doc/version.texi |
| -.dvi.ps: |
| +%.ps: %.dvi |
| TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ |
| $(DVIPS) -o $@ $< |
| |
| uninstall-dvi-am: |
| @$(NORMAL_UNINSTALL) |
| @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ |
| for p in $$list; do \ |
| $(am__strip_dir) \ |
| diff --git a/js/src/ctypes/libffi/aclocal.m4 b/js/src/ctypes/libffi/aclocal.m4 |
| --- a/js/src/ctypes/libffi/aclocal.m4 |
| +++ b/js/src/ctypes/libffi/aclocal.m4 |
| @@ -4703,17 +4703,17 @@ dnl Note also adjust exclude_expsyms for |
| # Tell ltmain to make .dll files, not .so files. |
| shrext_cmds=".dll" |
| # FIXME: Setting linknames here is a bad hack. |
| _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' |
| # The linker will automatically build a .lib file if we build a DLL. |
| _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' |
| # FIXME: Should let the user specify the lib program. |
| _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' |
| - _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' |
| + _LT_TAGVAR(fix_srcfile_path, $1)='' |
| _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes |
| ;; |
| |
| darwin* | rhapsody*) |
| _LT_DARWIN_LINKER_FEATURES($1) |
| ;; |
| |
| dgux*) |
| diff --git a/js/src/ctypes/libffi/config.sub b/js/src/ctypes/libffi/config.sub |
| --- a/js/src/ctypes/libffi/config.sub |
| +++ b/js/src/ctypes/libffi/config.sub |
| @@ -1,15 +1,15 @@ |
| #! /bin/sh |
| # Configuration validation subroutine script. |
| # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
| # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
| # Free Software Foundation, Inc. |
| |
| -timestamp='2009-11-07' |
| +timestamp='2011-01-03' |
| |
| # This file is (in principle) common to ALL GNU software. |
| # The presence of a machine in this file suggests that SOME GNU software |
| # can handle that machine. It does not imply ALL GNU software can. |
| # |
| # This file is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2 of the License, or |
| @@ -121,17 +121,17 @@ esac |
| |
| # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). |
| # Here we must recognize all the valid KERNEL-OS combinations. |
| maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` |
| case $maybe_os in |
| nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ |
| uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ |
| kopensolaris*-gnu* | \ |
| - storm-chaos* | os2-emx* | rtmk-nova*) |
| + storm-chaos* | os2-emx* | rtmk-nova* | wince-winmo*) |
| os=-$maybe_os |
| basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` |
| ;; |
| *) |
| basic_machine=`echo $1 | sed 's/-[^-]*$//'` |
| if [ $basic_machine != $1 ] |
| then os=`echo $1 | sed 's/.*-/-/'` |
| else os=; fi |
| @@ -282,32 +282,30 @@ case $basic_machine in |
| | mt \ |
| | msp430 \ |
| | nios | nios2 \ |
| | ns16k | ns32k \ |
| | or32 \ |
| | pdp10 | pdp11 | pj | pjl \ |
| | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ |
| | pyramid \ |
| - | rx \ |
| | score \ |
| | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ |
| | sh64 | sh64le \ |
| | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ |
| | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ |
| | spu | strongarm \ |
| | tahoe | thumb | tic4x | tic80 | tron \ |
| - | ubicom32 \ |
| | v850 | v850e \ |
| | we32k \ |
| | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ |
| | z8k | z80) |
| basic_machine=$basic_machine-unknown |
| ;; |
| - m6811 | m68hc11 | m6812 | m68hc12 | picochip) |
| + m6811 | m68hc11 | m6812 | m68hc12) |
| # Motorola 68HC11/12. |
| basic_machine=$basic_machine-unknown |
| os=-none |
| ;; |
| m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) |
| ;; |
| ms1) |
| basic_machine=mt-unknown |
| @@ -368,26 +366,25 @@ case $basic_machine in |
| | mt-* \ |
| | msp430-* \ |
| | nios-* | nios2-* \ |
| | none-* | np1-* | ns16k-* | ns32k-* \ |
| | orion-* \ |
| | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ |
| | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ |
| | pyramid-* \ |
| - | romp-* | rs6000-* | rx-* \ |
| + | romp-* | rs6000-* \ |
| | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ |
| | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ |
| | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ |
| | sparclite-* \ |
| | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ |
| | tahoe-* | thumb-* \ |
| | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ |
| | tron-* \ |
| - | ubicom32-* \ |
| | v850-* | v850e-* | vax-* \ |
| | we32k-* \ |
| | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ |
| | xstormy16-* | xtensa*-* \ |
| | ymp-* \ |
| | z8k-* | z80-*) |
| ;; |
| # Recognize the basic CPU types without company name, with glob match. |
| @@ -1294,17 +1291,17 @@ case $os in |
| | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ |
| | -uxpv* | -beos* | -mpeix* | -udk* \ |
| | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ |
| | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ |
| | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ |
| | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ |
| | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ |
| | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ |
| - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) |
| + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -winmo*) |
| # Remember, each alternative MUST END IN *, to match a version number. |
| ;; |
| -qnx*) |
| case $basic_machine in |
| x86-* | i*86-*) |
| ;; |
| *) |
| os=-nto$os |
| @@ -1336,16 +1333,19 @@ case $os in |
| os=`echo $os | sed -e 's|sunos6|solaris3|'` |
| ;; |
| -opened*) |
| os=-openedition |
| ;; |
| -os400*) |
| os=-os400 |
| ;; |
| + -wince-winmo*) |
| + os=-wince-winmo |
| + ;; |
| -wince*) |
| os=-wince |
| ;; |
| -osfrose*) |
| os=-osfrose |
| ;; |
| -osf*) |
| os=-osf |
| @@ -1427,16 +1427,19 @@ case $os in |
| os=-kaos |
| ;; |
| -zvmoe) |
| os=-zvmoe |
| ;; |
| -dicos*) |
| os=-dicos |
| ;; |
| + -android*) |
| + os=-android |
| + ;; |
| -none) |
| ;; |
| *) |
| # Get rid of the `-' at the beginning of $os. |
| os=`echo $os | sed 's/[^-]*-//'` |
| echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 |
| exit 1 |
| ;; |
| @@ -1681,16 +1684,19 @@ case $basic_machine in |
| vendor=apple |
| ;; |
| -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) |
| vendor=atari |
| ;; |
| -vos*) |
| vendor=stratus |
| ;; |
| + *-android*|*-linuxandroid*) |
| + vendor=linux- |
| + ;; |
| esac |
| basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` |
| ;; |
| esac |
| |
| echo $basic_machine$os |
| exit |
| |
| diff --git a/js/src/ctypes/libffi/configure b/js/src/ctypes/libffi/configure |
| --- a/js/src/ctypes/libffi/configure |
| +++ b/js/src/ctypes/libffi/configure |
| @@ -8903,17 +8903,17 @@ if test -z "$aix_libpath"; then aix_libp |
| # Tell ltmain to make .dll files, not .so files. |
| shrext_cmds=".dll" |
| # FIXME: Setting linknames here is a bad hack. |
| archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' |
| # The linker will automatically build a .lib file if we build a DLL. |
| old_archive_from_new_cmds='true' |
| # FIXME: Should let the user specify the lib program. |
| old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' |
| - fix_srcfile_path='`cygpath -w "$srcfile"`' |
| + fix_srcfile_path='' |
| enable_shared_with_static_runtimes=yes |
| ;; |
| |
| darwin* | rhapsody*) |
| |
| |
| archive_cmds_need_lc=no |
| hardcode_direct=no |
| @@ -12270,20 +12270,20 @@ fi |
| |
| if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then |
| { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports pc related relocs" >&5 |
| $as_echo_n "checking assembler supports pc related relocs... " >&6; } |
| if test "${libffi_cv_as_x86_pcrel+set}" = set; then : |
| $as_echo_n "(cached) " >&6 |
| else |
| |
| - libffi_cv_as_x86_pcrel=yes |
| + libffi_cv_as_x86_pcrel=no |
| echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s |
| - if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then |
| - libffi_cv_as_x86_pcrel=no |
| + if $CC $CFLAGS -c conftest.s > /dev/null; then |
| + libffi_cv_as_x86_pcrel=yes |
| fi |
| |
| fi |
| { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_x86_pcrel" >&5 |
| $as_echo "$libffi_cv_as_x86_pcrel" >&6; } |
| if test "x$libffi_cv_as_x86_pcrel" = xyes; then |
| |
| $as_echo "#define HAVE_AS_X86_PCREL 1" >>confdefs.h |
| diff --git a/js/src/ctypes/libffi/configure.ac b/js/src/ctypes/libffi/configure.ac |
| --- a/js/src/ctypes/libffi/configure.ac |
| +++ b/js/src/ctypes/libffi/configure.ac |
| @@ -272,20 +272,20 @@ if test x$TARGET = xSPARC; then |
| AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1, |
| [Define if your assembler supports .register.]) |
| fi |
| fi |
| |
| if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then |
| AC_CACHE_CHECK([assembler supports pc related relocs], |
| libffi_cv_as_x86_pcrel, [ |
| - libffi_cv_as_x86_pcrel=yes |
| + libffi_cv_as_x86_pcrel=no |
| echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s |
| - if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then |
| - libffi_cv_as_x86_pcrel=no |
| + if $CC $CFLAGS -c conftest.s > /dev/null; then |
| + libffi_cv_as_x86_pcrel=yes |
| fi |
| ]) |
| if test "x$libffi_cv_as_x86_pcrel" = xyes; then |
| AC_DEFINE(HAVE_AS_X86_PCREL, 1, |
| [Define if your assembler supports PC relative relocs.]) |
| fi |
| |
| AC_CACHE_CHECK([assembler .ascii pseudo-op support], |
| diff --git a/js/src/ctypes/libffi/include/ffi.h.in b/js/src/ctypes/libffi/include/ffi.h.in |
| --- a/js/src/ctypes/libffi/include/ffi.h.in |
| +++ b/js/src/ctypes/libffi/include/ffi.h.in |
| @@ -72,25 +72,37 @@ extern "C" { |
| #endif |
| |
| #include <stddef.h> |
| #include <limits.h> |
| |
| /* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). |
| But we can find it either under the correct ANSI name, or under GNU |
| C's internal name. */ |
| + |
| +#define FFI_64_BIT_MAX 9223372036854775807 |
| + |
| #ifdef LONG_LONG_MAX |
| # define FFI_LONG_LONG_MAX LONG_LONG_MAX |
| #else |
| # ifdef LLONG_MAX |
| # define FFI_LONG_LONG_MAX LLONG_MAX |
| # else |
| # ifdef __GNUC__ |
| # define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ |
| # endif |
| +# ifdef _AIX |
| +# ifndef __PPC64__ |
| +# if defined (__IBMC__) || defined (__IBMCPP__) |
| +# define FFI_LONG_LONG_MAX LONGLONG_MAX |
| +# endif |
| +# endif /* __PPC64__ */ |
| +# undef FFI_64_BIT_MAX |
| +# define FFI_64_BIT_MAX 9223372036854775807LL |
| +# endif |
| # endif |
| #endif |
| |
| /* The closure code assumes that this works on pointers, i.e. a size_t */ |
| /* can hold a pointer. */ |
| |
| typedef struct _ffi_type |
| { |
| @@ -127,27 +139,27 @@ typedef struct _ffi_type |
| #elif INT_MAX == 9223372036854775807 |
| # define ffi_type_uint ffi_type_uint64 |
| # define ffi_type_sint ffi_type_sint64 |
| #else |
| #error "int size not supported" |
| #endif |
| |
| #if LONG_MAX == 2147483647 |
| -# if FFI_LONG_LONG_MAX != 9223372036854775807 |
| +# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX |
| #error "no 64-bit data type supported" |
| # endif |
| -#elif LONG_MAX != 9223372036854775807 |
| +#elif LONG_MAX != FFI_64_BIT_MAX |
| #error "long size not supported" |
| #endif |
| |
| #if LONG_MAX == 2147483647 |
| # define ffi_type_ulong ffi_type_uint32 |
| # define ffi_type_slong ffi_type_sint32 |
| -#elif LONG_MAX == 9223372036854775807 |
| +#elif LONG_MAX == FFI_64_BIT_MAX |
| # define ffi_type_ulong ffi_type_uint64 |
| # define ffi_type_slong ffi_type_sint64 |
| #else |
| #error "long size not supported" |
| #endif |
| |
| /* These are defined in types.c */ |
| extern ffi_type ffi_type_void; |
| @@ -190,17 +202,17 @@ typedef struct { |
| #endif |
| } ffi_cif; |
| |
| /* ---- Definitions for the raw API -------------------------------------- */ |
| |
| #ifndef FFI_SIZEOF_ARG |
| # if LONG_MAX == 2147483647 |
| # define FFI_SIZEOF_ARG 4 |
| -# elif LONG_MAX == 9223372036854775807 |
| +# elif LONG_MAX == FFI_64_BIT_MAX |
| # define FFI_SIZEOF_ARG 8 |
| # endif |
| #endif |
| |
| #ifndef FFI_SIZEOF_JAVA_RAW |
| # define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG |
| #endif |
| |
| diff --git a/js/src/ctypes/libffi/src/arm/ffi.c b/js/src/ctypes/libffi/src/arm/ffi.c |
| --- a/js/src/ctypes/libffi/src/arm/ffi.c |
| +++ b/js/src/ctypes/libffi/src/arm/ffi.c |
| @@ -24,22 +24,30 @@ |
| DEALINGS IN THE SOFTWARE. |
| ----------------------------------------------------------------------- */ |
| |
| #include <ffi.h> |
| #include <ffi_common.h> |
| |
| #include <stdlib.h> |
| |
| +/* Forward declares. */ |
| +static int vfp_type_p (ffi_type *); |
| +static void layout_vfp_args (ffi_cif *); |
| + |
| /* ffi_prep_args is called by the assembly routine once stack space |
| - has been allocated for the function's arguments */ |
| - |
| -void ffi_prep_args(char *stack, extended_cif *ecif) |
| + has been allocated for the function's arguments |
| + |
| + The vfp_space parameter is the load area for VFP regs, the return |
| + value is cif->vfp_used (word bitset of VFP regs used for passing |
| + arguments). These are only used for the VFP hard-float ABI. |
| +*/ |
| +int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space) |
| { |
| - register unsigned int i; |
| + register unsigned int i, vi = 0; |
| register void **p_argv; |
| register char *argp; |
| register ffi_type **p_arg; |
| |
| argp = stack; |
| |
| if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { |
| *(void **) argp = ecif->rvalue; |
| @@ -49,16 +57,31 @@ void ffi_prep_args(char *stack, extended |
| p_argv = ecif->avalue; |
| |
| for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; |
| (i != 0); |
| i--, p_arg++) |
| { |
| size_t z; |
| |
| + /* Allocated in VFP registers. */ |
| + if (ecif->cif->abi == FFI_VFP |
| + && vi < ecif->cif->vfp_nargs && vfp_type_p (*p_arg)) |
| + { |
| + float* vfp_slot = vfp_space + ecif->cif->vfp_args[vi++]; |
| + if ((*p_arg)->type == FFI_TYPE_FLOAT) |
| + *((float*)vfp_slot) = *((float*)*p_argv); |
| + else if ((*p_arg)->type == FFI_TYPE_DOUBLE) |
| + *((double*)vfp_slot) = *((double*)*p_argv); |
| + else |
| + memcpy(vfp_slot, *p_argv, (*p_arg)->size); |
| + p_argv++; |
| + continue; |
| + } |
| + |
| /* Align if necessary */ |
| if (((*p_arg)->alignment - 1) & (unsigned) argp) { |
| argp = (char *) ALIGN(argp, (*p_arg)->alignment); |
| } |
| |
| if ((*p_arg)->type == FFI_TYPE_STRUCT) |
| argp = (char *) ALIGN(argp, 4); |
| |
| @@ -98,23 +121,25 @@ void ffi_prep_args(char *stack, extended |
| } |
| else |
| { |
| memcpy(argp, *p_argv, z); |
| } |
| p_argv++; |
| argp += z; |
| } |
| - |
| - return; |
| + |
| + /* Indicate the VFP registers used. */ |
| + return ecif->cif->vfp_used; |
| } |
| |
| /* Perform machine dependent cif processing */ |
| ffi_status ffi_prep_cif_machdep(ffi_cif *cif) |
| { |
| + int type_code; |
| /* Round the stack up to a multiple of 8 bytes. This isn't needed |
| everywhere, but it is on some platforms, and it doesn't harm anything |
| when it isn't needed. */ |
| cif->bytes = (cif->bytes + 7) & ~7; |
| |
| /* Set the return type flag */ |
| switch (cif->rtype->type) |
| { |
| @@ -125,137 +150,176 @@ ffi_status ffi_prep_cif_machdep(ffi_cif |
| break; |
| |
| case FFI_TYPE_SINT64: |
| case FFI_TYPE_UINT64: |
| cif->flags = (unsigned) FFI_TYPE_SINT64; |
| break; |
| |
| case FFI_TYPE_STRUCT: |
| - if (cif->rtype->size <= 4) |
| + if (cif->abi == FFI_VFP |
| + && (type_code = vfp_type_p (cif->rtype)) != 0) |
| + { |
| + /* A Composite Type passed in VFP registers, either |
| + FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */ |
| + cif->flags = (unsigned) type_code; |
| + } |
| + else if (cif->rtype->size <= 4) |
| /* A Composite Type not larger than 4 bytes is returned in r0. */ |
| cif->flags = (unsigned)FFI_TYPE_INT; |
| else |
| /* A Composite Type larger than 4 bytes, or whose size cannot |
| be determined statically ... is stored in memory at an |
| address passed [in r0]. */ |
| cif->flags = (unsigned)FFI_TYPE_STRUCT; |
| break; |
| |
| default: |
| cif->flags = FFI_TYPE_INT; |
| break; |
| } |
| |
| + /* Map out the register placements of VFP register args. |
| + The VFP hard-float calling conventions are slightly more sophisticated than |
| + the base calling conventions, so we do it here instead of in ffi_prep_args(). */ |
| + if (cif->abi == FFI_VFP) |
| + layout_vfp_args (cif); |
| + |
| return FFI_OK; |
| } |
| |
| -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, |
| - unsigned, unsigned, unsigned *, void (*fn)(void)); |
| +/* Prototypes for assembly functions, in sysv.S */ |
| +extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); |
| +extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); |
| |
| void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) |
| { |
| extended_cif ecif; |
| |
| int small_struct = (cif->flags == FFI_TYPE_INT |
| && cif->rtype->type == FFI_TYPE_STRUCT); |
| + int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT |
| + || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE); |
| |
| ecif.cif = cif; |
| ecif.avalue = avalue; |
| |
| unsigned int temp; |
| |
| /* If the return value is a struct and we don't have a return */ |
| /* value address then we need to make one */ |
| |
| if ((rvalue == NULL) && |
| (cif->flags == FFI_TYPE_STRUCT)) |
| { |
| ecif.rvalue = alloca(cif->rtype->size); |
| } |
| else if (small_struct) |
| ecif.rvalue = &temp; |
| + else if (vfp_struct) |
| + { |
| + /* Largest case is double x 4. */ |
| + ecif.rvalue = alloca(32); |
| + } |
| else |
| ecif.rvalue = rvalue; |
| |
| switch (cif->abi) |
| { |
| case FFI_SYSV: |
| - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, |
| - fn); |
| + ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); |
| + break; |
| |
| + case FFI_VFP: |
| + ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); |
| break; |
| + |
| default: |
| FFI_ASSERT(0); |
| break; |
| } |
| if (small_struct) |
| memcpy (rvalue, &temp, cif->rtype->size); |
| + else if (vfp_struct) |
| + memcpy (rvalue, ecif.rvalue, cif->rtype->size); |
| } |
| |
| /** private members **/ |
| |
| static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, |
| - void** args, ffi_cif* cif); |
| + void** args, ffi_cif* cif, float *vfp_stack); |
| |
| void ffi_closure_SYSV (ffi_closure *); |
| |
| +void ffi_closure_VFP (ffi_closure *); |
| + |
| /* This function is jumped to by the trampoline */ |
| |
| unsigned int |
| -ffi_closure_SYSV_inner (closure, respp, args) |
| +ffi_closure_SYSV_inner (closure, respp, args, vfp_args) |
| ffi_closure *closure; |
| void **respp; |
| void *args; |
| + void *vfp_args; |
| { |
| // our various things... |
| ffi_cif *cif; |
| void **arg_area; |
| |
| cif = closure->cif; |
| arg_area = (void**) alloca (cif->nargs * sizeof (void*)); |
| |
| /* this call will initialize ARG_AREA, such that each |
| * element in that array points to the corresponding |
| * value on the stack; and if the function returns |
| * a structure, it will re-set RESP to point to the |
| * structure return address. */ |
| |
| - ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); |
| + ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args); |
| |
| (closure->fun) (cif, *respp, arg_area, closure->user_data); |
| |
| return cif->flags; |
| } |
| |
| /*@-exportheader@*/ |
| static void |
| ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, |
| - void **avalue, ffi_cif *cif) |
| + void **avalue, ffi_cif *cif, |
| + /* Used only under VFP hard-float ABI. */ |
| + float *vfp_stack) |
| /*@=exportheader@*/ |
| { |
| - register unsigned int i; |
| + register unsigned int i, vi = 0; |
| register void **p_argv; |
| register char *argp; |
| register ffi_type **p_arg; |
| |
| argp = stack; |
| |
| if ( cif->flags == FFI_TYPE_STRUCT ) { |
| *rvalue = *(void **) argp; |
| argp += 4; |
| } |
| |
| p_argv = avalue; |
| |
| for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) |
| { |
| size_t z; |
| + size_t alignment; |
| + |
| + if (cif->abi == FFI_VFP |
| + && vi < cif->vfp_nargs && vfp_type_p (*p_arg)) |
| + { |
| + *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]); |
| + continue; |
| + } |
| |
| - size_t alignment = (*p_arg)->alignment; |
| + alignment = (*p_arg)->alignment; |
| if (alignment < 4) |
| alignment = 4; |
| /* Align if necessary */ |
| if ((alignment - 1) & (unsigned) argp) { |
| argp = (char *) ALIGN(argp, alignment); |
| } |
| |
| z = (*p_arg)->size; |
| @@ -290,20 +354,147 @@ ffi_prep_incoming_args_SYSV(char *stack, |
| |
| ffi_status |
| ffi_prep_closure_loc (ffi_closure* closure, |
| ffi_cif* cif, |
| void (*fun)(ffi_cif*,void*,void**,void*), |
| void *user_data, |
| void *codeloc) |
| { |
| - FFI_ASSERT (cif->abi == FFI_SYSV); |
| + void (*closure_func)(ffi_closure*) = NULL; |
| |
| + if (cif->abi == FFI_SYSV) |
| + closure_func = &ffi_closure_SYSV; |
| + else if (cif->abi == FFI_VFP) |
| + closure_func = &ffi_closure_VFP; |
| + else |
| + FFI_ASSERT (0); |
| + |
| FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ |
| - &ffi_closure_SYSV, \ |
| + closure_func, \ |
| codeloc); |
| |
| closure->cif = cif; |
| closure->user_data = user_data; |
| closure->fun = fun; |
| |
| return FFI_OK; |
| } |
| + |
| +/* Below are routines for VFP hard-float support. */ |
| + |
| +static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum) |
| +{ |
| + switch (t->type) |
| + { |
| + case FFI_TYPE_FLOAT: |
| + case FFI_TYPE_DOUBLE: |
| + *elt = (int) t->type; |
| + *elnum = 1; |
| + return 1; |
| + |
| + case FFI_TYPE_STRUCT_VFP_FLOAT: |
| + *elt = FFI_TYPE_FLOAT; |
| + *elnum = t->size / sizeof (float); |
| + return 1; |
| + |
| + case FFI_TYPE_STRUCT_VFP_DOUBLE: |
| + *elt = FFI_TYPE_DOUBLE; |
| + *elnum = t->size / sizeof (double); |
| + return 1; |
| + |
| + case FFI_TYPE_STRUCT:; |
| + { |
| + int base_elt = 0, total_elnum = 0; |
| + ffi_type **el = t->elements; |
| + while (*el) |
| + { |
| + int el_elt = 0, el_elnum = 0; |
| + if (! rec_vfp_type_p (*el, &el_elt, &el_elnum) |
| + || (base_elt && base_elt != el_elt) |
| + || total_elnum + el_elnum > 4) |
| + return 0; |
| + base_elt = el_elt; |
| + total_elnum += el_elnum; |
| + el++; |
| + } |
| + *elnum = total_elnum; |
| + *elt = base_elt; |
| + return 1; |
| + } |
| + default: ; |
| + } |
| + return 0; |
| +} |
| + |
| +static int vfp_type_p (ffi_type *t) |
| +{ |
| + int elt, elnum; |
| + if (rec_vfp_type_p (t, &elt, &elnum)) |
| + { |
| + if (t->type == FFI_TYPE_STRUCT) |
| + { |
| + if (elnum == 1) |
| + t->type = elt; |
| + else |
| + t->type = (elt == FFI_TYPE_FLOAT |
| + ? FFI_TYPE_STRUCT_VFP_FLOAT |
| + : FFI_TYPE_STRUCT_VFP_DOUBLE); |
| + } |
| + return (int) t->type; |
| + } |
| + return 0; |
| +} |
| + |
| +static void place_vfp_arg (ffi_cif *cif, ffi_type *t) |
| +{ |
| + int reg = cif->vfp_reg_free; |
| + int nregs = t->size / sizeof (float); |
| + int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT |
| + || t->type == FFI_TYPE_FLOAT) ? 1 : 2); |
| + /* Align register number. */ |
| + if ((reg & 1) && align == 2) |
| + reg++; |
| + while (reg + nregs <= 16) |
| + { |
| + int s, new_used = 0; |
| + for (s = reg; s < reg + nregs; s++) |
| + { |
| + new_used |= (1 << s); |
| + if (cif->vfp_used & (1 << s)) |
| + { |
| + reg += align; |
| + goto next_reg; |
| + } |
| + } |
| + /* Found regs to allocate. */ |
| + cif->vfp_used |= new_used; |
| + cif->vfp_args[cif->vfp_nargs++] = reg; |
| + |
| + /* Update vfp_reg_free. */ |
| + if (cif->vfp_used & (1 << cif->vfp_reg_free)) |
| + { |
| + reg += nregs; |
| + while (cif->vfp_used & (1 << reg)) |
| + reg += 1; |
| + cif->vfp_reg_free = reg; |
| + } |
| + return; |
| + next_reg: ; |
| + } |
| +} |
| + |
| +static void layout_vfp_args (ffi_cif *cif) |
| +{ |
| + int i; |
| + /* Init VFP fields */ |
| + cif->vfp_used = 0; |
| + cif->vfp_nargs = 0; |
| + cif->vfp_reg_free = 0; |
| + memset (cif->vfp_args, -1, 16); /* Init to -1. */ |
| + |
| + for (i = 0; i < cif->nargs; i++) |
| + { |
| + ffi_type *t = cif->arg_types[i]; |
| + if (vfp_type_p (t)) |
| + place_vfp_arg (cif, t); |
| + } |
| +} |
| diff --git a/js/src/ctypes/libffi/src/arm/ffitarget.h b/js/src/ctypes/libffi/src/arm/ffitarget.h |
| --- a/js/src/ctypes/libffi/src/arm/ffitarget.h |
| +++ b/js/src/ctypes/libffi/src/arm/ffitarget.h |
| @@ -29,21 +29,35 @@ |
| |
| #ifndef LIBFFI_ASM |
| typedef unsigned long ffi_arg; |
| typedef signed long ffi_sarg; |
| |
| typedef enum ffi_abi { |
| FFI_FIRST_ABI = 0, |
| FFI_SYSV, |
| + FFI_VFP, |
| FFI_LAST_ABI, |
| +#ifdef __ARM_PCS_VFP |
| + FFI_DEFAULT_ABI = FFI_VFP |
| +#else |
| FFI_DEFAULT_ABI = FFI_SYSV |
| +#endif |
| } ffi_abi; |
| #endif |
| |
| +#define FFI_EXTRA_CIF_FIELDS \ |
| + int vfp_used; \ |
| + short vfp_reg_free, vfp_nargs; \ |
| + signed char vfp_args[16] \ |
| + |
| +/* Internally used. */ |
| +#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1) |
| +#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2) |
| + |
| /* ---- Definitions for closures ----------------------------------------- */ |
| |
| #define FFI_CLOSURES 1 |
| #define FFI_TRAMPOLINE_SIZE 20 |
| #define FFI_NATIVE_RAW_API 0 |
| |
| #endif |
| |
| diff --git a/js/src/ctypes/libffi/src/arm/sysv.S b/js/src/ctypes/libffi/src/arm/sysv.S |
| --- a/js/src/ctypes/libffi/src/arm/sysv.S |
| +++ b/js/src/ctypes/libffi/src/arm/sysv.S |
| @@ -137,54 +137,52 @@ |
| ldr\cond pc, [sp], #4 |
| .else |
| ldm\cond\dirn sp!, {\regs, pc} |
| .endif |
| #endif |
| .endm |
| |
| |
| - @ r0: ffi_prep_args |
| + @ r0: fn |
| @ r1: &ecif |
| @ r2: cif->bytes |
| @ r3: fig->flags |
| @ sp+0: ecif.rvalue |
| - @ sp+4: fn |
| |
| @ This assumes we are using gas. |
| ARM_FUNC_START ffi_call_SYSV |
| @ Save registers |
| stmfd sp!, {r0-r3, fp, lr} |
| UNWIND .save {r0-r3, fp, lr} |
| mov fp, sp |
| |
| UNWIND .setfp fp, sp |
| |
| @ Make room for all of the new args. |
| sub sp, fp, r2 |
| |
| @ Place all of the ffi_prep_args in position |
| - mov ip, r0 |
| mov r0, sp |
| @ r1 already set |
| |
| @ Call ffi_prep_args(stack, &ecif) |
| - call_reg(ip) |
| + bl ffi_prep_args |
| |
| @ move first 4 parameters in registers |
| ldmia sp, {r0-r3} |
| |
| @ and adjust stack |
| - ldr ip, [fp, #8] |
| - cmp ip, #16 |
| - movhs ip, #16 |
| - add sp, sp, ip |
| + sub lr, fp, sp @ cif->bytes == fp - sp |
| + ldr ip, [fp] @ load fn() in advance |
| + cmp lr, #16 |
| + movhs lr, #16 |
| + add sp, sp, lr |
| |
| @ call (fn) (...) |
| - ldr ip, [fp, #28] |
| call_reg(ip) |
| |
| @ Remove the space we pushed for the args |
| mov sp, fp |
| |
| @ Load r2 with the pointer to storage for the return value |
| ldr r2, [sp, #24] |
| |
| @@ -225,16 +223,111 @@ ARM_FUNC_START ffi_call_SYSV |
| |
| LSYM(Lepilogue): |
| RETLDM "r0-r3,fp" |
| |
| .ffi_call_SYSV_end: |
| UNWIND .fnend |
| .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) |
| |
| + |
| + @ r0: fn |
| + @ r1: &ecif |
| + @ r2: cif->bytes |
| + @ r3: fig->flags |
| + @ sp+0: ecif.rvalue |
| + |
| +ARM_FUNC_START ffi_call_VFP |
| + @ Save registers |
| + stmfd sp!, {r0-r3, fp, lr} |
| + UNWIND .save {r0-r3, fp, lr} |
| + mov fp, sp |
| + UNWIND .setfp fp, sp |
| + |
| + @ Make room for all of the new args. |
| + sub sp, sp, r2 |
| + |
| + @ Make room for loading VFP args |
| + sub sp, sp, #64 |
| + |
| + @ Place all of the ffi_prep_args in position |
| + mov r0, sp |
| + @ r1 already set |
| + sub r2, fp, #64 @ VFP scratch space |
| + |
| + @ Call ffi_prep_args(stack, &ecif, vfp_space) |
| + bl ffi_prep_args |
| + |
| + @ Load VFP register args if needed |
| + cmp r0, #0 |
| + beq LSYM(Lbase_args) |
| + |
| + @ Load only d0 if possible |
| + cmp r0, #3 |
| + sub ip, fp, #64 |
| + flddle d0, [ip] |
| + fldmiadgt ip, {d0-d7} |
| + |
| +LSYM(Lbase_args): |
| + @ move first 4 parameters in registers |
| + ldmia sp, {r0-r3} |
| + |
| + @ and adjust stack |
| + sub lr, ip, sp @ cif->bytes == (fp - 64) - sp |
| + ldr ip, [fp] @ load fn() in advance |
| + cmp lr, #16 |
| + movhs lr, #16 |
| + add sp, sp, lr |
| + |
| + @ call (fn) (...) |
| + call_reg(ip) |
| + |
| + @ Remove the space we pushed for the args |
| + mov sp, fp |
| + |
| + @ Load r2 with the pointer to storage for |
| + @ the return value |
| + ldr r2, [sp, #24] |
| + |
| + @ Load r3 with the return type code |
| + ldr r3, [sp, #12] |
| + |
| + @ If the return value pointer is NULL, |
| + @ assume no return value. |
| + cmp r2, #0 |
| + beq LSYM(Lepilogue_vfp) |
| + |
| + cmp r3, #FFI_TYPE_INT |
| + streq r0, [r2] |
| + beq LSYM(Lepilogue_vfp) |
| + |
| + cmp r3, #FFI_TYPE_SINT64 |
| + stmeqia r2, {r0, r1} |
| + beq LSYM(Lepilogue_vfp) |
| + |
| + cmp r3, #FFI_TYPE_FLOAT |
| + fstseq s0, [r2] |
| + beq LSYM(Lepilogue_vfp) |
| + |
| + cmp r3, #FFI_TYPE_DOUBLE |
| + fstdeq d0, [r2] |
| + beq LSYM(Lepilogue_vfp) |
| + |
| + cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT |
| + cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE |
| + fstmiadeq r2, {d0-d3} |
| + |
| +LSYM(Lepilogue_vfp): |
| + RETLDM "r0-r3,fp" |
| + |
| +.ffi_call_VFP_end: |
| + UNWIND .fnend |
| + .size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP) |
| + |
| + |
| /* |
| unsigned int FFI_HIDDEN |
| ffi_closure_SYSV_inner (closure, respp, args) |
| ffi_closure *closure; |
| void **respp; |
| void *args; |
| */ |
| |
| @@ -297,11 +390,73 @@ ARM_FUNC_START ffi_closure_SYSV |
| ldfd f0, [sp] |
| b .Lclosure_epilogue |
| #endif |
| |
| .ffi_closure_SYSV_end: |
| UNWIND .fnend |
| .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) |
| |
| + |
| +ARM_FUNC_START ffi_closure_VFP |
| + fstmfdd sp!, {d0-d7} |
| + @ r0-r3, then d0-d7 |
| + UNWIND .pad #80 |
| + add ip, sp, #80 |
| + stmfd sp!, {ip, lr} |
| + UNWIND .save {r0, lr} |
| + add r2, sp, #72 |
| + add r3, sp, #8 |
| + .pad #72 |
| + sub sp, sp, #72 |
| + str sp, [sp, #64] |
| + add r1, sp, #64 |
| + bl ffi_closure_SYSV_inner |
| + |
| + cmp r0, #FFI_TYPE_INT |
| + beq .Lretint_vfp |
| + |
| + cmp r0, #FFI_TYPE_FLOAT |
| + beq .Lretfloat_vfp |
| + |
| + cmp r0, #FFI_TYPE_DOUBLE |
| + cmpne r0, #FFI_TYPE_LONGDOUBLE |
| + beq .Lretdouble_vfp |
| + |
| + cmp r0, #FFI_TYPE_SINT64 |
| + beq .Lretlonglong_vfp |
| + |
| + cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT |
| + beq .Lretfloat_struct_vfp |
| + |
| + cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE |
| + beq .Lretdouble_struct_vfp |
| + |
| +.Lclosure_epilogue_vfp: |
| + add sp, sp, #72 |
| + ldmfd sp, {sp, pc} |
| + |
| +.Lretfloat_vfp: |
| + flds s0, [sp] |
| + b .Lclosure_epilogue_vfp |
| +.Lretdouble_vfp: |
| + fldd d0, [sp] |
| + b .Lclosure_epilogue_vfp |
| +.Lretint_vfp: |
| + ldr r0, [sp] |
| + b .Lclosure_epilogue_vfp |
| +.Lretlonglong_vfp: |
| + ldmia sp, {r0, r1} |
| + b .Lclosure_epilogue_vfp |
| +.Lretfloat_struct_vfp: |
| + fldmiad sp, {d0-d1} |
| + b .Lclosure_epilogue_vfp |
| +.Lretdouble_struct_vfp: |
| + fldmiad sp, {d0-d3} |
| + b .Lclosure_epilogue_vfp |
| + |
| +.ffi_closure_VFP_end: |
| + UNWIND .fnend |
| + .size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP) |
| + |
| #if defined __ELF__ && defined __linux__ |
| .section .note.GNU-stack,"",%progbits |
| #endif |
| diff --git a/js/src/ctypes/libffi/src/x86/ffi64.c b/js/src/ctypes/libffi/src/x86/ffi64.c |
| --- a/js/src/ctypes/libffi/src/x86/ffi64.c |
| +++ b/js/src/ctypes/libffi/src/x86/ffi64.c |
| @@ -373,29 +373,29 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
| || gprcount + ngpr > MAX_GPR_REGS |
| || ssecount + nsse > MAX_SSE_REGS) |
| { |
| long align = cif->arg_types[i]->alignment; |
| |
| if (align < 8) |
| align = 8; |
| |
| - bytes = ALIGN(bytes, align); |
| + bytes = ALIGN (bytes, align); |
| bytes += cif->arg_types[i]->size; |
| } |
| else |
| { |
| gprcount += ngpr; |
| ssecount += nsse; |
| } |
| } |
| if (ssecount) |
| flags |= 1 << 11; |
| cif->flags = flags; |
| - cif->bytes = bytes; |
| + cif->bytes = ALIGN (bytes, 8); |
| |
| return FFI_OK; |
| } |
| |
| void |
| ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) |
| { |
| enum x86_64_reg_class classes[MAX_CLASSES]; |
| diff --git a/js/src/ctypes/libffi/testsuite/lib/libffi-dg.exp b/js/src/ctypes/libffi/testsuite/lib/libffi-dg.exp |
| --- a/js/src/ctypes/libffi/testsuite/lib/libffi-dg.exp |
| +++ b/js/src/ctypes/libffi/testsuite/lib/libffi-dg.exp |
| @@ -261,16 +261,66 @@ proc dg-xfail-if { args } { |
| set args [lreplace $args 0 0] |
| set selector "target [join [lindex $args 1]]" |
| if { [dg-process-target $selector] == "S" } { |
| global compiler_conditional_xfail_data |
| set compiler_conditional_xfail_data $args |
| } |
| } |
| |
| +proc check-flags { args } { |
| + |
| + # The args are within another list; pull them out. |
| + set args [lindex $args 0] |
| + |
| + # The next two arguments are optional. If they were not specified, |
| + # use the defaults. |
| + if { [llength $args] == 2 } { |
| + lappend $args [list "*"] |
| + } |
| + if { [llength $args] == 3 } { |
| + lappend $args [list ""] |
| + } |
| + |
| + # If the option strings are the defaults, or the same as the |
| + # defaults, there is no need to call check_conditional_xfail to |
| + # compare them to the actual options. |
| + if { [string compare [lindex $args 2] "*"] == 0 |
| + && [string compare [lindex $args 3] "" ] == 0 } { |
| + set result 1 |
| + } else { |
| + # The target list might be an effective-target keyword, so replace |
| + # the original list with "*-*-*", since we already know it matches. |
| + set result [check_conditional_xfail [lreplace $args 1 1 "*-*-*"]] |
| + } |
| + |
| + return $result |
| +} |
| + |
| +proc dg-skip-if { args } { |
| + # Verify the number of arguments. The last two are optional. |
| + set args [lreplace $args 0 0] |
| + if { [llength $args] < 2 || [llength $args] > 4 } { |
| + error "dg-skip-if 2: need 2, 3, or 4 arguments" |
| + } |
| + |
| + # Don't bother if we're already skipping the test. |
| + upvar dg-do-what dg-do-what |
| + if { [lindex ${dg-do-what} 1] == "N" } { |
| + return |
| + } |
| + |
| + set selector [list target [lindex $args 1]] |
| + if { [dg-process-target $selector] == "S" } { |
| + if [check-flags $args] { |
| + upvar dg-do-what dg-do-what |
| + set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"] |
| + } |
| + } |
| +} |
| |
| # We need to make sure that additional_files and additional_sources |
| # are both cleared out after every test. It is not enough to clear |
| # them out *before* the next test run because gcc-target-compile gets |
| # run directly from some .exp files (outside of any test). (Those |
| # uses should eventually be eliminated.) |
| |
| # Because the DG framework doesn't provide a hook that is run at the |
| diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/cls_double_va.c b/js/src/ctypes/libffi/testsuite/libffi.call/cls_double_va.c |
| --- a/js/src/ctypes/libffi/testsuite/libffi.call/cls_double_va.c |
| +++ b/js/src/ctypes/libffi/testsuite/libffi.call/cls_double_va.c |
| @@ -1,16 +1,18 @@ |
| /* Area: ffi_call, closure_call |
| Purpose: Test doubles passed in variable argument lists. |
| Limitations: none. |
| PR: none. |
| Originator: Blake Chaffin 6/6/2007 */ |
| |
| /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ |
| /* { dg-output "" { xfail avr32*-*-* } } */ |
| +/* { dg-skip-if "" arm*-*-* { "-mfloat-abi=hard" } { "" } } */ |
| + |
| #include "ffitest.h" |
| |
| static void |
| cls_double_va_fn(ffi_cif* cif __UNUSED__, void* resp, |
| void** args, void* userdata __UNUSED__) |
| { |
| char* format = *(char**)args[0]; |
| double doubleValue = *(double*)args[1]; |
| diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/cls_longdouble_va.c b/js/src/ctypes/libffi/testsuite/libffi.call/cls_longdouble_va.c |
| --- a/js/src/ctypes/libffi/testsuite/libffi.call/cls_longdouble_va.c |
| +++ b/js/src/ctypes/libffi/testsuite/libffi.call/cls_longdouble_va.c |
| @@ -1,16 +1,18 @@ |
| /* Area: ffi_call, closure_call |
| Purpose: Test long doubles passed in variable argument lists. |
| Limitations: none. |
| PR: none. |
| Originator: Blake Chaffin 6/6/2007 */ |
| |
| /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ |
| /* { dg-output "" { xfail avr32*-*-* x86_64-*-mingw* } } */ |
| +/* { dg-skip-if "" arm*-*-* { "-mfloat-abi=hard" } { "" } } */ |
| + |
| #include "ffitest.h" |
| |
| static void |
| cls_longdouble_va_fn(ffi_cif* cif __UNUSED__, void* resp, |
| void** args, void* userdata __UNUSED__) |
| { |
| char* format = *(char**)args[0]; |
| long double ldValue = *(long double*)args[1]; |