diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-04-11 09:13:11 +0000 |
---|---|---|
committer | <> | 2014-04-23 12:05:38 +0000 |
commit | 6af3fdec2262dd94954acc5e426ef71cbd4521d3 (patch) | |
tree | 9be02de9a80f7935892a2d03741adee44723e65d /libffi | |
parent | 19be2b4342ac32e9edc78ce6fed8f61b63ae98d1 (diff) | |
download | gcc-tarball-6af3fdec2262dd94954acc5e426ef71cbd4521d3.tar.gz |
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-4.7.3.tar.bz2.gcc-4.7.3
Diffstat (limited to 'libffi')
31 files changed, 1043 insertions, 471 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 1fa5b279f6..5077968302 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,10 +1,135 @@ -2011-10-26 Release Manager +2013-04-11 Release Manager - * GCC 4.6.2 released. + * GCC 4.7.3 released. -2011-10-04 Andrew Haley <aph@redhat.com> +2012-09-20 Jakub Jelinek <jakub@redhat.com> - * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Clear icache. + PR other/43620 + * configure.ac (AM_INIT_AUTOMAKE): Add no-dist. + * Makefile.in: Regenerated. + * include/Makefile.in: Regenerated. + * man/Makefile.in: Regenerated. + * testsuite/Makefile.in: Regenerated. + +2012-09-20 Release Manager + + * GCC 4.7.2 released. + +2012-06-14 Release Manager + + * GCC 4.7.1 released. + +2012-03-22 David Edelsohn <dje.gcc@gmail.com> + + Backport from mainline: + 2012-03-09 David Edelsohn <dje.gcc@gmail.com> + + * src/powerpc/aix_closure.S (ffi_closure_ASM): Adjust for Darwin64 + change to return value of ffi_closure_helper_DARWIN and load type + from return type. + + From Tom Honermann <tom.honermann@oracle.com>: + * src/powerpc/aix.S: Declare .ffi_prep_args. Insert nops after + branch instructions. + * src/powerpc/aix_closure.S: Declare .ffi_closure_helper_DARWIN. + +2012-03-22 Release Manager + + * GCC 4.7.0 released. + +2012-02-27 Mikael Pettersson <mikpe@it.uu.se> + + PR libffi/52223 + * Makefile.am (FLAGS_TO_PASS): Define. + * Makefile.in: Regenerate. + +2012-02-23 Kai Tietz <ktietz@redhat.com> + + PR libffi/52221 + * src/x86/ffi.c (ffi_closure_raw_THISCALL): New + prototype. + (ffi_prep_raw_closure_loc): Use ffi_closure_raw_THISCALL for + thiscall-convention. + (ffi_raw_call): Use ffi_prep_args_raw. + * src/x86/win32.S (ffi_closure_raw_THISCALL): Add + implementation for stub. + +2012-02-13 Kai Tietz <ktietz@redhat.com> + + PR libffi/52221 + * src/x86/ffi.c (ffi_prep_raw_closure_loc): Add thiscall + support for X86_WIN32. + (FFI_INIT_TRAMPOLINE_THISCALL): Fix displacement. + +2012-02-11 Eric Botcazou <ebotcazou@adacore.com> + + * src/sparc/v9.S (STACKFRAME): Bump to 176. + +2012-02-10 Kai Tietz <ktietz@redhat.com> + + * configure.ac (AM_LTLDFLAGS): Add -no-undefine for x64 + windows target. + * configure: Regenerated. + +2012-02-08 Kai Tietz <ktietz@redhat.com> + + * src/prep_cif.c (ffi_prep_cif): Allow for X86_WIN32 + also FFI_THISCALL. + * src/x86/ffi.c (ffi_closure_THISCALL): Add prototype. + (FFI_INIT_TRAMPOLINE_THISCALL): New trampoline code. + (ffi_prep_closure_loc): Add FFI_THISCALL support. + * src/x86/ffitarget.h (FFI_TRAMPOLINE_SIZE): Adjust size. + * src/x86/win32.S (ffi_closure_THISCALL): New closure code + for thiscall-calling convention. + * testsuite/libffi.call/closure_thiscall.c: New test. + +2012-01-28 Kai Tietz <ktietz@redhat.com> + + * src/libffi/src/x86/ffi.c (ffi_call_win32): Add new + argument to prototype for specify calling-convention. + (ffi_call): Add support for stdcall/thiscall convention. + (ffi_prep_args): Likewise. + (ffi_raw_call): Likewise. + * src/x86/ffitarget.h (ffi_abi): Add FFI_THISCALL and + FFI_FASTCALL. + * src/x86/win32.S (_ffi_call_win32): Add support for + fastcall/thiscall calling-convention calls. + * testsuite/libffi.call/fastthis1_win32.c: New test. + * testsuite/libffi.call/fastthis2_win32.c: New test. + * testsuite/libffi.call/fastthis3_win32.c: New test. + * testsuite/libffi.call/strlen2_win32.c: New test. + * testsuite/libffi.call/many2_win32.c: New test. + * testsuite/libffi.call/struct1_win32.c: New test. + * testsuite/libffi.call/struct2_win32.c: New test. + +2012-01-23 Andreas Schwab <schwab@linux-m68k.org> + + * src/m68k/sysv.S (ffi_call_SYSV): Properly test for plain + mc68000. Test for __HAVE_68881__ in addition to __MC68881__. + +2012-01-19 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/48496 + * src/ia64/ffi.c (ffi_call): Fix up aliasing violations. + +2012-01-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac (i?86-*-*): Set TARGET to X86_64. + * configure: Regenerate. + +2011-12-07 Andrew Pinski <apinski@cavium.com> + + PR libffi/50051 + * src/mips/n32.S: Add ".set mips4". + +2011-11-21 Andreas Tobler <andreast@fgznet.ch> + + * configure: Regenerate. + +2011-11-10 Richard Henderson <rth@redhat.com> + + * configure.ac (GCC_AS_CFI_PSEUDO_OP): Use it instead of inline check. + * configure, aclocal.m4: Rebuild. 2011-09-04 Iain Sandoe <iains@gcc.gnu.org> @@ -12,6 +137,16 @@ * src/powerpc/darwin_closure.S (stubs): Make the stub binding helper reference track the architecture pointer size. +2011-08-25 Andrew Haley <aph@redhat.com> + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Remove hard-coded assembly + instructions. + * src/arm/sysv.S (ffi_arm_trampoline): Put them here instead. + +2011-07-11 Andrew Haley <aph@redhat.com> + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Clear icache. + 2011-06-29 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * testsuite/libffi.call/cls_double_va.c: Move PR number to comment. @@ -24,24 +159,21 @@ mips-sgi-irix6*. * testsuite/libffi.call/cls_longdouble_va.c: Likewise. -2011-06-27 Release Manager - - * GCC 4.6.1 released. +2011-06-14 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> -2011-05-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + * testsuite/libffi.call/huge_struct.c (test_large_fn): Use PRIu8, + PRId8 instead of %hhu, %hhd. + * testsuite/libffi.call/ffitest.h [__alpha__ && __osf__] (PRId8, + PRIu8): Define. + [__sgi__] (PRId8, PRIu8): Define. - Backport from mainline: - 2011-04-29 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> +2011-04-29 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * src/alpha/osf.S (UA_SI, FDE_ENCODING, FDE_ENCODE, FDE_ARANGE): Define. Use them to handle ELF vs. ECOFF differences. [__osf__] (_GLOBAL__F_ffi_call_osf): Define. -2011-03-25 Release Manager - - * GCC 4.6.0 released. - 2011-02-13 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> * configure: Regenerate. diff --git a/libffi/Makefile.am b/libffi/Makefile.am index ccbefe64da..23e002e964 100644 --- a/libffi/Makefile.am +++ b/libffi/Makefile.am @@ -76,6 +76,9 @@ AM_MAKEFLAGS = \ "RANLIB=$(RANLIB)" \ "DESTDIR=$(DESTDIR)" +# Subdir rules rely on $(FLAGS_TO_PASS) +FLAGS_TO_PASS = $(AM_MAKEFLAGS) + MAKEOVERRIDES= toolexeclib_LTLIBRARIES = libffi.la diff --git a/libffi/Makefile.in b/libffi/Makefile.in index 3ac6d29b87..7b438cb9fc 100644 --- a/libffi/Makefile.in +++ b/libffi/Makefile.in @@ -61,15 +61,13 @@ target_triplet = @target@ @PA_LINUX_TRUE@am__append_24 = src/pa/linux.S src/pa/ffi.c @PA_HPUX_TRUE@am__append_25 = src/pa/hpux32.S src/pa/ffi.c subdir = . -DIST_COMMON = README $(am__configure_deps) $(srcdir)/../compile \ - $(srcdir)/../config.guess $(srcdir)/../config.sub \ - $(srcdir)/../depcomp $(srcdir)/../install-sh \ - $(srcdir)/../ltmain.sh $(srcdir)/../missing \ - $(srcdir)/../mkinstalldirs $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/fficonfig.h.in \ - $(top_srcdir)/configure ChangeLog +DIST_COMMON = README ChangeLog $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(srcdir)/fficonfig.h.in \ + $(srcdir)/../mkinstalldirs $(srcdir)/../depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/../config/asmcfi.m4 \ + $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/lead-dot.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/override.m4 \ @@ -201,7 +199,6 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ 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) MULTISRCTOP = MULTIBUILDTOP = MULTIDIRS = @@ -218,47 +215,10 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ - $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ - distdir dist dist-all distcheck + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -distdir = $(PACKAGE)-$(VERSION) -top_distdir = $(distdir) -am__remove_distdir = \ - { test ! -d "$(distdir)" \ - || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -fr "$(distdir)"; }; } -am__relativize = \ - dir0=`pwd`; \ - sed_first='s,^\([^/]*\)/.*$$,\1,'; \ - sed_rest='s,^[^/]*/*,,'; \ - sed_last='s,^.*/\([^/]*\)$$,\1,'; \ - sed_butlast='s,/*[^/]*$$,,'; \ - while test -n "$$dir1"; do \ - first=`echo "$$dir1" | sed -e "$$sed_first"`; \ - if test "$$first" != "."; then \ - if test "$$first" = ".."; then \ - dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ - dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ - else \ - first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ - if test "$$first2" = "$$first"; then \ - dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ - else \ - dir2="../$$dir2"; \ - fi; \ - dir0="$$dir0"/"$$first"; \ - fi; \ - fi; \ - dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ - done; \ - reldir="$$dir2" -DIST_ARCHIVES = $(distdir).tar.gz -GZIP_ENV = --best -distuninstallcheck_listfiles = find . -type f -print -distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ @@ -455,6 +415,9 @@ AM_MAKEFLAGS = \ "RANLIB=$(RANLIB)" \ "DESTDIR=$(DESTDIR)" + +# Subdir rules rely on $(FLAGS_TO_PASS) +FLAGS_TO_PASS = $(AM_MAKEFLAGS) MAKEOVERRIDES = toolexeclib_LTLIBRARIES = libffi.la noinst_LTLIBRARIES = libffi_convenience.la @@ -1184,182 +1147,6 @@ GTAGS: distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - $(am__remove_distdir) - test -d "$(distdir)" || mkdir "$(distdir)" - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - test -d "$(distdir)/$$subdir" \ - || $(MKDIR_P) "$(distdir)/$$subdir" \ - || exit 1; \ - fi; \ - done - @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - if test "$$subdir" = .; then :; else \ - dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ - $(am__relativize); \ - new_distdir=$$reldir; \ - dir1=$$subdir; dir2="$(top_distdir)"; \ - $(am__relativize); \ - new_top_distdir=$$reldir; \ - echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ - echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ - ($(am__cd) $$subdir && \ - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$new_top_distdir" \ - distdir="$$new_distdir" \ - am__remove_distdir=: \ - am__skip_length_check=: \ - am__skip_mode_fix=: \ - distdir) \ - || exit 1; \ - fi; \ - done - -test -n "$(am__skip_mode_fix)" \ - || find "$(distdir)" -type d ! -perm -755 \ - -exec chmod u+rwx,go+rx {} \; -o \ - ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ - || chmod -R a+r "$(distdir)" -dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -dist-bzip2: distdir - tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 - $(am__remove_distdir) - -dist-lzma: distdir - tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma - $(am__remove_distdir) - -dist-xz: distdir - tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz - $(am__remove_distdir) - -dist-tarZ: distdir - tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__remove_distdir) - -dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__remove_distdir) - -dist-zip: distdir - -rm -f $(distdir).zip - zip -rq $(distdir).zip $(distdir) - $(am__remove_distdir) - -dist dist-all: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -# This target untars the dist file and tries a VPATH configuration. Then -# it guarantees that the distribution is self-contained by making another -# tarfile. -distcheck: dist - case '$(DIST_ARCHIVES)' in \ - *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ - *.tar.bz2*) \ - bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.lzma*) \ - lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ - *.tar.xz*) \ - xz -dc $(distdir).tar.xz | $(am__untar) ;;\ - *.tar.Z*) \ - uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ - *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ - *.zip*) \ - unzip $(distdir).zip ;;\ - esac - chmod -R a-w $(distdir); chmod a+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst - chmod a-w $(distdir) - test -d $(distdir)/_build || exit 0; \ - dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ - && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ - && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ - $(DISTCHECK_CONFIGURE_FLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ - && $(MAKE) $(AM_MAKEFLAGS) check \ - && $(MAKE) $(AM_MAKEFLAGS) install \ - && $(MAKE) $(AM_MAKEFLAGS) installcheck \ - && $(MAKE) $(AM_MAKEFLAGS) uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ - distuninstallcheck \ - && chmod -R a-w "$$dc_install_base" \ - && ({ \ - (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ - distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ - } || { rm -rf "$$dc_destdir"; exit 1; }) \ - && rm -rf "$$dc_destdir" \ - && $(MAKE) $(AM_MAKEFLAGS) dist \ - && rm -rf $(DIST_ARCHIVES) \ - && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ - && cd "$$am__cwd" \ - || exit 1 - $(am__remove_distdir) - @(echo "$(distdir) archives ready for distribution: "; \ - list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' -distuninstallcheck: - @$(am__cd) '$(distuninstallcheck_dir)' \ - && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ - || { echo "ERROR: files left after uninstall:" ; \ - if test -n "$(DESTDIR)"; then \ - echo " (check DESTDIR support)"; \ - fi ; \ - $(distuninstallcheck_listfiles) ; \ - exit 1; } >&2 -distcleancheck: distclean - @if test '$(srcdir)' = . ; then \ - echo "ERROR: distcleancheck can only run from a VPATH build" ; \ - exit 1 ; \ - fi - @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left in build directory after distclean:" ; \ - $(distcleancheck_listfiles) ; \ - exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) all-multi fficonfig.h @@ -1510,18 +1297,15 @@ uninstall-am: uninstall-toolexeclibLTLIBRARIES all all-am all-multi am--refresh check check-am clean \ clean-generic clean-libtool clean-multi \ clean-noinstLTLIBRARIES clean-toolexeclibLTLIBRARIES ctags \ - ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-lzma \ - dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \ - distclean-compile distclean-generic distclean-hdr \ - distclean-libtool distclean-multi distclean-tags \ - distcleancheck distdir distuninstallcheck dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-multi install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - install-toolexeclibLTLIBRARIES installcheck installcheck-am \ - installdirs installdirs-am maintainer-clean \ + ctags-recursive distclean distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-multi distclean-tags \ + dvi dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-multi \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-toolexeclibLTLIBRARIES installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic maintainer-clean-multi mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ mostlyclean-multi pdf pdf-am ps ps-am tags tags-recursive \ diff --git a/libffi/aclocal.m4 b/libffi/aclocal.m4 index f7ef2f8e28..9d6a6694fd 100644 --- a/libffi/aclocal.m4 +++ b/libffi/aclocal.m4 @@ -1025,6 +1025,7 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR +m4_include([../config/asmcfi.m4]) m4_include([../config/depstand.m4]) m4_include([../config/lead-dot.m4]) m4_include([../config/multi.m4]) diff --git a/libffi/configure b/libffi/configure index 6478747033..1591495390 100755 --- a/libffi/configure +++ b/libffi/configure @@ -9001,7 +9001,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) + freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes @@ -9914,7 +9914,7 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[123]*) objformat=aout ;; + freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi @@ -9932,7 +9932,7 @@ freebsd* | dragonfly*) esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) @@ -11368,7 +11368,7 @@ case "$host" in TARGET=X86_64; TARGETDIR=x86 ;; i?86-*-*) - TARGET=X86; TARGETDIR=x86 + TARGET=X86_64; TARGETDIR=x86 ;; ia64*-*-*) @@ -11435,6 +11435,15 @@ case "$host" in x86_64-*-cygwin* | x86_64-*-mingw*) TARGET=X86_WIN64; TARGETDIR=x86 + # All mingw/cygwin/win32 builds require -no-undefined for sharedlib. + # We must also check with_cross_host to decide if this is a native + # or cross-build and select where to install dlls appropriately. + if test -n "$with_cross_host" && + test x"$with_cross_host" != x"no"; then + AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"'; + else + AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"'; + fi ;; x86_64-*-*) @@ -12282,11 +12291,11 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .cfi pseudo-op support" >&5 $as_echo_n "checking assembler .cfi pseudo-op support... " >&6; } -if test "${libffi_cv_as_cfi_pseudo_op+set}" = set; then : +if test "${gcc_cv_as_cfi_pseudo_op+set}" = set; then : $as_echo_n "(cached) " >&6 else - libffi_cv_as_cfi_pseudo_op=unknown + gcc_cv_as_cfi_pseudo_op=unknown cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ asm (".cfi_startproc\n\t.cfi_endproc"); @@ -12299,20 +12308,21 @@ main () } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - libffi_cv_as_cfi_pseudo_op=yes + gcc_cv_as_cfi_pseudo_op=yes else - libffi_cv_as_cfi_pseudo_op=no + gcc_cv_as_cfi_pseudo_op=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_cfi_pseudo_op" >&5 -$as_echo "$libffi_cv_as_cfi_pseudo_op" >&6; } -if test "x$libffi_cv_as_cfi_pseudo_op" = xyes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_cfi_pseudo_op" >&5 +$as_echo "$gcc_cv_as_cfi_pseudo_op" >&6; } + if test "x$gcc_cv_as_cfi_pseudo_op" = xyes; then $as_echo "#define HAVE_AS_CFI_PSEUDO_OP 1" >>confdefs.h -fi + fi + if test x$TARGET = xSPARC; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler and linker support unaligned pc related relocs" >&5 diff --git a/libffi/configure.ac b/libffi/configure.ac index d16155a40f..c810b8590f 100644 --- a/libffi/configure.ac +++ b/libffi/configure.ac @@ -12,7 +12,7 @@ target_alias=${target_alias-$host_alias} . ${srcdir}/configure.host -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE([no-dist]) # The same as in boehm-gc and libstdc++. Have to borrow it from there. # We must force CC to /not/ be precious variables; otherwise @@ -99,7 +99,7 @@ case "$host" in TARGET=X86_64; TARGETDIR=x86 ;; i?86-*-*) - TARGET=X86; TARGETDIR=x86 + TARGET=X86_64; TARGETDIR=x86 ;; ia64*-*-*) @@ -166,6 +166,15 @@ case "$host" in x86_64-*-cygwin* | x86_64-*-mingw*) TARGET=X86_WIN64; TARGETDIR=x86 + # All mingw/cygwin/win32 builds require -no-undefined for sharedlib. + # We must also check with_cross_host to decide if this is a native + # or cross-build and select where to install dlls appropriately. + if test -n "$with_cross_host" && + test x"$with_cross_host" != x"no"; then + AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"'; + else + AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"'; + fi ;; x86_64-*-*) @@ -228,17 +237,7 @@ AC_SUBST(HAVE_LONG_DOUBLE) AC_C_BIGENDIAN -AC_CACHE_CHECK([assembler .cfi pseudo-op support], - libffi_cv_as_cfi_pseudo_op, [ - libffi_cv_as_cfi_pseudo_op=unknown - AC_TRY_COMPILE([asm (".cfi_startproc\n\t.cfi_endproc");],, - [libffi_cv_as_cfi_pseudo_op=yes], - [libffi_cv_as_cfi_pseudo_op=no]) -]) -if test "x$libffi_cv_as_cfi_pseudo_op" = xyes; then - AC_DEFINE(HAVE_AS_CFI_PSEUDO_OP, 1, - [Define if your assembler supports .cfi_* directives.]) -fi +GCC_AS_CFI_PSEUDO_OP if test x$TARGET = xSPARC; then AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs], diff --git a/libffi/include/Makefile.in b/libffi/include/Makefile.in index 781b9a8ce8..b76694b3b1 100644 --- a/libffi/include/Makefile.in +++ b/libffi/include/Makefile.in @@ -36,10 +36,11 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = include -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/ffi.h.in $(toollibffi_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/../config/asmcfi.m4 \ + $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/lead-dot.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/override.m4 \ @@ -54,7 +55,6 @@ CONFIG_HEADER = $(top_builddir)/fficonfig.h CONFIG_CLEAN_FILES = ffi.h ffitarget.h CONFIG_CLEAN_VPATH_FILES = SOURCES = -DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -80,7 +80,6 @@ am__installdirs = "$(DESTDIR)$(toollibffidir)" HEADERS = $(toollibffi_HEADERS) ETAGS = etags CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ @@ -329,37 +328,6 @@ GTAGS: distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done check-am: all-am check: check-am all-am: Makefile $(HEADERS) @@ -463,17 +431,16 @@ uninstall-am: uninstall-toollibffiHEADERS .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool ctags distclean distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip \ - install-toollibffiHEADERS installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ - ps ps-am tags uninstall uninstall-am \ - uninstall-toollibffiHEADERS + distclean-libtool distclean-tags dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip install-toollibffiHEADERS \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-toollibffiHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libffi/man/Makefile.in b/libffi/man/Makefile.in index 79466b353b..5af7ce4b47 100644 --- a/libffi/man/Makefile.in +++ b/libffi/man/Makefile.in @@ -35,9 +35,10 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = man -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/../config/asmcfi.m4 \ + $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/lead-dot.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/override.m4 \ @@ -52,7 +53,6 @@ CONFIG_HEADER = $(top_builddir)/fficonfig.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = -DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -78,7 +78,6 @@ man3dir = $(mandir)/man3 am__installdirs = "$(DESTDIR)$(man3dir)" NROFF = nroff MANS = $(man_MANS) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ @@ -292,50 +291,6 @@ TAGS: ctags: CTAGS CTAGS: - -distdir: $(DISTFILES) - @list='$(MANS)'; if test -n "$$list"; then \ - list=`for p in $$list; do \ - if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ - if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ - if test -n "$$list" && \ - grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ - echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ - grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ - echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ - echo " typically \`make maintainer-clean' will remove them" >&2; \ - exit 1; \ - else :; fi; \ - else :; fi - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done check-am: all-am check: check-am all-am: Makefile $(MANS) @@ -439,16 +394,16 @@ uninstall-man: uninstall-man3 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ - distclean distclean-generic distclean-libtool distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-man3 \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - uninstall uninstall-am uninstall-man uninstall-man3 + distclean distclean-generic distclean-libtool dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-man3 install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ + uninstall-man uninstall-man3 # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libffi/src/arm/ffi.c b/libffi/src/arm/ffi.c index 4e72c3bcd7..d526033363 100644 --- a/libffi/src/arm/ffi.c +++ b/libffi/src/arm/ffi.c @@ -337,14 +337,14 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, /* How to make a trampoline. */ +extern unsigned int ffi_arm_trampoline[3]; + #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ unsigned int __fun = (unsigned int)(FUN); \ unsigned int __ctx = (unsigned int)(CTX); \ unsigned char *insns = (unsigned char *)(CTX); \ - *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ - *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ - *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ + memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline); \ *(unsigned int*) &__tramp[12] = __ctx; \ *(unsigned int*) &__tramp[16] = __fun; \ __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \ diff --git a/libffi/src/arm/sysv.S b/libffi/src/arm/sysv.S index 72f0ee0ca0..be6493a25b 100644 --- a/libffi/src/arm/sysv.S +++ b/libffi/src/arm/sysv.S @@ -461,6 +461,11 @@ ARM_FUNC_START ffi_closure_VFP UNWIND .fnend .size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP) +ENTRY(ffi_arm_trampoline) + stmfd sp!, {r0-r3} + ldr r0, [pc] + ldr pc, [pc] + #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",%progbits #endif diff --git a/libffi/src/ia64/ffi.c b/libffi/src/ia64/ffi.c index 84b144868e..79e29b45a8 100644 --- a/libffi/src/ia64/ffi.c +++ b/libffi/src/ia64/ffi.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1998, 2007, 2008 Red Hat, Inc. + ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc. Copyright (c) 2000 Hewlett Packard Company IA64 Foreign Function Interface @@ -324,13 +324,17 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) case FFI_TYPE_FLOAT: if (gpcount < 8 && fpcount < 8) stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]); - stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i]; + { + UINT32 tmp; + memcpy (&tmp, avalue[i], sizeof (UINT32)); + stack->gp_regs[gpcount++] = tmp; + } break; case FFI_TYPE_DOUBLE: if (gpcount < 8 && fpcount < 8) stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]); - stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i]; + memcpy (&stack->gp_regs[gpcount++], avalue[i], sizeof (UINT64)); break; case FFI_TYPE_LONGDOUBLE: diff --git a/libffi/src/m68k/sysv.S b/libffi/src/m68k/sysv.S index c782f5192c..dfdd864438 100644 --- a/libffi/src/m68k/sysv.S +++ b/libffi/src/m68k/sysv.S @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 1998 Andreas Schwab + sysv.S - Copyright (c) 1998, 2012 Andreas Schwab Copyright (c) 2008 Red Hat, Inc. m68k Foreign Function Interface @@ -87,7 +87,7 @@ ffi_call_SYSV: | If the return value pointer is NULL, assume no return value. | NOTE: On the mc68000, tst on an address register is not supported. -#if defined(__mc68000__) && !defined(__mcoldfire__) +#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__) cmp.w #0, %a1 #else tst.l %a1 @@ -109,7 +109,7 @@ retlongint: retfloat: btst #2,%d2 jbeq retdouble -#if defined(__MC68881__) +#if defined(__MC68881__) || defined(__HAVE_68881__) fmove.s %fp0,(%a1) #else move.l %d0,(%a1) @@ -119,7 +119,7 @@ retfloat: retdouble: btst #3,%d2 jbeq retlongdouble -#if defined(__MC68881__) +#if defined(__MC68881__) || defined(__HAVE_68881__) fmove.d %fp0,(%a1) #else move.l %d0,(%a1)+ @@ -130,7 +130,7 @@ retdouble: retlongdouble: btst #4,%d2 jbeq retpointer -#if defined(__MC68881__) +#if defined(__MC68881__) || defined(__HAVE_68881__) fmove.x %fp0,(%a1) #else move.l %d0,(%a1)+ @@ -199,7 +199,7 @@ ffi_closure_SYSV: move.l (%a0),%d1 jra .Lcls_epilogue .Lcls_ret_float: -#if defined(__MC68881__) +#if defined(__MC68881__) || defined(__HAVE_68881__) fmove.s (%a0),%fp0 #else move.l (%a0),%d0 @@ -209,7 +209,7 @@ ffi_closure_SYSV: lsr.l #2,%d0 jne 1f jcs .Lcls_ret_ldouble -#if defined(__MC68881__) +#if defined(__MC68881__) || defined(__HAVE_68881__) fmove.d (%a0),%fp0 #else move.l (%a0)+,%d0 @@ -217,7 +217,7 @@ ffi_closure_SYSV: #endif jra .Lcls_epilogue .Lcls_ret_ldouble: -#if defined(__MC68881__) +#if defined(__MC68881__) || defined(__HAVE_68881__) fmove.x (%a0),%fp0 #else move.l (%a0)+,%d0 diff --git a/libffi/src/mips/n32.S b/libffi/src/mips/n32.S index ae23094667..ff4bbce1de 100644 --- a/libffi/src/mips/n32.S +++ b/libffi/src/mips/n32.S @@ -43,6 +43,7 @@ #ifdef __GNUC__ .abicalls #endif + .set mips4 .text .align 2 .globl ffi_call_N32 diff --git a/libffi/src/powerpc/aix.S b/libffi/src/powerpc/aix.S index c6f87644d9..213f2db39d 100644 --- a/libffi/src/powerpc/aix.S +++ b/libffi/src/powerpc/aix.S @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------- - aix.S - Copyright (c) 2002,2009 Free Software Foundation, Inc. + aix.S - Copyright (c) 2002, 2009 Free Software Foundation, Inc. based on darwin.S by John Hornkvist PowerPC Assembly glue. @@ -79,6 +79,8 @@ .set f20,20 .set f21,21 + .extern .ffi_prep_args + #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> @@ -125,6 +127,7 @@ ffi_call_AIX: /* Call ffi_prep_args. */ mr r4, r1 bl .ffi_prep_args + nop /* Now do the call. */ ld r0, 0(r29) @@ -226,6 +229,7 @@ L(float_return_value): /* Call ffi_prep_args. */ mr r4, r1 bl .ffi_prep_args + nop /* Now do the call. */ lwz r0, 0(r29) diff --git a/libffi/src/powerpc/aix_closure.S b/libffi/src/powerpc/aix_closure.S index 5c74448f2b..aabd3c3c1e 100644 --- a/libffi/src/powerpc/aix_closure.S +++ b/libffi/src/powerpc/aix_closure.S @@ -79,6 +79,8 @@ .set f20,20 .set f21,21 + .extern .ffi_closure_helper_DARWIN + #define LIBFFI_ASM #define JUMPTARGET(name) name #define L(x) x @@ -165,6 +167,7 @@ ffi_closure_ASM: /* look up the proper starting point in table */ /* by using return type as offset */ + lhz r3, 10(r3) /* load type from return type */ ld r4, LC..60(2) /* get address of jump table */ sldi r3, r3, 4 /* now multiply return type by 16 */ ld r0, 240+16(r1) /* load return address */ @@ -337,8 +340,9 @@ L..finish: /* look up the proper starting point in table */ /* by using return type as offset */ + lhz r3, 6(r3) /* load type from return type */ lwz r4, LC..60(2) /* get address of jump table */ - slwi r3, r3, 4 /* now multiply return type by 4 */ + slwi r3, r3, 4 /* now multiply return type by 16 */ lwz r0, 176+8(r1) /* load return address */ add r3, r3, r4 /* add contents of table to table address */ mtctr r3 diff --git a/libffi/src/prep_cif.c b/libffi/src/prep_cif.c index c1c3b9a6c8..e0a0c68cac 100644 --- a/libffi/src/prep_cif.c +++ b/libffi/src/prep_cif.c @@ -93,7 +93,12 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, ffi_type **ptr; FFI_ASSERT(cif != NULL); +#ifndef X86_WIN32 FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); +#else + FFI_ASSERT(abi > FFI_FIRST_ABI && abi <= FFI_DEFAULT_ABI + || abi == FFI_THISCALL); +#endif cif->abi = abi; cif->arg_types = atypes; diff --git a/libffi/src/sparc/v9.S b/libffi/src/sparc/v9.S index 489ff0293f..bf31a2b511 100644 --- a/libffi/src/sparc/v9.S +++ b/libffi/src/sparc/v9.S @@ -32,7 +32,7 @@ /* Only compile this in for 64bit builds, because otherwise the object file will have inproper architecture due to used instructions. */ -#define STACKFRAME 128 /* Minimum stack framesize for SPARC */ +#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */ #define STACK_BIAS 2047 #define ARGS (128) /* Offset of register area in frame */ diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c index fea9d6deaf..469578ea50 100644 --- a/libffi/src/x86/ffi.c +++ b/libffi/src/x86/ffi.c @@ -48,6 +48,13 @@ void ffi_prep_args(char *stack, extended_cif *ecif) register void **p_argv; register char *argp; register ffi_type **p_arg; +#ifdef X86_WIN32 + size_t p_stack_args[2]; + void *p_stack_data[2]; + char *argp2 = stack; + int stack_args_count = 0; + int cabi = ecif->cif->abi; +#endif argp = stack; @@ -59,6 +66,16 @@ void ffi_prep_args(char *stack, extended_cif *ecif) ) { *(void **) argp = ecif->rvalue; +#ifdef X86_WIN32 + /* For fastcall/thiscall this is first register-passed + argument. */ + if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL) + { + p_stack_args[stack_args_count] = sizeof (void*); + p_stack_data[stack_args_count] = argp; + ++stack_args_count; + } +#endif argp += sizeof(void*); } @@ -134,6 +151,24 @@ void ffi_prep_args(char *stack, extended_cif *ecif) { memcpy(argp, *p_argv, z); } + +#ifdef X86_WIN32 + /* For thiscall/fastcall convention register-passed arguments + are the first two none-floating-point arguments with a size + smaller or equal to sizeof (void*). */ + if ((cabi == FFI_THISCALL && stack_args_count < 1) + || (cabi == FFI_FASTCALL && stack_args_count < 2)) + { + if (z <= 4 + && ((*p_arg)->type != FFI_TYPE_FLOAT + && (*p_arg)->type != FFI_TYPE_STRUCT)) + { + p_stack_args[stack_args_count] = z; + p_stack_data[stack_args_count] = argp; + ++stack_args_count; + } + } +#endif p_argv++; #ifdef X86_WIN64 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); @@ -141,7 +176,45 @@ void ffi_prep_args(char *stack, extended_cif *ecif) argp += z; #endif } - + +#ifdef X86_WIN32 + /* We need to move the register-passed arguments for thiscall/fastcall + on top of stack, so that those can be moved to registers ecx/edx by + call-handler. */ + if (stack_args_count > 0) + { + size_t zz = (p_stack_args[0] + 3) & ~3; + char *h; + + /* Move first argument to top-stack position. */ + if (p_stack_data[0] != argp2) + { + h = alloca (zz + 1); + memcpy (h, p_stack_data[0], zz); + memmove (argp2 + zz, argp2, + (size_t) ((char *) p_stack_data[0] - (char*)argp2)); + memcpy (argp2, h, zz); + } + + argp2 += zz; + --stack_args_count; + if (zz > 4) + stack_args_count = 0; + + /* If we have a second argument, then move it on top + after the first one. */ + if (stack_args_count > 0 && p_stack_data[1] != argp2) + { + zz = p_stack_args[1]; + zz = (zz + 3) & ~3; + h = alloca (zz + 1); + h = alloca (zz + 1); + memcpy (h, p_stack_data[1], zz); + memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2)); + memcpy (argp2, h, zz); + } + } +#endif return; } @@ -252,7 +325,7 @@ ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, #elif defined(X86_WIN32) extern void ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); + unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); #else extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); @@ -316,8 +389,37 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) #elif defined(X86_WIN32) case FFI_SYSV: case FFI_STDCALL: - ffi_call_win32(ffi_prep_args, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); + ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, + ecif.rvalue, fn); + break; + case FFI_THISCALL: + case FFI_FASTCALL: + { + unsigned int abi = cif->abi; + unsigned int i, passed_regs = 0; + + if (cif->flags == FFI_TYPE_STRUCT) + ++passed_regs; + + for (i=0; i < cif->nargs && passed_regs < 2;i++) + { + size_t sz; + + if (cif->arg_types[i]->type == FFI_TYPE_FLOAT + || cif->arg_types[i]->type == FFI_TYPE_STRUCT) + continue; + sz = (cif->arg_types[i]->size + 3) & ~3; + if (sz == 0 || sz > 4) + continue; + ++passed_regs; + } + if (passed_regs < 2 && abi == FFI_FASTCALL) + abi = FFI_THISCALL; + if (passed_regs < 1 && abi == FFI_THISCALL) + abi = FFI_STDCALL; + ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags, + ecif.rvalue, fn); + } break; #else case FFI_SYSV: @@ -345,8 +447,12 @@ unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *) void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *) __attribute__ ((regparm(1))); #ifdef X86_WIN32 +void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *) + __attribute__ ((regparm(1))); void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *) __attribute__ ((regparm(1))); +void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *) + __attribute__ ((regparm(1))); #endif #ifdef X86_WIN64 void FFI_HIDDEN ffi_closure_win64 (ffi_closure *); @@ -506,6 +612,33 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ } +#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \ +{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ + unsigned int __fun = (unsigned int)(FUN); \ + unsigned int __ctx = (unsigned int)(CTX); \ + unsigned int __dis = __fun - (__ctx + 49); \ + unsigned short __size = (unsigned short)(SIZE); \ + *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \ + *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \ + *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \ + *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \ + *(unsigned char*) &__tramp[13] = 0xb8; \ + *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \ + *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \ + *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \ + *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \ + *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \ + *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \ + *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \ + *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \ + *(unsigned char*) &__tramp[39] = 0xb8; \ + *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \ + *(unsigned char *) &__tramp[44] = 0xe8; \ + *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \ + *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \ + *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \ + } + #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \ { unsigned char *__tramp = (unsigned char*)(TRAMP); \ unsigned int __fun = (unsigned int)(FUN); \ @@ -548,6 +681,13 @@ ffi_prep_closure_loc (ffi_closure* closure, (void*)codeloc); } #ifdef X86_WIN32 + else if (cif->abi == FFI_THISCALL) + { + FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], + &ffi_closure_THISCALL, + (void*)codeloc, + cif->bytes); + } else if (cif->abi == FFI_STDCALL) { FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], @@ -582,6 +722,9 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, int i; if (cif->abi != FFI_SYSV) { +#ifdef X86_WIN32 + if (cif->abi != FFI_THISCALL) +#endif return FFI_BAD_ABI; } @@ -596,10 +739,20 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE); } - +#ifdef X86_WIN32 + if (cif->abi == FFI_SYSV) + { +#endif FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV, codeloc); - +#ifdef X86_WIN32 + } + else if (cif->abi == FFI_THISCALL) + { + FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, + codeloc, cif->bytes); + } +#endif closure->cif = cif; closure->user_data = user_data; closure->fun = fun; @@ -644,8 +797,37 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) #ifdef X86_WIN32 case FFI_SYSV: case FFI_STDCALL: - ffi_call_win32(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); + ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, + ecif.rvalue, fn); + break; + case FFI_THISCALL: + case FFI_FASTCALL: + { + unsigned int abi = cif->abi; + unsigned int i, passed_regs = 0; + + if (cif->flags == FFI_TYPE_STRUCT) + ++passed_regs; + + for (i=0; i < cif->nargs && passed_regs < 2;i++) + { + size_t sz; + + if (cif->arg_types[i]->type == FFI_TYPE_FLOAT + || cif->arg_types[i]->type == FFI_TYPE_STRUCT) + continue; + sz = (cif->arg_types[i]->size + 3) & ~3; + if (sz == 0 || sz > 4) + continue; + ++passed_regs; + } + if (passed_regs < 2 && abi == FFI_FASTCALL) + cif->abi = abi = FFI_THISCALL; + if (passed_regs < 1 && abi == FFI_THISCALL) + cif->abi = abi = FFI_STDCALL; + ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags, + ecif.rvalue, fn); + } break; #else case FFI_SYSV: diff --git a/libffi/src/x86/ffitarget.h b/libffi/src/x86/ffitarget.h index b85016cc01..dfecd1b3c6 100644 --- a/libffi/src/x86/ffitarget.h +++ b/libffi/src/x86/ffitarget.h @@ -64,6 +64,8 @@ typedef enum ffi_abi { #ifdef X86_WIN32 FFI_SYSV, FFI_STDCALL, + FFI_THISCALL, + FFI_FASTCALL, /* TODO: Add fastcall support for the sake of completeness */ FFI_DEFAULT_ABI = FFI_SYSV, #endif @@ -101,7 +103,7 @@ typedef enum ffi_abi { #define FFI_NATIVE_RAW_API 0 #else #ifdef X86_WIN32 -#define FFI_TRAMPOLINE_SIZE 13 +#define FFI_TRAMPOLINE_SIZE 52 #else #ifdef X86_WIN64 #define FFI_TRAMPOLINE_SIZE 29 diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S index 34ec0fd82b..deb4a0394d 100644 --- a/libffi/src/x86/win32.S +++ b/libffi/src/x86/win32.S @@ -45,6 +45,7 @@ _TEXT SEGMENT ffi_call_win32 PROC NEAR, ffi_prep_args : NEAR PTR DWORD, ecif : NEAR PTR DWORD, + cif_abi : DWORD, cif_bytes : DWORD, cif_flags : DWORD, rvalue : NEAR PTR DWORD, @@ -64,6 +65,19 @@ ffi_call_win32 PROC NEAR, ;; Return stack to previous state and call the function add esp, 8 + ;; Handle thiscall and fastcall + cmp cif_abi, 3 ;; FFI_THISCALL + jz do_thiscall + cmp cif_abi, 4 ;; FFI_FASTCALL + jnz do_stdcall + mov ecx, DWORD PTR [esp] + mov edx, DWORD PTR [esp+4] + add esp, 8 + jmp do_stdcall +do_thiscall: + mov ecx, DWORD PTR [esp] + add esp, 4 +do_stdcall: call fn ;; cdecl: we restore esp in the epilogue, so there's no need to @@ -156,6 +170,16 @@ ca_epilogue: ret ffi_call_win32 ENDP +ffi_closure_THISCALL PROC NEAR FORCEFRAME + push ebp + mov ebp, esp + sub esp, 40 + lea edx, [ebp -24] + mov [ebp - 12], edx /* resp */ + lea edx, [ebp + 12] /* account for stub return address on stack */ + jmp stub +ffi_closure_THISCALL ENDP + ffi_closure_SYSV PROC NEAR FORCEFRAME ;; the ffi_closure ctx is passed in eax by the trampoline. @@ -163,6 +187,7 @@ ffi_closure_SYSV PROC NEAR FORCEFRAME lea edx, [ebp - 24] mov [ebp - 12], edx ;; resp lea edx, [ebp + 8] +stub: mov [esp + 8], edx ;; args lea edx, [ebp - 12] mov [esp + 4], edx ;; &resp @@ -239,6 +264,18 @@ ffi_closure_SYSV ENDP #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) #define CIF_FLAGS_OFFSET 20 +ffi_closure_raw_THISCALL PROC NEAR + push ebp + mov ebp, esp + push esi + sub esp, 36 + mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif + mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data + mov [esp + 12], edx + lea edx, [ebp + 12], edx + jmp stubraw +ffi_closure_raw_SYSV ENDP + ffi_closure_raw_SYSV PROC NEAR USES esi ;; the ffi_closure ctx is passed in eax by the trampoline. @@ -247,6 +284,7 @@ ffi_closure_raw_SYSV PROC NEAR USES esi mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data mov [esp + 12], edx ;; user_data lea edx, [ebp + 8] +stubraw: mov [esp + 8], edx ;; raw_args lea edx, [ebp - 24] mov [esp + 4], edx ;; &res @@ -405,7 +443,7 @@ _ffi_call_win32: movl %esp,%ebp .LCFI1: # Make room for all of the new args. - movl 16(%ebp),%ecx + movl 20(%ebp),%ecx subl %ecx,%esp movl %esp,%eax @@ -417,19 +455,34 @@ _ffi_call_win32: # Return stack to previous state and call the function addl $8,%esp - + + # Handle fastcall and thiscall + cmpl $3, 16(%ebp) # FFI_THISCALL + jz .do_thiscall + cmpl $4, 16(%ebp) # FFI_FASTCALL + jnz .do_fncall + movl (%esp), %ecx + movl 4(%esp), %edx + addl $8, %esp + jmp .do_fncall +.do_thiscall: + movl (%esp), %ecx + addl $4, %esp + +.do_fncall: + # FIXME: Align the stack to a 128-bit boundary to avoid # potential performance hits. - call *28(%ebp) + call *32(%ebp) # stdcall functions pop arguments off the stack themselves # Load %ecx with the return type code - movl 20(%ebp),%ecx + movl 24(%ebp),%ecx # If the return value pointer is NULL, assume no return value. - cmpl $0,24(%ebp) + cmpl $0,28(%ebp) jne 0f # Even if there is no space for the return value, we are @@ -488,50 +541,50 @@ _ffi_call_win32: .Lretint: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movl %eax,0(%ecx) jmp .Lepilogue .Lretfloat: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx fstps (%ecx) jmp .Lepilogue .Lretdouble: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx fstpl (%ecx) jmp .Lepilogue .Lretlongdouble: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx fstpt (%ecx) jmp .Lepilogue .Lretint64: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movl %eax,0(%ecx) movl %edx,4(%ecx) jmp .Lepilogue .Lretstruct1b: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movb %al,0(%ecx) jmp .Lepilogue .Lretstruct2b: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movw %ax,0(%ecx) jmp .Lepilogue .Lretstruct4b: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movl %eax,0(%ecx) jmp .Lepilogue @@ -544,6 +597,19 @@ _ffi_call_win32: popl %ebp ret .ffi_call_win32_end: + .balign 16 + .globl _ffi_closure_THISCALL +#ifndef __OS2__ + .def _ffi_closure_THISCALL; .scl 2; .type 32; .endef +#endif +_ffi_closure_THISCALL: + pushl %ebp + movl %esp, %ebp + subl $40, %esp + leal -24(%ebp), %edx + movl %edx, -12(%ebp) /* resp */ + leal 12(%ebp), %edx /* account for stub return address on stack */ + jmp .stub .LFE1: # This assumes we are using gas. @@ -562,6 +628,7 @@ _ffi_closure_SYSV: leal -24(%ebp), %edx movl %edx, -12(%ebp) /* resp */ leal 8(%ebp), %edx +.stub: movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ leal -12(%ebp), %edx movl %edx, (%esp) /* &resp */ @@ -668,7 +735,21 @@ _ffi_closure_SYSV: #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) #define CIF_FLAGS_OFFSET 20 - + .balign 16 + .globl _ffi_closure_raw_THISCALL +#ifndef __OS2__ + .def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef +#endif +_ffi_closure_raw_THISCALL: + pushl %ebp + movl %esp, %ebp + pushl %esi + subl $36, %esp + movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ + movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ + movl %edx, 12(%esp) /* user_data */ + leal 12(%ebp), %edx /* __builtin_dwarf_cfa () */ + jmp .stubraw # This assumes we are using gas. .balign 16 .globl _ffi_closure_raw_SYSV @@ -688,6 +769,7 @@ _ffi_closure_raw_SYSV: movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ movl %edx, 12(%esp) /* user_data */ leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ +.stubraw: movl %edx, 8(%esp) /* raw_args */ leal -24(%ebp), %edx movl %edx, 4(%esp) /* &res */ diff --git a/libffi/testsuite/Makefile.in b/libffi/testsuite/Makefile.in index fae969b85f..ea0bdcd646 100644 --- a/libffi/testsuite/Makefile.in +++ b/libffi/testsuite/Makefile.in @@ -35,9 +35,10 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = testsuite -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/../config/asmcfi.m4 \ + $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/lead-dot.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/override.m4 \ @@ -52,10 +53,8 @@ CONFIG_HEADER = $(top_builddir)/fficonfig.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = -DIST_SOURCES = DEJATOOL = $(PACKAGE) RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ @@ -278,37 +277,6 @@ distclean-DEJAGNU: -l='$(DEJATOOL)'; for tool in $$l; do \ rm -f $$tool.sum $$tool.log; \ done - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU check: check-am @@ -410,8 +378,8 @@ uninstall-am: .PHONY: all all-am check check-DEJAGNU check-am clean clean-generic \ clean-libtool distclean distclean-DEJAGNU distclean-generic \ - distclean-libtool distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ + distclean-libtool dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ diff --git a/libffi/testsuite/libffi.call/closure_thiscall.c b/libffi/testsuite/libffi.call/closure_thiscall.c new file mode 100644 index 0000000000..6c46f35372 --- /dev/null +++ b/libffi/testsuite/libffi.call/closure_thiscall.c @@ -0,0 +1,64 @@ +/* Area: closure_call (thiscall convention) + Purpose: Check handling when caller expects thiscall callee + Limitations: none. + PR: none. + Originator: <ktietz@redhat.com> */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ +#include "ffitest.h" + +static void +closure_test_thiscall(ffi_cif* cif __UNUSED__, void* resp, void** args, + void* userdata) +{ + *(ffi_arg*)resp = + (int)*(int *)args[0] + (int)(*(int *)args[1]) + + (int)(*(int *)args[2]) + (int)(*(int *)args[3]) + + (int)(intptr_t)userdata; + + printf("%d %d %d %d: %d\n", + (int)*(int *)args[0], (int)(*(int *)args[1]), + (int)(*(int *)args[2]), (int)(*(int *)args[3]), + (int)*(ffi_arg *)resp); + +} + +typedef int (__thiscall *closure_test_type0)(int, int, int, int); + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + ffi_type * cl_arg_types[17]; + int res; + void* sp_pre; + void* sp_post; + char buf[1024]; + + cl_arg_types[0] = &ffi_type_uint; + cl_arg_types[1] = &ffi_type_uint; + cl_arg_types[2] = &ffi_type_uint; + cl_arg_types[3] = &ffi_type_uint; + cl_arg_types[4] = NULL; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_THISCALL, 4, + &ffi_type_sint, cl_arg_types) == FFI_OK); + + CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_thiscall, + (void *) 3 /* userdata */, code) == FFI_OK); + + asm volatile (" movl %%esp,%0" : "=g" (sp_pre)); + res = (*(closure_test_type0)code)(0, 1, 2, 3); + asm volatile (" movl %%esp,%0" : "=g" (sp_post)); + /* { dg-output "0 1 2 3: 9" } */ + + printf("res: %d\n",res); + /* { dg-output "\nres: 9" } */ + + sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post); + printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf)); + /* { dg-output "\nstack pointer match" } */ + exit(0); +} diff --git a/libffi/testsuite/libffi.call/fastthis1_win32.c b/libffi/testsuite/libffi.call/fastthis1_win32.c new file mode 100644 index 0000000000..b3c4c733b6 --- /dev/null +++ b/libffi/testsuite/libffi.call/fastthis1_win32.c @@ -0,0 +1,50 @@ +/* Area: ffi_call + Purpose: Check fastcall fct call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" + +static size_t __attribute__((fastcall)) my_fastcall_f(char *s, float a) +{ + return (size_t) ((int) strlen(s) + (int) a); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + char *s; + float v2; + args[0] = &ffi_type_pointer; + args[1] = &ffi_type_float; + values[0] = (void*) &s; + values[1] = (void*) &v2; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 2, + &ffi_type_sint, args) == FFI_OK); + + s = "a"; + v2 = 0.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 1); + + s = "1234567"; + v2 = -1.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 6); + + s = "1234567890123456789012345"; + v2 = 1.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 26); + + printf("fastcall fct1 tests passed\n"); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/fastthis2_win32.c b/libffi/testsuite/libffi.call/fastthis2_win32.c new file mode 100644 index 0000000000..f148a12fa6 --- /dev/null +++ b/libffi/testsuite/libffi.call/fastthis2_win32.c @@ -0,0 +1,50 @@ +/* Area: ffi_call + Purpose: Check fastcall fct call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" + +static size_t __attribute__((fastcall)) my_fastcall_f(float a, char *s) +{ + return (size_t) ((int) strlen(s) + (int) a); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + char *s; + float v2; + args[1] = &ffi_type_pointer; + args[0] = &ffi_type_float; + values[1] = (void*) &s; + values[0] = (void*) &v2; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 2, + &ffi_type_sint, args) == FFI_OK); + + s = "a"; + v2 = 0.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 1); + + s = "1234567"; + v2 = -1.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 6); + + s = "1234567890123456789012345"; + v2 = 1.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 26); + + printf("fastcall fct2 tests passed\n"); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/fastthis3_win32.c b/libffi/testsuite/libffi.call/fastthis3_win32.c new file mode 100644 index 0000000000..5cf82bbfa9 --- /dev/null +++ b/libffi/testsuite/libffi.call/fastthis3_win32.c @@ -0,0 +1,56 @@ +/* Area: ffi_call + Purpose: Check fastcall f call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" + +static size_t __attribute__((fastcall)) my_fastcall_f(float a, char *s, int i) +{ + return (size_t) ((int) strlen(s) + (int) a + i); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + char *s; + int v1; + float v2; + args[2] = &ffi_type_sint; + args[1] = &ffi_type_pointer; + args[0] = &ffi_type_float; + values[2] = (void*) &v1; + values[1] = (void*) &s; + values[0] = (void*) &v2; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 3, + &ffi_type_sint, args) == FFI_OK); + + s = "a"; + v1 = 1; + v2 = 0.0; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 2); + + s = "1234567"; + v2 = -1.0; + v1 = -2; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 4); + + s = "1234567890123456789012345"; + v2 = 1.0; + v1 = 2; + ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values); + CHECK(rint == 28); + + printf("fastcall fct3 tests passed\n"); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/ffitest.h b/libffi/testsuite/libffi.call/ffitest.h index 59ef032ea5..0e95e164f6 100644 --- a/libffi/testsuite/libffi.call/ffitest.h +++ b/libffi/testsuite/libffi.call/ffitest.h @@ -67,6 +67,8 @@ #define PRIdLL "ld" #undef PRIuLL #define PRIuLL "lu" +#define PRId8 "hd" +#define PRIu8 "hu" #define PRId64 "ld" #define PRIu64 "lu" #define PRIuPTR "lu" @@ -81,6 +83,8 @@ #if defined(__sgi) /* IRIX 6.5 <inttypes.h> provides all definitions, but only for C99 compilations. */ +#define PRId8 "hhd" +#define PRIu8 "hhu" #if (_MIPS_SZLONG == 32) #define PRId64 "lld" #define PRIu64 "llu" diff --git a/libffi/testsuite/libffi.call/huge_struct.c b/libffi/testsuite/libffi.call/huge_struct.c index 602437ade5..e04e1d58a4 100644 --- a/libffi/testsuite/libffi.call/huge_struct.c +++ b/libffi/testsuite/libffi.call/huge_struct.c @@ -129,14 +129,14 @@ test_large_fn( ui64_4 + 4, si64_4 + 4, f_4 + 4, d_4 + 4, ld_4 + 4, (char*)((intptr_t)p_4 + 4), ui8_5 + 5, si8_5 + 5}; - printf("%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %hhu %hhd: " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %hhu %hhd\n", + printf("%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 ": " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n", ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, (unsigned long)p_1, ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, (unsigned long)p_2, ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, (unsigned long)p_3, @@ -296,10 +296,10 @@ main(int argc __UNUSED__, const char** argv __UNUSED__) ffi_call(&cif, FFI_FN(test_large_fn), &retVal, argValues); // { dg-output "1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } - printf("res: %hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %hhu %hhd\n", + printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n", retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f, retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l, retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r, @@ -324,10 +324,10 @@ main(int argc __UNUSED__, const char** argv __UNUSED__) ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p, ui8, si8); // { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } - printf("res: %hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " - "%hhu %hhd %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %hhu %hhd\n", + printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx " + "%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n", retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f, retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l, retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r, diff --git a/libffi/testsuite/libffi.call/many2_win32.c b/libffi/testsuite/libffi.call/many2_win32.c new file mode 100644 index 0000000000..4adbe4d705 --- /dev/null +++ b/libffi/testsuite/libffi.call/many2_win32.c @@ -0,0 +1,63 @@ +/* Area: ffi_call + Purpose: Check stdcall many call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" +#include <float.h> + +static float __attribute__((fastcall)) fastcall_many(float f1, + float f2, + float f3, + float f4, + float f5, + float f6, + float f7, + float f8, + float f9, + float f10, + float f11, + float f12, + float f13) +{ + return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[13]; + void *values[13]; + float fa[13]; + float f, ff; + unsigned long ul; + + for (ul = 0; ul < 13; ul++) + { + args[ul] = &ffi_type_float; + values[ul] = &fa[ul]; + fa[ul] = (float) ul; + } + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 13, + &ffi_type_float, args) == FFI_OK); + + ff = fastcall_many(fa[0], fa[1], + fa[2], fa[3], + fa[4], fa[5], + fa[6], fa[7], + fa[8], fa[9], + fa[10], fa[11], fa[12]); + + ffi_call(&cif, FFI_FN(fastcall_many), &f, values); + + if (f - ff < FLT_EPSILON) + printf("fastcall many arg tests ok!\n"); + else + CHECK(0); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/strlen2_win32.c b/libffi/testsuite/libffi.call/strlen2_win32.c new file mode 100644 index 0000000000..b348e43409 --- /dev/null +++ b/libffi/testsuite/libffi.call/strlen2_win32.c @@ -0,0 +1,45 @@ +/* Area: ffi_call + Purpose: Check fastcall strlen call on X86_WIN32 systems. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ + +#include "ffitest.h" + +static size_t __attribute__((fastcall)) my_fastcall_strlen(char *s) +{ + return (strlen(s)); +} + +int d +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + char *s; + args[0] = &ffi_type_pointer; + values[0] = (void*) &s; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, + &ffi_type_sint, args) == FFI_OK); + + s = "a"; + ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values); + CHECK(rint == 1); + + s = "1234567"; + ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values); + CHECK(rint == 7); + + s = "1234567890123456789012345"; + ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values); + CHECK(rint == 25); + + printf("fastcall strlen tests passed\n"); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/struct1_win32.c b/libffi/testsuite/libffi.call/struct1_win32.c new file mode 100644 index 0000000000..4a7eb9444b --- /dev/null +++ b/libffi/testsuite/libffi.call/struct1_win32.c @@ -0,0 +1,65 @@ +/* Area: ffi_call + Purpose: Check structures with fastcall/thiscall convention. + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ +#include "ffitest.h" + +typedef struct +{ + unsigned char uc; + double d; + unsigned int ui; +} test_structure_1; + +static __attribute__ ((fastcall)) test_structure_1 struct1(test_structure_1 ts) +{ + ts.uc++; + ts.d--; + ts.ui++; + + return ts; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_type ts1_type; + ffi_type *ts1_type_elements[4]; + ts1_type.size = 0; + ts1_type.alignment = 0; + ts1_type.type = FFI_TYPE_STRUCT; + ts1_type.elements = ts1_type_elements; + ts1_type_elements[0] = &ffi_type_uchar; + ts1_type_elements[1] = &ffi_type_double; + ts1_type_elements[2] = &ffi_type_uint; + ts1_type_elements[3] = NULL; + + test_structure_1 ts1_arg; + /* This is a hack to get a properly aligned result buffer */ + test_structure_1 *ts1_result = + (test_structure_1 *) malloc (sizeof(test_structure_1)); + + args[0] = &ts1_type; + values[0] = &ts1_arg; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, + &ts1_type, args) == FFI_OK); + + ts1_arg.uc = '\x01'; + ts1_arg.d = 3.14159; + ts1_arg.ui = 555; + + ffi_call(&cif, FFI_FN(struct1), ts1_result, values); + + CHECK(ts1_result->ui == 556); + CHECK(ts1_result->d == 3.14159 - 1); + + free (ts1_result); + exit(0); +} diff --git a/libffi/testsuite/libffi.call/struct2_win32.c b/libffi/testsuite/libffi.call/struct2_win32.c new file mode 100644 index 0000000000..2bfbdc5ff8 --- /dev/null +++ b/libffi/testsuite/libffi.call/struct2_win32.c @@ -0,0 +1,67 @@ +/* Area: ffi_call + Purpose: Check structures in fastcall/stdcall function + Limitations: none. + PR: none. + Originator: From the original ffitest.c */ + +/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ +#include "ffitest.h" + +typedef struct +{ + double d1; + double d2; +} test_structure_2; + +static test_structure_2 __attribute__ ((fastcall)) struct2(test_structure_2 ts) +{ + ts.d1--; + ts.d2--; + + return ts; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + test_structure_2 ts2_arg; + ffi_type ts2_type; + ffi_type *ts2_type_elements[3]; + ts2_type.size = 0; + ts2_type.alignment = 0; + ts2_type.type = FFI_TYPE_STRUCT; + ts2_type.elements = ts2_type_elements; + ts2_type_elements[0] = &ffi_type_double; + ts2_type_elements[1] = &ffi_type_double; + ts2_type_elements[2] = NULL; + + + /* This is a hack to get a properly aligned result buffer */ + test_structure_2 *ts2_result = + (test_structure_2 *) malloc (sizeof(test_structure_2)); + + args[0] = &ts2_type; + values[0] = &ts2_arg; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 1, &ts2_type, args) == FFI_OK); + + ts2_arg.d1 = 5.55; + ts2_arg.d2 = 6.66; + + printf ("%g\n", ts2_arg.d1); + printf ("%g\n", ts2_arg.d2); + + ffi_call(&cif, FFI_FN(struct2), ts2_result, values); + + printf ("%g\n", ts2_result->d1); + printf ("%g\n", ts2_result->d2); + + CHECK(ts2_result->d1 == 5.55 - 1); + CHECK(ts2_result->d2 == 6.66 - 1); + + free (ts2_result); + exit(0); +} |