diff options
171 files changed, 5182 insertions, 2679 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 80dfb63004b..36979e13785 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -540,7 +540,7 @@ Gabriele Svelto gabriele.svelto@st.com Sriraman Tallam tmsriram@google.com Chung-Lin Tang cltang@codesourcery.com Samuel Tardieu sam@rfc1149.net -Dinar Temirbulatov dinar@kugelworks.com +Dinar Temirbulatov dtemirbulatov@gmail.com Kresten Krab Thorup krab@gcc.gnu.org Caroline Tice cmtice@google.com Kyrylo Tkachov kyrylo.tkachov@arm.com diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog index 6f124526e3d..1b5c92d878b 100644 --- a/boehm-gc/ChangeLog +++ b/boehm-gc/ChangeLog @@ -1,3 +1,13 @@ +2014-04-22 Jakub Jelinek <jakub@redhat.com> + + PR other/43620 + * Makefile.am (AUTOMAKE_OPTIONS): Add no-dist. + * include/Makefile.am (AUTOMAKE_OPTIONS): Likewise. + * testsuite/Makefile.am (AUTOMAKE_OPTIONS): Likewise. + * Makefile.in: Regenerated. + * include/Makefile.in: Regenerated. + * testsuite/Makefile.in: Regenerated. + 2013-12-21 Andreas Tobler <andreast@gcc.gnu.org> * include/private/gcconfig.h: Add FreeBSD powerpc64 defines. diff --git a/boehm-gc/Makefile.am b/boehm-gc/Makefile.am index 468e6ffc9b4..fa187ef31ee 100644 --- a/boehm-gc/Makefile.am +++ b/boehm-gc/Makefile.am @@ -4,7 +4,7 @@ ## files that should be in the distribution are not mentioned in this ## Makefile.am. -AUTOMAKE_OPTIONS = foreign subdir-objects +AUTOMAKE_OPTIONS = foreign subdir-objects no-dist ACLOCAL_AMFLAGS = -I .. -I ../config SUBDIRS = include testsuite diff --git a/boehm-gc/Makefile.in b/boehm-gc/Makefile.in index cd588103659..5fc84910128 100644 --- a/boehm-gc/Makefile.in +++ b/boehm-gc/Makefile.in @@ -36,13 +36,10 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = . -DIST_COMMON = $(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)/threads.mk.in \ - $(top_srcdir)/configure ChangeLog depcomp +DIST_COMMON = ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/configure $(am__configure_deps) \ + $(srcdir)/../mkinstalldirs $(srcdir)/threads.mk.in \ + $(srcdir)/../depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ @@ -63,14 +60,6 @@ CONFIG_CLEAN_FILES = threads.mk CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = -am__libgcjgc_la_SOURCES_DIST = allchblk.c alloc.c blacklst.c \ - checksums.c dbg_mlc.c dyn_load.c finalize.c gc_dlopen.c \ - gcj_mlc.c headers.c malloc.c mallocx.c mark.c mark_rts.c \ - misc.c new_hblk.c obj_map.c os_dep.c pcr_interface.c \ - ptr_chck.c real_malloc.c reclaim.c specific.c stubborn.c \ - typd_mlc.c backgraph.c win32_threads.c pthread_support.c \ - pthread_stop_world.c darwin_stop_world.c \ - powerpc_darwin_mach_dep.s @POWERPC_DARWIN_TRUE@am__objects_1 = powerpc_darwin_mach_dep.lo am_libgcjgc_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo checksums.lo \ dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \ @@ -80,14 +69,6 @@ am_libgcjgc_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo checksums.lo \ backgraph.lo win32_threads.lo pthread_support.lo \ pthread_stop_world.lo darwin_stop_world.lo $(am__objects_1) libgcjgc_la_OBJECTS = $(am_libgcjgc_la_OBJECTS) -am__libgcjgc_convenience_la_SOURCES_DIST = allchblk.c alloc.c \ - blacklst.c checksums.c dbg_mlc.c dyn_load.c finalize.c \ - gc_dlopen.c gcj_mlc.c headers.c malloc.c mallocx.c mark.c \ - mark_rts.c misc.c new_hblk.c obj_map.c os_dep.c \ - pcr_interface.c ptr_chck.c real_malloc.c reclaim.c specific.c \ - stubborn.c typd_mlc.c backgraph.c win32_threads.c \ - pthread_support.c pthread_stop_world.c darwin_stop_world.c \ - powerpc_darwin_mach_dep.s am__objects_2 = allchblk.lo alloc.lo blacklst.lo checksums.lo \ dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \ headers.lo malloc.lo mallocx.lo mark.lo mark_rts.lo misc.lo \ @@ -115,8 +96,6 @@ CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) LTCCASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) SOURCES = $(libgcjgc_la_SOURCES) $(libgcjgc_convenience_la_SOURCES) -DIST_SOURCES = $(am__libgcjgc_la_SOURCES_DIST) \ - $(am__libgcjgc_convenience_la_SOURCES_DIST) MULTISRCTOP = MULTIBUILDTOP = MULTIDIRS = @@ -133,47 +112,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@ AMTAR = @AMTAR@ AM_CPPFLAGS = @AM_CPPFLAGS@ @@ -314,7 +256,7 @@ toolexeclibdir = @toolexeclibdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = foreign subdir-objects +AUTOMAKE_OPTIONS = foreign subdir-objects no-dist ACLOCAL_AMFLAGS = -I .. -I ../config SUBDIRS = include testsuite noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la @@ -672,182 +614,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 @@ -960,21 +726,19 @@ uninstall-am: .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am all-multi am--refresh check check-am clean \ clean-generic clean-libtool clean-multi \ - clean-noinstLTLIBRARIES 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-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 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 uninstall uninstall-am + clean-noinstLTLIBRARIES ctags ctags-recursive distclean \ + distclean-compile distclean-generic 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 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 \ + uninstall uninstall-am override CFLAGS := $(filter-out $(O0_CFLAGS), $(CFLAGS)) $(O0_CFLAGS) diff --git a/boehm-gc/include/Makefile.am b/boehm-gc/include/Makefile.am index 381ae76b8fe..63aec076056 100644 --- a/boehm-gc/include/Makefile.am +++ b/boehm-gc/include/Makefile.am @@ -1,4 +1,4 @@ -AUTOMAKE_OPTIONS = foreign +AUTOMAKE_OPTIONS = foreign no-dist noinst_HEADERS = gc.h gc_backptr.h gc_local_alloc.h \ gc_pthread_redirects.h gc_cpp.h diff --git a/boehm-gc/include/Makefile.in b/boehm-gc/include/Makefile.in index db67a999adf..8287ef6b1d9 100644 --- a/boehm-gc/include/Makefile.in +++ b/boehm-gc/include/Makefile.in @@ -36,9 +36,9 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = include -DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/gc_config.h.in \ - $(srcdir)/gc_ext_config.h.in +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/gc_config.h.in $(srcdir)/gc_ext_config.h.in \ + $(noinst_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ @@ -55,11 +55,9 @@ CONFIG_HEADER = gc_config.h gc_ext_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = -DIST_SOURCES = HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CPPFLAGS = @AM_CPPFLAGS@ @@ -200,7 +198,7 @@ toolexeclibdir = @toolexeclibdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = foreign +AUTOMAKE_OPTIONS = foreign no-dist noinst_HEADERS = gc.h gc_backptr.h gc_local_alloc.h \ gc_pthread_redirects.h gc_cpp.h @@ -323,37 +321,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) gc_config.h gc_ext_config.h @@ -453,16 +420,15 @@ uninstall-am: .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool ctags distclean distclean-generic distclean-hdr \ - 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 installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ - uninstall-am + 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 installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/boehm-gc/testsuite/Makefile.am b/boehm-gc/testsuite/Makefile.am index 98010bd1f69..f1eac3b1666 100644 --- a/boehm-gc/testsuite/Makefile.am +++ b/boehm-gc/testsuite/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -AUTOMAKE_OPTIONS = foreign dejagnu +AUTOMAKE_OPTIONS = foreign dejagnu no-dist EXPECT = expect diff --git a/boehm-gc/testsuite/Makefile.in b/boehm-gc/testsuite/Makefile.in index b12a5c51558..dbb2ff604e0 100644 --- a/boehm-gc/testsuite/Makefile.in +++ b/boehm-gc/testsuite/Makefile.in @@ -35,7 +35,7 @@ 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/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ @@ -53,10 +53,8 @@ CONFIG_HEADER = $(top_builddir)/include/gc_config.h \ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = -DIST_SOURCES = RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir RUNTEST = runtest -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CPPFLAGS = @AM_CPPFLAGS@ @@ -197,7 +195,7 @@ toolexeclibdir = @toolexeclibdir@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -AUTOMAKE_OPTIONS = foreign dejagnu +AUTOMAKE_OPTIONS = foreign dejagnu no-dist EXPECT = expect # Override default. @@ -267,37 +265,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 @@ -399,8 +366,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/config/ChangeLog b/config/ChangeLog index 7d000625c76..f4152c4ebff 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,3 +1,8 @@ +2014-04-25 Marc Glisse <marc.glisse@inria.fr> + + PR target/43538 + * mt-gnu: Don't reset CXXFLAGS_FOR_TARGET. + 2013-11-29 Marek Polacek <polacek@redhat.com> * bootstrap-ubsan.mk (POSTSTAGE1_LDFLAGS): Remove -lpthread -ldl. diff --git a/config/mt-gnu b/config/mt-gnu index 15bf4171603..5c696f51b0b 100644 --- a/config/mt-gnu +++ b/config/mt-gnu @@ -1 +1 @@ -CXXFLAGS_FOR_TARGET = $(CXXFLAGS) -D_GNU_SOURCE +CXXFLAGS_FOR_TARGET += -D_GNU_SOURCE diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a29383083b3..67a4645a87a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,376 @@ +2014-04-28 Richard Biener <rguenther@suse.de> + + * tree-vrp.c (vrp_var_may_overflow): Remove. + (vrp_visit_phi_node): Rather than bumping to +-INF possibly + with overflow immediately bump to one before that value and + let iteration figure out overflow status. + +2014-04-28 Richard Biener <rguenther@suse.de> + + * configure.ac: Do valgrind header checks unconditionally. + Add --enable-valgrind-annotations. + * system.h: Guard valgrind header inclusion with + ENABLE_VALGRIND_ANNOTATIONS instead of ENABLE_VALGRIND_CHECKING. + * alloc-pool.c (pool_alloc, pool_free): Use + ENABLE_VALGRIND_ANNOTATIONS instead of ENABLE_VALGRIND_CHECKING + to guard possibly dead code. + * config.in: Regenerated. + * configure: Likewise. + +2014-04-28 Jeff Law <law@redhat.com> + + PR tree-optimization/60902 + * tree-ssa-threadedge.c + (record_temporary_equivalences_from_stmts_at_dest): Only iterate + over real defs when invalidating outputs from statements that do not + produce useful outputs for threading. + +2014-04-28 Richard Biener <rguenther@suse.de> + + PR tree-optimization/60979 + * graphite-scop-detection.c (scopdet_basic_block_info): Reject + SCOPs that end in a block with a successor with abnormal + predecessors. + +2014-04-28 Richard Biener <rguenther@suse.de> + + * tree-pass.h (execute_pass_list): Adjust prototype. + * passes.c (pass_manager::execute_early_local_passes): + Adjust. + (do_per_function): Change callback signature, push all actual + work to the callbals. + (do_per_function_toporder): Likewise. + (execute_function_dump): Adjust. + (execute_function_todo): Likewise. + (clear_last_verified): Likewise. + (verify_curr_properties): Likewise. + (update_properties_after_pass): Likewise. + (execute_pass_list_1): Split out from ... + (execute_pass_list): ... here. Adjust. + (execute_ipa_pass_list): Likewise. + * cgraphunit.c (cgraph_add_new_function): Adjust. + (analyze_function): Likewise. + (expand_function): Likewise. + * cgraph.c (release_function_body): Free dominance info + here instead of asserting it was magically freed elsewhere. + +2014-04-28 Eric Botcazou <ebotcazou@adacore.com> + + * configure.ac: Tweak GAS check for LEON instructions on SPARC. + * configure: Regenerate. + * config/sparc/sparc.opt (muser-mode): New option. + * config/sparc/sync.md (atomic_compare_and_swap<mode>_1): Do not enable + for LEON3. + (atomic_compare_and_swap_leon3_1): New instruction for LEON3. + * doc/invoke.texi (SPARC options): Document -muser-mode. + +2014-04-27 Richard Sandiford <rdsandiford@googlemail.com> + + * cselib.c (find_slot_memmode): Delete. + (cselib_hasher): Change compare_type to a struct. + (cselib_hasher::equal): Update accordingly. Don't expect wrapped + constants. + (preserve_constants_and_equivs): Adjust for new compare_type. + (cselib_find_slot): Likewise. Take the mode of the rtx as argument. + (wrap_constant): Delete. + (cselib_lookup_mem, cselib_lookup_1): Update calls to cselib_find_slot. + +2014-04-26 Markus Trippelsdorf <markus@trippelsdorf.de> + + * doc/install.texi (Building with profile feedback): Remove + outdated sentence. + +2014-04-26 Tom de Vries <tom@codesourcery.com> + + * config/i386/i386.md (define_expand "ldexpxf3"): Fix out-of-bounds + array accesses. + +2014-04-25 Cary Coutant <ccoutant@google.com> + + PR debug/60929 + * dwarf2out.c (should_move_die_to_comdat): A type definition + can contain a subprogram definition, but don't move it to a + comdat unit. + (clone_as_declaration): Copy DW_AT_abstract_origin attribute. + (generate_skeleton_bottom_up): Remove DW_AT_object_pointer attribute + from original DIE. + (clone_tree_hash): Rename to... + (clone_tree_partial): ...this; change callers. Copy + DW_TAG_subprogram DIEs as declarations. + (copy_decls_walk): Don't copy children of a declaration into a + type unit. + +2014-04-25 H.J. Lu <hongjiu.lu@intel.com> + + PR target/60969 + * config/i386/i386.md (*movsf_internal): Set MODE to SI for + alternative 12. + +2014-04-25 Jiong Wang <jiong.wang@arm.com> + + * config/arm/predicates.md (call_insn_operand): Add long_call check. + * config/arm/arm.md (sibcall, sibcall_value): Force the address to + reg for long_call. + * config/arm/arm.c (arm_function_ok_for_sibcall): Remove long_call + restriction. + +2014-04-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm.c (arm_cortex_a8_tune): Initialise + T16-related fields. + +2014-04-25 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + PR tree-optimization/60930 + * gimple-ssa-strength-reduction.c (create_mul_imm_cand): Reject + creating a multiply candidate by folding two constant + multiplicands when the result overflows. + +2014-04-25 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/60960 + * tree-vect-generic.c (expand_vector_operation): Only call + expand_vector_divmod if type's mode satisfies VECTOR_MODE_P. + +2014-04-25 Tom de Vries <tom@codesourcery.com> + + * expr.c (clobber_reg_mode): New function. + * expr.h (clobber_reg): New function. + +2014-04-25 Tom de Vries <tom@codesourcery.com> + + * rtlanal.c (find_all_hard_reg_sets): Note INSN_CALL_FUNCTION_USAGE + clobbers. + +2014-04-25 Radovan Obradovic <robradovic@mips.com> + Tom de Vries <tom@codesourcery.com> + + * rtlanal.c (find_all_hard_reg_sets): Add bool implicit parameter and + handle. + * rtl.h (find_all_hard_reg_sets): Add bool parameter. + * haifa-sched.c (recompute_todo_spec, check_clobbered_conditions): Add + new argument to find_all_hard_reg_sets call. + +2014-04-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/aarch-common.c (aarch_rev16_shright_mask_imm_p): + Use HOST_WIDE_INT_C for mask literal. + (aarch_rev16_shleft_mask_imm_p): Likewise. + +2014-04-25 Eric Botcazou <ebotcazou@adacore.com> + + PR target/60941 + * config/sparc/sparc.md (ashlsi3_extend): Delete. + +2014-04-25 Marc Glisse <marc.glisse@inria.fr> + + PR preprocessor/56540 + * config/i386/i386-c.c (ix86_target_macros): Define + __SIZEOF_FLOAT80__ and __SIZEOF_FLOAT128__. + +2014-04-25 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac (tga_func): Remove. + (LIB_TLS_SPEC): Remove. + * configure: Regenerate. + * config.in: Regenerate. + * config/sol2.h (LIB_SPEC): Don't use LIB_TLS_SPEC. + +2014-04-25 Richard Biener <rguenther@suse.de> + + PR ipa/60912 + * tree-ssa-structalias.c (ipa_pta_execute): Compute direct + call stmt use/clobber sets during stmt walk instead of + walking the possibly incomplete set of caller edges. + +2014-04-25 Richard Biener <rguenther@suse.de> + + PR ipa/60911 + * passes.c (apply_ipa_transforms): Inline into only caller ... + (execute_one_pass): ... here. Properly bring in function + bodies for nodes we want to apply IPA transforms to. + +2014-04-24 Cong Hou <congh@google.com> + + PR tree-optimization/60896 + * tree-vect-patterns.c (vect_recog_dot_prod_pattern): Pick up + all statements in PATTERN_DEF_SEQ in recognized widen-mult pattern. + (vect_mark_pattern_stmts): Set the def type of all statements in + PATTERN_DEF_SEQ as vect_internal_def. + +2014-04-24 Michael Meissner <meissner@linux.vnet.ibm.com> + + * doc/extend.texi (PowerPC Built-in Functions): Document new + powerpc extended divide, bcd, pack/unpack 128-bit, builtin + functions. + (PowerPC AltiVec/VSX Built-in Functions): Likewise. + + * config/rs6000/predicates.md (const_0_to_3_operand): New + predicate to match 0..3 integer constants. + + * config/rs6000/rs6000-builtin.def (BU_DFP_MISC_1): Add new macros + to support adding miscellaneous builtin functions. + (BU_DFP_MISC_2): Likewise. + (BU_P7_MISC_1): Likewise. + (BU_P7_MISC_2): Likewise. + (BU_P8V_MISC_3): Likewise. + (BU_MISC_1): Likewise. + (BU_MISC_2): Likewise. + (DIVWE): Add extended divide builtin functions. + (DIVWEO): Likewise. + (DIVWEU): Likewise. + (DIVWEUO): Likewise. + (DIVDE): Likewise. + (DIVDEO): Likewise. + (DIVDEU): Likewise. + (DIVDEUO): Likewise. + (DXEX): Add decimal floating-point builtin functions. + (DXEXQ): Likewise. + (DDEDPD): Likewise. + (DDEDPDQ): Likewise. + (DENBCD): Likewise. + (DENBCDQ): Likewise. + (DIEX): Likewise. + (DIEXQ): Likewise. + (DSCLI): Likewise. + (DSCLIQ): Likewise. + (DSCRI): Likewise. + (DSCRIQ): Likewise. + (CDTBCD): Add new BCD builtin functions. + (CBCDTD): Likewise. + (ADDG6S): Likewise. + (BCDADD): Likewise. + (BCDADD_LT): Likewise. + (BCDADD_EQ): Likewise. + (BCDADD_GT): Likewise. + (BCDADD_OV): Likewise. + (BCDSUB): Likewise. + (BCDSUB_LT): Likewise. + (BCDSUB_EQ): Likewise. + (BCDSUB_GT): Likewise. + (BCDSUB_OV): Likewise. + (PACK_TD): Add new pack/unpack 128-bit type builtin functions. + (UNPACK_TD): Likewise. + (PACK_TF): Likewise. + (UNPACK_TF): Likewise. + (UNPACK_TF_0): Likewise. + (UNPACK_TF_1): Likewise. + (PACK_V1TI): Likewise. + (UNPACK_V1TI): Likewise. + + * config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Add + support for decimal floating point builtin functions. + (rs6000_expand_ternop_builtin): Add checks for the new builtin + functions that take constant arguments. + (rs6000_invalid_builtin): Add decimal floating point builtin + support. + (rs6000_init_builtins): Setup long double, _Decimal64, and + _Decimal128 types for new builtin functions. + (builtin_function_type): Set the unsigned flags appropriately for + the new builtin functions. + (rs6000_opt_masks): Add support for decimal floating point builtin + functions. + + * config/rs6000/rs6000.h (RS6000_BTM_DFP): Add support for decimal + floating point builtin functions. + (RS6000_BTM_COMMON): Likewise. + (RS6000_BTI_long_double): Likewise. + (RS6000_BTI_dfloat64): Likewise. + (RS6000_BTI_dfloat128): Likewise. + (long_double_type_internal_node): Likewise. + (dfloat64_type_internal_node): Likewise. + (dfloat128_type_internal_node): Likewise. + + * config/rs6000/altivec.h (UNSPEC_BCDADD): Add support for ISA + 2.07 bcd arithmetic instructions. + (UNSPEC_BCDSUB): Likewise. + (UNSPEC_BCD_OVERFLOW): Likewise. + (UNSPEC_BCD_ADD_SUB): Likewise. + (bcd_add_sub): Likewise. + (BCD_TEST): Likewise. + (bcd<bcd_add_sub>): Likewise. + (bcd<bcd_add_sub>_test): Likewise. + (bcd<bcd_add_sub>_test2): Likewise. + (bcd<bcd_add_sub>_<code>): Likewise. + (peephole2 for combined bcd ops): Likewise. + + * config/rs6000/dfp.md (UNSPEC_DDEDPD): Add support for new + decimal floating point builtin functions. + (UNSPEC_DENBCD): Likewise. + (UNSPEC_DXEX): Likewise. + (UNSPEC_DIEX): Likewise. + (UNSPEC_DSCLI): Likewise. + (UNSPEC_DSCRI): Likewise. + (D64_D128): Likewise. + (dfp_suffix): Likewise. + (dfp_ddedpd_<mode>): Likewise. + (dfp_denbcd_<mode>): Likewise. + (dfp_dxex_<mode>): Likewise. + (dfp_diex_<mode>): Likewise. + (dfp_dscli_<mode>): Likewise. + (dfp_dscri_<mode>): Likewise. + + * config/rs6000/rs6000.md (UNSPEC_ADDG6S): Add support for new BCD + builtin functions. + (UNSPEC_CDTBCD): Likewise. + (UNSPEC_CBCDTD): Likewise. + (UNSPEC_DIVE): Add support for new extended divide builtin + functions. + (UNSPEC_DIVEO): Likewise. + (UNSPEC_DIVEU): Likewise. + (UNSPEC_DIVEUO): Likewise. + (UNSPEC_UNPACK_128BIT): Add support for new builtin functions to + pack/unpack 128-bit types. + (UNSPEC_PACK_128BIT): Likewise. + (idiv_ldiv): New mode attribute to set the 32/64-bit divide type. + (udiv<mode>3): Use idiv_ldiv mode attribute. + (div<mode>3): Likewise. + (addg6s): Add new BCD builtin functions. + (cdtbcd): Likewise. + (cbcdtd): Likewise. + (UNSPEC_DIV_EXTEND): Add support for new extended divide + instructions. + (div_extend): Likewise. + (div<div_extend>_<mode>"): Likewise. + (FP128_64): Add support for new builtin functions to pack/unpack + 128-bit types. + (unpack<mode>): Likewise. + (unpacktf_0): Likewise. + (unpacktf_1): Likewise. + (unpack<mode>_dm): Likewise. + (unpack<mode>_nodm): Likewise. + (pack<mode>): Likewise. + (unpackv1ti): Likewise. + (packv1ti): Likewise. + +2014-04-24 Vishnu K S <Vishnu.k_s@atmel.com> + + * gcc/config/avr/avr.c: Add comment on why -fdelete-null-pointer-checks + is disabled. + +2014-04-24 Jakub Jelinek <jakub@redhat.com> + + * tree.h (OMP_CLAUSE_LINEAR_GIMPLE_SEQ): Define. + * gimplify.c (omp_is_private): Change last argument's type to int. + Only diagnose lastprivate if the simd argument is 1, only diagnose + linear if the simd argument is 2. + (gimplify_omp_for): Adjust omp_is_private callers. When adding + lastprivate or private, add the clause to OMP_FOR_CLAUSES. Pass + GOVD_EXPLICIT to omp_add_variable. For simd with collapse == 1 + create OMP_CLAUSE_LINEAR rather than OMP_CLAUSE_PRIVATE for var. + If var != decl and decl is in OMP_CLAUSE_LINEAR, gimplify decl + increment to OMP_CLAUSE_LINEAR_GIMPLE_SEQ. + * omp-low.c (scan_sharing_clauses, lower_lastprivate_clauses): Handle + OMP_CLAUSE_LINEAR_GIMPLE_SEQ. + * tree-nested.c (convert_nonlocal_omp_clauses, + convert_local_omp_clauses): Handle OMP_CLAUSE_LINEAR. + +2014-04-24 Segher Boessenkool <segher@kernel.crashing.org> + + PR target/60822 + * config/m68k/m68k.md (extendplussidi): Don't allow memory for + operand 1. + 2014-04-24 Dimitris Papavasiliou <dpapavas@gmail.com> * flag-types.h (enum ivar_visibility): Add. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index dd60d348052..2eee80b2cf1 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20140424 +20140428 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6dc0c11ed3f..a31cd3c2f11 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2014-04-26 Eric Botcazou <ebotcazou@adacore.com> + + * gnatvsn.ads (Library_Version): Bump to 4.10. + 2014-04-23 Eric Botcazou <ebotcazou@adacore.com> Revert diff --git a/gcc/ada/gnatvsn.ads b/gcc/ada/gnatvsn.ads index d1f95621b98..a0155fe7cb9 100644 --- a/gcc/ada/gnatvsn.ads +++ b/gcc/ada/gnatvsn.ads @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2013, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2014, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -82,7 +82,7 @@ package Gnatvsn is -- Prefix generated by binder. If it is changed, be sure to change -- GNAT.Compiler_Version.Ver_Prefix as well. - Library_Version : constant String := "4.9"; + Library_Version : constant String := "4.10"; -- Library version. This value must be updated when the compiler -- version number Gnat_Static_Version_String is updated. -- diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c index dfb13ce55fb..87fbd8556fb 100644 --- a/gcc/alloc-pool.c +++ b/gcc/alloc-pool.c @@ -250,7 +250,7 @@ void * pool_alloc (alloc_pool pool) { alloc_pool_list header; -#ifdef ENABLE_VALGRIND_CHECKING +#ifdef ENABLE_VALGRIND_ANNOTATIONS int size; #endif @@ -265,7 +265,7 @@ pool_alloc (alloc_pool pool) } gcc_checking_assert (pool); -#ifdef ENABLE_VALGRIND_CHECKING +#ifdef ENABLE_VALGRIND_ANNOTATIONS size = pool->elt_size - offsetof (allocation_object, u.data); #endif @@ -334,7 +334,7 @@ void pool_free (alloc_pool pool, void *ptr) { alloc_pool_list header; -#if defined(ENABLE_VALGRIND_CHECKING) || defined(ENABLE_CHECKING) +#if defined(ENABLE_VALGRIND_ANNOTATIONS) || defined(ENABLE_CHECKING) int size; size = pool->elt_size - offsetof (allocation_object, u.data); #endif diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 1b466ac4b51..fb0d102eac3 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,20 @@ +2014-04-25 Marek Polacek <polacek@redhat.com> + + PR c/18079 + * c-common.c (handle_noinline_attribute): Warn if the attribute + conflicts with always_inline attribute. + (handle_always_inline_attribute): Warn if the attribute conflicts + with noinline attribute. + +2014-04-25 Marek Polacek <polacek@redhat.com> + + PR c/60156 + * c-common.c (check_main_parameter_types): Warn about variadic main. + +2014-04-24 Mike Stump <mikestump@comcast.net> + + * c.opt (Wshadow-ivar): Default to on. + 2014-04-24 Dimitris Papavasiliou <dpapavas@gmail.com> * c.opt (Wshadow-ivar, flocal-ivars, fivar-visibility): Add. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 347be6e8208..0afe2f5ab38 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -2229,6 +2229,10 @@ check_main_parameter_types (tree decl) if (argct > 0 && (argct < 2 || argct > 3)) pedwarn (input_location, OPT_Wmain, "%q+D takes only zero or two arguments", decl); + + if (stdarg_p (TREE_TYPE (decl))) + pedwarn (input_location, OPT_Wmain, + "%q+D declared as variadic function", decl); } /* vector_targets_convertible_p is used for vector pointer types. The @@ -6549,8 +6553,8 @@ handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args), { if (lookup_attribute ("cold", DECL_ATTRIBUTES (*node)) != NULL) { - warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s", - name, "cold"); + warning (OPT_Wattributes, "%qE attribute ignored due to conflict " + "with attribute %qs", name, "cold"); *no_add_attrs = true; } /* Most of the rest of the hot processing is done later with @@ -6577,8 +6581,8 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args), { if (lookup_attribute ("hot", DECL_ATTRIBUTES (*node)) != NULL) { - warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s", - name, "hot"); + warning (OPT_Wattributes, "%qE attribute ignored due to conflict " + "with attribute %qs", name, "hot"); *no_add_attrs = true; } /* Most of the rest of the cold processing is done later with @@ -6651,7 +6655,16 @@ handle_noinline_attribute (tree *node, tree name, int ARG_UNUSED (flags), bool *no_add_attrs) { if (TREE_CODE (*node) == FUNCTION_DECL) - DECL_UNINLINABLE (*node) = 1; + { + if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node))) + { + warning (OPT_Wattributes, "%qE attribute ignored due to conflict " + "with attribute %qs", name, "always_inline"); + *no_add_attrs = true; + } + else + DECL_UNINLINABLE (*node) = 1; + } else { warning (OPT_Wattributes, "%qE attribute ignored", name); @@ -6689,9 +6702,16 @@ handle_always_inline_attribute (tree *node, tree name, { if (TREE_CODE (*node) == FUNCTION_DECL) { - /* Set the attribute and mark it for disregarding inline - limits. */ - DECL_DISREGARD_INLINE_LIMITS (*node) = 1; + if (lookup_attribute ("noinline", DECL_ATTRIBUTES (*node))) + { + warning (OPT_Wattributes, "%qE attribute ignored due to conflict " + "with %qs attribute", name, "noinline"); + *no_add_attrs = true; + } + else + /* Set the attribute and mark it for disregarding inline + limits. */ + DECL_DISREGARD_INLINE_LIMITS (*node) = 1; } else { diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 2bc06ba7bba..94447082fb5 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -685,7 +685,7 @@ ObjC ObjC++ Var(warn_selector) Warning Warn if a selector has multiple methods Wshadow-ivar -ObjC ObjC++ Var(warn_shadow_ivar) Init(-1) Warning +ObjC ObjC++ Var(warn_shadow_ivar) Init(1) Warning Warn if a local declaration hides an instance variable Wsequence-point diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 2d182f354d5..80841af40ee 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,38 @@ +2014-04-25 Marek Polacek <polacek@redhat.com> + + PR c/18079 + * c-decl.c (diagnose_mismatched_decls): Warn for mismatched + always_inline/noinline and hot/cold attributes. + +2014-04-25 Marek Polacek <polacek@redhat.com> + + PR c/60114 + * c-parser.c (c_parser_initelt): Pass input_location to + process_init_element. + (c_parser_initval): Pass loc to process_init_element. + * c-tree.h (process_init_element): Adjust declaration. + * c-typeck.c (push_init_level): Pass input_location to + process_init_element. + (pop_init_level): Likewise. + (set_designator): Likewise. + (output_init_element): Add location_t parameter. Pass loc to + digest_init. + (output_pending_init_elements): Pass input_location to + output_init_element. + (process_init_element): Add location_t parameter. Pass loc to + output_init_element. + +2014-04-24 Prathamesh Kulkarni <bilbotheelffriend@gmail.com> + + * c-parser.c (c_parser_sizeof_expression): Reorganize slightly to + avoid goto. + +2014-04-24 Jakub Jelinek <jakub@redhat.com> + + * c-parser.c (c_parser_omp_atomic): Allow seq_cst before + atomic-clause, allow comma in between atomic-clause and + seq_cst. + 2014-04-22 Jakub Jelinek <jakub@redhat.com> PR c/59073 diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 82b882e3cd1..90808eda618 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -2099,18 +2099,38 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, /* Diagnose inline __attribute__ ((noinline)) which is silly. */ if (DECL_DECLARED_INLINE_P (newdecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl))) - { - warned |= warning (OPT_Wattributes, - "inline declaration of %qD follows " - "declaration with attribute noinline", newdecl); - } + warned |= warning (OPT_Wattributes, + "inline declaration of %qD follows " + "declaration with attribute noinline", newdecl); else if (DECL_DECLARED_INLINE_P (olddecl) && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))) - { - warned |= warning (OPT_Wattributes, - "declaration of %q+D with attribute " - "noinline follows inline declaration ", newdecl); - } + warned |= warning (OPT_Wattributes, + "declaration of %q+D with attribute " + "noinline follows inline declaration ", newdecl); + else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)) + && lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl))) + warned |= warning (OPT_Wattributes, + "declaration of %q+D with attribute " + "%qs follows declaration with attribute %qs", + newdecl, "noinline", "always_inline"); + else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl)) + && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl))) + warned |= warning (OPT_Wattributes, + "declaration of %q+D with attribute " + "%qs follows declaration with attribute %qs", + newdecl, "always_inline", "noinline"); + else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl)) + && lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl))) + warned |= warning (OPT_Wattributes, + "declaration of %q+D with attribute %qs follows " + "declaration with attribute %qs", newdecl, "cold", + "hot"); + else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl)) + && lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl))) + warned |= warning (OPT_Wattributes, + "declaration of %q+D with attribute %qs follows " + "declaration with attribute %qs", newdecl, "hot", + "cold"); } else /* PARM_DECL, VAR_DECL */ { diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index b1770860ae7..41ae77b541e 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -4219,7 +4219,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) init.original_type = NULL; c_parser_error (parser, "expected identifier"); c_parser_skip_until_found (parser, CPP_COMMA, NULL); - process_init_element (init, false, braced_init_obstack); + process_init_element (input_location, init, false, + braced_init_obstack); return; } } @@ -4351,7 +4352,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) init.original_type = NULL; c_parser_error (parser, "expected %<=%>"); c_parser_skip_until_found (parser, CPP_COMMA, NULL); - process_init_element (init, false, braced_init_obstack); + process_init_element (input_location, init, false, + braced_init_obstack); return; } } @@ -4372,18 +4374,19 @@ c_parser_initval (c_parser *parser, struct c_expr *after, { struct c_expr init; gcc_assert (!after || c_dialect_objc ()); + location_t loc = c_parser_peek_token (parser)->location; + if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after) init = c_parser_braced_init (parser, NULL_TREE, true); else { - location_t loc = c_parser_peek_token (parser)->location; init = c_parser_expr_no_commas (parser, after); if (init.value != NULL_TREE && TREE_CODE (init.value) != STRING_CST && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR) init = convert_lvalue_to_rvalue (loc, init, true, true); } - process_init_element (init, false, braced_init_obstack); + process_init_element (loc, init, false, braced_init_obstack); } /* Parse a compound statement (possibly a function body) (C90 6.6.2, @@ -6514,30 +6517,29 @@ c_parser_sizeof_expression (c_parser *parser) return ret; } if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) + expr = c_parser_postfix_expression_after_paren_type (parser, + type_name, + expr_loc); + else { - expr = c_parser_postfix_expression_after_paren_type (parser, - type_name, - expr_loc); - goto sizeof_expr; + /* sizeof ( type-name ). */ + c_inhibit_evaluation_warnings--; + in_sizeof--; + return c_expr_sizeof_type (expr_loc, type_name); } - /* sizeof ( type-name ). */ - c_inhibit_evaluation_warnings--; - in_sizeof--; - return c_expr_sizeof_type (expr_loc, type_name); } else { expr_loc = c_parser_peek_token (parser)->location; expr = c_parser_unary_expression (parser); - sizeof_expr: - c_inhibit_evaluation_warnings--; - in_sizeof--; - mark_exp_read (expr.value); - if (TREE_CODE (expr.value) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) - error_at (expr_loc, "%<sizeof%> applied to a bit-field"); - return c_expr_sizeof_expr (expr_loc, expr); } + c_inhibit_evaluation_warnings--; + in_sizeof--; + mark_exp_read (expr.value); + if (TREE_CODE (expr.value) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) + error_at (expr_loc, "%<sizeof%> applied to a bit-field"); + return c_expr_sizeof_expr (expr_loc, expr); } /* Parse an alignof expression. */ @@ -11198,6 +11200,18 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) if (c_parser_next_token_is (parser, CPP_NAME)) { const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (!strcmp (p, "seq_cst")) + { + seq_cst = true; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); + } + } + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); if (!strcmp (p, "read")) code = OMP_ATOMIC_READ; @@ -11212,13 +11226,21 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) if (p) c_parser_consume_token (parser); } - if (c_parser_next_token_is (parser, CPP_NAME)) + if (!seq_cst) { - const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - if (!strcmp (p, "seq_cst")) + if (c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); + + if (c_parser_next_token_is (parser, CPP_NAME)) { - seq_cst = true; - c_parser_consume_token (parser); + const char *p + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (!strcmp (p, "seq_cst")) + { + seq_cst = true; + c_parser_consume_token (parser); + } } } c_parser_skip_to_pragma_eol (parser); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 85df8858dea..53768d619b7 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -612,7 +612,8 @@ extern void push_init_level (int, struct obstack *); extern struct c_expr pop_init_level (int, struct obstack *); extern void set_init_index (tree, tree, struct obstack *); extern void set_init_label (tree, struct obstack *); -extern void process_init_element (struct c_expr, bool, struct obstack *); +extern void process_init_element (location_t, struct c_expr, bool, + struct obstack *); extern tree build_compound_literal (location_t, tree, tree, bool); extern void check_compound_literal_type (location_t, struct c_type_name *); extern tree c_start_case (location_t, location_t, tree); diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 886ef518be6..e4293104d7b 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -103,8 +103,8 @@ static int spelling_length (void); static char *print_spelling (char *); static void warning_init (int, const char *); static tree digest_init (location_t, tree, tree, tree, bool, bool, int); -static void output_init_element (tree, tree, bool, tree, tree, int, bool, - struct obstack *); +static void output_init_element (location_t, tree, tree, bool, tree, tree, int, + bool, struct obstack *); static void output_pending_init_elements (int, struct obstack *); static int set_designator (int, struct obstack *); static void push_range_stack (tree, struct obstack *); @@ -7182,13 +7182,15 @@ push_init_level (int implicit, struct obstack * braced_init_obstack) if ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) && constructor_fields == 0) - process_init_element (pop_init_level (1, braced_init_obstack), + process_init_element (input_location, + pop_init_level (1, braced_init_obstack), true, braced_init_obstack); else if (TREE_CODE (constructor_type) == ARRAY_TYPE && constructor_max_index && tree_int_cst_lt (constructor_max_index, constructor_index)) - process_init_element (pop_init_level (1, braced_init_obstack), + process_init_element (input_location, + pop_init_level (1, braced_init_obstack), true, braced_init_obstack); else break; @@ -7388,10 +7390,9 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack) /* When we come to an explicit close brace, pop any inner levels that didn't have explicit braces. */ while (constructor_stack->implicit) - { - process_init_element (pop_init_level (1, braced_init_obstack), - true, braced_init_obstack); - } + process_init_element (input_location, + pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); gcc_assert (!constructor_range_stack); } @@ -7569,10 +7570,9 @@ set_designator (int array, struct obstack * braced_init_obstack) /* Designator list starts at the level of closest explicit braces. */ while (constructor_stack->implicit) - { - process_init_element (pop_init_level (1, braced_init_obstack), - true, braced_init_obstack); - } + process_init_element (input_location, + pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); constructor_designated = 1; return 0; } @@ -8194,9 +8194,9 @@ find_init_member (tree field, struct obstack * braced_init_obstack) existing initializer. */ static void -output_init_element (tree value, tree origtype, bool strict_string, tree type, - tree field, int pending, bool implicit, - struct obstack * braced_init_obstack) +output_init_element (location_t loc, tree value, tree origtype, + bool strict_string, tree type, tree field, int pending, + bool implicit, struct obstack * braced_init_obstack) { tree semantic_type = NULL_TREE; bool maybe_const = true; @@ -8294,8 +8294,8 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type, if (semantic_type) value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value); - value = digest_init (input_location, type, value, origtype, npc, - strict_string, require_constant_value); + value = digest_init (loc, type, value, origtype, npc, strict_string, + require_constant_value); if (value == error_mark_node) { constructor_erroneous = 1; @@ -8422,8 +8422,8 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack) { if (tree_int_cst_equal (elt->purpose, constructor_unfilled_index)) - output_init_element (elt->value, elt->origtype, true, - TREE_TYPE (constructor_type), + output_init_element (input_location, elt->value, elt->origtype, + true, TREE_TYPE (constructor_type), constructor_unfilled_index, 0, false, braced_init_obstack); else if (tree_int_cst_lt (constructor_unfilled_index, @@ -8477,8 +8477,8 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack) if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos)) { constructor_unfilled_fields = elt->purpose; - output_init_element (elt->value, elt->origtype, true, - TREE_TYPE (elt->purpose), + output_init_element (input_location, elt->value, elt->origtype, + true, TREE_TYPE (elt->purpose), elt->purpose, 0, false, braced_init_obstack); } @@ -8551,7 +8551,7 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack) existing initializer. */ void -process_init_element (struct c_expr value, bool implicit, +process_init_element (location_t loc, struct c_expr value, bool implicit, struct obstack * braced_init_obstack) { tree orig_value = value.value; @@ -8595,14 +8595,14 @@ process_init_element (struct c_expr value, bool implicit, if ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) && constructor_fields == 0) - process_init_element (pop_init_level (1, braced_init_obstack), + process_init_element (loc, pop_init_level (1, braced_init_obstack), true, braced_init_obstack); else if ((TREE_CODE (constructor_type) == ARRAY_TYPE || TREE_CODE (constructor_type) == VECTOR_TYPE) && constructor_max_index && tree_int_cst_lt (constructor_max_index, constructor_index)) - process_init_element (pop_init_level (1, braced_init_obstack), + process_init_element (loc, pop_init_level (1, braced_init_obstack), true, braced_init_obstack); else break; @@ -8680,7 +8680,7 @@ process_init_element (struct c_expr value, bool implicit, if (value.value) { push_member_name (constructor_fields); - output_init_element (value.value, value.original_type, + output_init_element (loc, value.value, value.original_type, strict_string, fieldtype, constructor_fields, 1, implicit, braced_init_obstack); @@ -8772,7 +8772,7 @@ process_init_element (struct c_expr value, bool implicit, if (value.value) { push_member_name (constructor_fields); - output_init_element (value.value, value.original_type, + output_init_element (loc, value.value, value.original_type, strict_string, fieldtype, constructor_fields, 1, implicit, braced_init_obstack); @@ -8824,7 +8824,7 @@ process_init_element (struct c_expr value, bool implicit, if (value.value) { push_array_bounds (tree_to_uhwi (constructor_index)); - output_init_element (value.value, value.original_type, + output_init_element (loc, value.value, value.original_type, strict_string, elttype, constructor_index, 1, implicit, braced_init_obstack); @@ -8859,7 +8859,7 @@ process_init_element (struct c_expr value, bool implicit, { if (TREE_CODE (value.value) == VECTOR_CST) elttype = TYPE_MAIN_VARIANT (constructor_type); - output_init_element (value.value, value.original_type, + output_init_element (loc, value.value, value.original_type, strict_string, elttype, constructor_index, 1, implicit, braced_init_obstack); @@ -8888,7 +8888,7 @@ process_init_element (struct c_expr value, bool implicit, else { if (value.value) - output_init_element (value.value, value.original_type, + output_init_element (loc, value.value, value.original_type, strict_string, constructor_type, NULL_TREE, 1, implicit, braced_init_obstack); @@ -8907,8 +8907,8 @@ process_init_element (struct c_expr value, bool implicit, while (constructor_stack != range_stack->stack) { gcc_assert (constructor_stack->implicit); - process_init_element (pop_init_level (1, - braced_init_obstack), + process_init_element (loc, + pop_init_level (1, braced_init_obstack), true, braced_init_obstack); } for (p = range_stack; @@ -8916,7 +8916,8 @@ process_init_element (struct c_expr value, bool implicit, p = p->prev) { gcc_assert (constructor_stack->implicit); - process_init_element (pop_init_level (1, braced_init_obstack), + process_init_element (loc, + pop_init_level (1, braced_init_obstack), true, braced_init_obstack); } diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 28524f85ca1..b5df572d039 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1695,8 +1695,8 @@ release_function_body (tree decl) } if (cfun->cfg) { - gcc_assert (dom_computed[0] == DOM_NONE); - gcc_assert (dom_computed[1] == DOM_NONE); + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); clear_edges (); cfun->cfg = NULL; } diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 7bf9a07cbb2..d06ce3217fd 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -520,7 +520,7 @@ cgraph_add_new_function (tree fndecl, bool lowered) push_cfun (DECL_STRUCT_FUNCTION (fndecl)); gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); - execute_pass_list (passes->all_lowering_passes); + execute_pass_list (cfun, passes->all_lowering_passes); passes->execute_early_local_passes (); bitmap_obstack_release (NULL); pop_cfun (); @@ -658,7 +658,7 @@ analyze_function (struct cgraph_node *node) gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); - execute_pass_list (g->get_passes ()->all_lowering_passes); + execute_pass_list (cfun, g->get_passes ()->all_lowering_passes); free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_DOMINATORS); compact_blocks (); @@ -1771,7 +1771,7 @@ expand_function (struct cgraph_node *node) /* Signal the start of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL); - execute_pass_list (g->get_passes ()->all_passes); + execute_pass_list (cfun, g->get_passes ()->all_passes); /* Signal the end of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); diff --git a/gcc/config.in b/gcc/config.in index af02866dd33..c0ba36ea98b 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -172,6 +172,12 @@ #endif +/* Define to get calls to the valgrind runtime enabled. */ +#ifndef USED_FOR_TARGET +#undef ENABLE_VALGRIND_ANNOTATIONS +#endif + + /* Define if you want to run subprograms and generated programs through valgrind (a memory checker). This is extremely expensive. */ #ifndef USED_FOR_TARGET @@ -1697,12 +1703,6 @@ #endif -/* Define to the library containing __tls_get_addr/___tls_get_addr. */ -#ifndef USED_FOR_TARGET -#undef LIB_TLS_SPEC -#endif - - /* The linker hash style */ #ifndef USED_FOR_TARGET #undef LINKER_HASH_STYLE diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c index 884d4b37fac..d31191ab9e7 100644 --- a/gcc/config/arm/aarch-common.c +++ b/gcc/config/arm/aarch-common.c @@ -195,14 +195,18 @@ bool aarch_rev16_shright_mask_imm_p (rtx val, enum machine_mode mode) { return CONST_INT_P (val) - && INTVAL (val) == trunc_int_for_mode (0xff00ff00ff00ff, mode); + && INTVAL (val) + == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff), + mode); } bool aarch_rev16_shleft_mask_imm_p (rtx val, enum machine_mode mode) { return CONST_INT_P (val) - && INTVAL (val) == trunc_int_for_mode (0xff00ff00ff00ff00, mode); + && INTVAL (val) + == trunc_int_for_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff00), + mode); } diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 8ca945f1a67..1e44080d601 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1710,7 +1710,8 @@ const struct tune_params arm_cortex_a8_tune = false, /* Prefer LDRD/STRD. */ {true, true}, /* Prefer non short circuit. */ &arm_default_vec_cost, /* Vectorizer costs. */ - false /* Prefer Neon for 64-bits bitops. */ + false, /* Prefer Neon for 64-bits bitops. */ + false, false /* Prefer 32-bit encodings. */ }; const struct tune_params arm_cortex_a7_tune = @@ -6216,11 +6217,6 @@ arm_function_ok_for_sibcall (tree decl, tree exp) if (TARGET_VXWORKS_RTP && flag_pic && !targetm.binds_local_p (decl)) return false; - /* Cannot tail-call to long calls, since these are out of range of - a branch instruction. */ - if (decl && arm_is_long_call_p (decl)) - return false; - /* If we are interworking and the function is not declared static then we can't tail-call it unless we know that it exists in this compilation unit (since it might be a Thumb routine). */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 8a949b929fa..97753ce1e98 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -9367,8 +9367,10 @@ "TARGET_32BIT" " { - if (!REG_P (XEXP (operands[0], 0)) - && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)) + if ((!REG_P (XEXP (operands[0], 0)) + && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF) + || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF + && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0))))) XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); if (operands[2] == NULL_RTX) @@ -9385,8 +9387,10 @@ "TARGET_32BIT" " { - if (!REG_P (XEXP (operands[1], 0)) && - (GET_CODE (XEXP (operands[1],0)) != SYMBOL_REF)) + if ((!REG_P (XEXP (operands[1], 0)) + && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF) + || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF + && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0))))) XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); if (operands[3] == NULL_RTX) diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 6273e8820c6..d74fcb31bc7 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -681,5 +681,6 @@ (match_code "reg" "0"))) (define_predicate "call_insn_operand" - (ior (match_code "symbol_ref") + (ior (and (match_code "symbol_ref") + (match_test "!arm_is_long_call_p (SYMBOL_REF_DECL (op))")) (match_operand 0 "s_register_operand"))) diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 25075b2f4b3..0fa7f6633e2 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -290,6 +290,12 @@ avr_to_int_mode (rtx x) static void avr_option_override (void) { + /* Disable -fdelete-null-pointer-checks option for AVR target. + This option compiler assumes that dereferencing of a null pointer + would halt the program. For AVR this assumption is not true and + programs can safely dereference null pointers. Changes made by this + option may not work properly for AVR. So disable this option. */ + flag_delete_null_pointer_checks = 0; /* caller-save.c looks for call-clobbered hard registers that are assigned diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index c9977bf2b0e..2c31dc8062d 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -518,6 +518,13 @@ ix86_target_macros (void) if (TARGET_LONG_DOUBLE_128) cpp_define (parse_in, "__LONG_DOUBLE_128__"); + if (TARGET_128BIT_LONG_DOUBLE) + cpp_define (parse_in, "__SIZEOF_FLOAT80__=16"); + else + cpp_define (parse_in, "__SIZEOF_FLOAT80__=12"); + + cpp_define (parse_in, "__SIZEOF_FLOAT128__=16"); + cpp_define_formatted (parse_in, "__ATOMIC_HLE_ACQUIRE=%d", IX86_HLE_ACQUIRE); cpp_define_formatted (parse_in, "__ATOMIC_HLE_RELEASE=%d", IX86_HLE_RELEASE); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 25e2e93e317..fde0a93e68f 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -3201,7 +3201,7 @@ (const_string "1") (const_string "*"))) (set (attr "mode") - (cond [(eq_attr "alternative" "3,4,9,10,13,14,15") + (cond [(eq_attr "alternative" "3,4,9,10,12,13,14,15") (const_string "SI") (eq_attr "alternative" "11") (const_string "DI") @@ -14427,15 +14427,16 @@ "TARGET_USE_FANCY_MATH_387 && flag_unsafe_math_optimizations" { + rtx tmp1, tmp2; if (optimize_insn_for_size_p ()) FAIL; - operands[3] = gen_reg_rtx (XFmode); - operands[4] = gen_reg_rtx (XFmode); + tmp1 = gen_reg_rtx (XFmode); + tmp2 = gen_reg_rtx (XFmode); - emit_insn (gen_floatsixf2 (operands[3], operands[2])); - emit_insn (gen_fscalexf4_i387 (operands[0], operands[4], - operands[1], operands[3])); + emit_insn (gen_floatsixf2 (tmp1, operands[2])); + emit_insn (gen_fscalexf4_i387 (operands[0], tmp2, + operands[1], tmp1)); DONE; }) diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index e61048b4d0b..72c11f592db 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -1868,9 +1868,11 @@ ;; Maybe there is a way to make that the general case, by forcing the ;; result of the SI tree to be in the lower register of the DI target +;; Don't allow memory for operand 1 as that would require an earlyclobber +;; which results in worse code (define_insn "extendplussidi" [(set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (plus:SI (match_operand:SI 1 "general_operand" "%rmn") + (sign_extend:DI (plus:SI (match_operand:SI 1 "general_operand" "%rn") (match_operand:SI 2 "general_operand" "rmn"))))] "" { diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 674cb40bf7a..a8cfcb739ea 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -143,6 +143,9 @@ UNSPEC_VSUBEUQM UNSPEC_VSUBECUQ UNSPEC_VBPERMQ + UNSPEC_BCDADD + UNSPEC_BCDSUB + UNSPEC_BCD_OVERFLOW ]) (define_c_enum "unspecv" @@ -3334,3 +3337,112 @@ "vbpermq %0,%1,%2" [(set_attr "length" "4") (set_attr "type" "vecsimple")]) + +;; Decimal Integer operations +(define_int_iterator UNSPEC_BCD_ADD_SUB [UNSPEC_BCDADD UNSPEC_BCDSUB]) + +(define_int_attr bcd_add_sub [(UNSPEC_BCDADD "add") + (UNSPEC_BCDSUB "sub")]) + +(define_code_iterator BCD_TEST [eq lt gt unordered]) + +(define_insn "bcd<bcd_add_sub>" + [(set (match_operand:V1TI 0 "register_operand" "") + (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "") + (match_operand:V1TI 2 "register_operand" "") + (match_operand:QI 3 "const_0_to_1_operand" "")] + UNSPEC_BCD_ADD_SUB)) + (clobber (reg:CCFP 74))] + "TARGET_P8_VECTOR" + "bcd<bcd_add_sub>. %0,%1,%2,%3" + [(set_attr "length" "4") + (set_attr "type" "vecsimple")]) + +;; Use a floating point type (V2DFmode) for the compare to set CR6 so that we +;; can use the unordered test for BCD nans and add/subtracts that overflow. An +;; UNORDERED test on an integer type (like V1TImode) is not defined. The type +;; probably should be one that can go in the VMX (Altivec) registers, so we +;; can't use DDmode or DFmode. +(define_insn "*bcd<bcd_add_sub>_test" + [(set (reg:CCFP 74) + (compare:CCFP + (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "v") + (match_operand:V1TI 2 "register_operand" "v") + (match_operand:QI 3 "const_0_to_1_operand" "i")] + UNSPEC_BCD_ADD_SUB) + (match_operand:V2DF 4 "zero_constant" "j"))) + (clobber (match_scratch:V1TI 0 "=v"))] + "TARGET_P8_VECTOR" + "bcd<bcd_add_sub>. %0,%1,%2,%3" + [(set_attr "length" "4") + (set_attr "type" "vecsimple")]) + +(define_insn "*bcd<bcd_add_sub>_test2" + [(set (match_operand:V1TI 0 "register_operand" "=v") + (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "v") + (match_operand:V1TI 2 "register_operand" "v") + (match_operand:QI 3 "const_0_to_1_operand" "i")] + UNSPEC_BCD_ADD_SUB)) + (set (reg:CCFP 74) + (compare:CCFP + (unspec:V2DF [(match_dup 1) + (match_dup 2) + (match_dup 3)] + UNSPEC_BCD_ADD_SUB) + (match_operand:V2DF 4 "zero_constant" "j")))] + "TARGET_P8_VECTOR" + "bcd<bcd_add_sub>. %0,%1,%2,%3" + [(set_attr "length" "4") + (set_attr "type" "vecsimple")]) + +(define_expand "bcd<bcd_add_sub>_<code>" + [(parallel [(set (reg:CCFP 74) + (compare:CCFP + (unspec:V2DF [(match_operand:V1TI 1 "register_operand" "") + (match_operand:V1TI 2 "register_operand" "") + (match_operand:QI 3 "const_0_to_1_operand" "")] + UNSPEC_BCD_ADD_SUB) + (match_dup 4))) + (clobber (match_scratch:V1TI 5 ""))]) + (set (match_operand:SI 0 "register_operand" "") + (BCD_TEST:SI (reg:CCFP 74) + (const_int 0)))] + "TARGET_P8_VECTOR" +{ + operands[4] = CONST0_RTX (V2DFmode); +}) + +;; Peephole2 pattern to combine a bcdadd/bcdsub that calculates the value and +;; the bcdadd/bcdsub that tests the value. The combiner won't work since +;; CR6 is a hard coded register. Unfortunately, all of the Altivec predicate +;; support is hard coded to use the fixed register CR6 instead of creating +;; a register class for CR6. + +(define_peephole2 + [(parallel [(set (match_operand:V1TI 0 "register_operand" "") + (unspec:V1TI [(match_operand:V1TI 1 "register_operand" "") + (match_operand:V1TI 2 "register_operand" "") + (match_operand:QI 3 "const_0_to_1_operand" "")] + UNSPEC_BCD_ADD_SUB)) + (clobber (reg:CCFP 74))]) + (parallel [(set (reg:CCFP 74) + (compare:CCFP + (unspec:V2DF [(match_dup 1) + (match_dup 2) + (match_dup 3)] + UNSPEC_BCD_ADD_SUB) + (match_operand:V2DF 4 "zero_constant" ""))) + (clobber (match_operand:V1TI 5 "register_operand" ""))])] + "TARGET_P8_VECTOR" + [(parallel [(set (match_dup 0) + (unspec:V1TI [(match_dup 1) + (match_dup 2) + (match_dup 3)] + UNSPEC_BCD_ADD_SUB)) + (set (reg:CCFP 74) + (compare:CCFP + (unspec:V2DF [(match_dup 1) + (match_dup 2) + (match_dup 3)] + UNSPEC_BCD_ADD_SUB) + (match_dup 4)))])]) diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md index 8e99bc0d787..40e27e77d23 100644 --- a/gcc/config/rs6000/dfp.md +++ b/gcc/config/rs6000/dfp.md @@ -322,3 +322,72 @@ "TARGET_DFP" "dctfixq %0,%1" [(set_attr "type" "fp")]) + + +;; Decimal builtin support + +(define_c_enum "unspec" + [UNSPEC_DDEDPD + UNSPEC_DENBCD + UNSPEC_DXEX + UNSPEC_DIEX + UNSPEC_DSCLI + UNSPEC_DSCRI]) + +(define_mode_iterator D64_D128 [DD TD]) + +(define_mode_attr dfp_suffix [(DD "") + (TD "q")]) + +(define_insn "dfp_ddedpd_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_3_operand" "i") + (match_operand:D64_D128 2 "gpc_reg_operand" "d")] + UNSPEC_DDEDPD))] + "TARGET_DFP" + "ddedpd<dfp_suffix> %1,%0,%2" + [(set_attr "type" "fp")]) + +(define_insn "dfp_denbcd_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:QI 1 "const_0_to_1_operand" "i") + (match_operand:D64_D128 2 "gpc_reg_operand" "d")] + UNSPEC_DENBCD))] + "TARGET_DFP" + "denbcd<dfp_suffix> %1,%0,%2" + [(set_attr "type" "fp")]) + +(define_insn "dfp_dxex_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d")] + UNSPEC_DXEX))] + "TARGET_DFP" + "dxex<dfp_suffix> %0,%1" + [(set_attr "type" "fp")]) + +(define_insn "dfp_diex_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d") + (match_operand:D64_D128 2 "gpc_reg_operand" "d")] + UNSPEC_DXEX))] + "TARGET_DFP" + "diex<dfp_suffix> %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "dfp_dscli_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d") + (match_operand:QI 2 "immediate_operand" "i")] + UNSPEC_DSCLI))] + "TARGET_DFP" + "dscli<dfp_suffix> %0,%1,%2" + [(set_attr "type" "fp")]) + +(define_insn "dfp_dscri_<mode>" + [(set (match_operand:D64_D128 0 "gpc_reg_operand" "=d") + (unspec:D64_D128 [(match_operand:D64_D128 1 "gpc_reg_operand" "d") + (match_operand:QI 2 "immediate_operand" "i")] + UNSPEC_DSCRI))] + "TARGET_DFP" + "dscri<dfp_suffix> %0,%1,%2" + [(set_attr "type" "fp")]) diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 2ed1d4a184d..1616b888c9c 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -171,6 +171,11 @@ (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 0, 1)"))) +;; Match op = 0..3. +(define_predicate "const_0_to_3_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 3)"))) + ;; Match op = 2 or op = 3. (define_predicate "const_2_to_3_operand" (and (match_code "const_int") diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index 83351691fa5..16793f501e7 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -570,6 +570,75 @@ MASK, /* MASK */ \ (ATTR | RS6000_BTC_SPECIAL), /* ATTR */ \ CODE_FOR_nothing) /* ICODE */ + + +/* Decimal floating point builtins for instructions. */ +#define BU_DFP_MISC_1(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_DFP, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_UNARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_DFP_MISC_2(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_DFP, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_BINARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + + +/* Miscellaneous builtins for instructions added in ISA 2.06. These + instructions don't require either the DFP or VSX options, just the basic ISA + 2.06 (popcntd) enablement since they operate on general purpose + registers. */ +#define BU_P7_MISC_1(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_POPCNTD, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_UNARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_P7_MISC_2(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_POPCNTD, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_BINARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + + +/* Miscellaneous builtins for instructions added in ISA 2.07. These + instructions do require the ISA 2.07 vector support, but they aren't vector + instructions. */ +#define BU_P8V_MISC_3(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_3 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_P8_VECTOR, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_TERNARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +/* Miscellaneous builtins. */ +#define BU_MISC_1(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_ALWAYS, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_UNARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_MISC_2(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_" NAME, /* NAME */ \ + RS6000_BTM_ALWAYS, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_BINARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + #endif /* Insure 0 is not a legitimate index. */ @@ -1412,10 +1481,10 @@ BU_P8V_AV_2 (ORC_V4SF, "orc_v4sf", CONST, orcv4sf3) BU_P8V_AV_2 (ORC_V2DF, "orc_v2df", CONST, orcv2df3) /* 3 argument altivec instructions added in ISA 2.07. */ -BU_P8V_AV_3 (VADDEUQM, "vaddeuqm", CONST, altivec_vaddeuqm) -BU_P8V_AV_3 (VADDECUQ, "vaddecuq", CONST, altivec_vaddecuq) -BU_P8V_AV_3 (VSUBEUQM, "vsubeuqm", CONST, altivec_vsubeuqm) -BU_P8V_AV_3 (VSUBECUQ, "vsubecuq", CONST, altivec_vsubecuq) +BU_P8V_AV_3 (VADDEUQM, "vaddeuqm", CONST, altivec_vaddeuqm) +BU_P8V_AV_3 (VADDECUQ, "vaddecuq", CONST, altivec_vaddecuq) +BU_P8V_AV_3 (VSUBEUQM, "vsubeuqm", CONST, altivec_vsubeuqm) +BU_P8V_AV_3 (VSUBECUQ, "vsubecuq", CONST, altivec_vsubecuq) /* Vector comparison instructions added in ISA 2.07. */ BU_P8V_AV_2 (VCMPEQUD, "vcmpequd", CONST, vector_eqv2di) @@ -1475,6 +1544,64 @@ BU_P8V_OVERLOAD_3 (VSUBECUQ, "vsubecuq") BU_P8V_OVERLOAD_3 (VSUBEUQM, "vsubeuqm") +/* 2 argument extended divide functions added in ISA 2.06. */ +BU_P7_MISC_2 (DIVWE, "divwe", CONST, dive_si) +BU_P7_MISC_2 (DIVWEO, "divweo", CONST, diveo_si) +BU_P7_MISC_2 (DIVWEU, "divweu", CONST, diveu_si) +BU_P7_MISC_2 (DIVWEUO, "divweuo", CONST, diveuo_si) +BU_P7_MISC_2 (DIVDE, "divde", CONST, dive_di) +BU_P7_MISC_2 (DIVDEO, "divdeo", CONST, diveo_di) +BU_P7_MISC_2 (DIVDEU, "divdeu", CONST, diveu_di) +BU_P7_MISC_2 (DIVDEUO, "divdeuo", CONST, diveuo_di) + +/* 1 argument DFP (decimal floating point) functions added in ISA 2.05. */ +BU_DFP_MISC_1 (DXEX, "dxex", CONST, dfp_dxex_dd) +BU_DFP_MISC_1 (DXEXQ, "dxexq", CONST, dfp_dxex_td) + +/* 2 argument DFP (decimal floating point) functions added in ISA 2.05. */ +BU_DFP_MISC_2 (DDEDPD, "ddedpd", CONST, dfp_ddedpd_dd) +BU_DFP_MISC_2 (DDEDPDQ, "ddedpdq", CONST, dfp_ddedpd_td) +BU_DFP_MISC_2 (DENBCD, "denbcd", CONST, dfp_denbcd_dd) +BU_DFP_MISC_2 (DENBCDQ, "denbcdq", CONST, dfp_denbcd_td) +BU_DFP_MISC_2 (DIEX, "diex", CONST, dfp_diex_dd) +BU_DFP_MISC_2 (DIEXQ, "diexq", CONST, dfp_diex_td) +BU_DFP_MISC_2 (DSCLI, "dscli", CONST, dfp_dscli_dd) +BU_DFP_MISC_2 (DSCLIQ, "dscliq", CONST, dfp_dscli_td) +BU_DFP_MISC_2 (DSCRI, "dscri", CONST, dfp_dscri_dd) +BU_DFP_MISC_2 (DSCRIQ, "dscriq", CONST, dfp_dscri_td) + +/* 1 argument BCD functions added in ISA 2.06. */ +BU_P7_MISC_1 (CDTBCD, "cdtbcd", CONST, cdtbcd) +BU_P7_MISC_1 (CBCDTD, "cbcdtd", CONST, cbcdtd) + +/* 2 argument BCD functions added in ISA 2.06. */ +BU_P7_MISC_2 (ADDG6S, "addg6s", CONST, addg6s) + +/* 3 argument BCD functions added in ISA 2.07. */ +BU_P8V_MISC_3 (BCDADD, "bcdadd", CONST, bcdadd) +BU_P8V_MISC_3 (BCDADD_LT, "bcdadd_lt", CONST, bcdadd_lt) +BU_P8V_MISC_3 (BCDADD_EQ, "bcdadd_eq", CONST, bcdadd_eq) +BU_P8V_MISC_3 (BCDADD_GT, "bcdadd_gt", CONST, bcdadd_gt) +BU_P8V_MISC_3 (BCDADD_OV, "bcdadd_ov", CONST, bcdadd_unordered) +BU_P8V_MISC_3 (BCDSUB, "bcdsub", CONST, bcdsub) +BU_P8V_MISC_3 (BCDSUB_LT, "bcdsub_lt", CONST, bcdsub_lt) +BU_P8V_MISC_3 (BCDSUB_EQ, "bcdsub_eq", CONST, bcdsub_eq) +BU_P8V_MISC_3 (BCDSUB_GT, "bcdsub_gt", CONST, bcdsub_gt) +BU_P8V_MISC_3 (BCDSUB_OV, "bcdsub_ov", CONST, bcdsub_unordered) + +/* 2 argument pack/unpack 128-bit floating point types. */ +BU_DFP_MISC_2 (PACK_TD, "pack_dec128", CONST, packtd) +BU_DFP_MISC_2 (UNPACK_TD, "unpack_dec128", CONST, unpacktd) + +BU_MISC_2 (PACK_TF, "pack_longdouble", CONST, packtf) +BU_MISC_2 (UNPACK_TF, "unpack_longdouble", CONST, unpacktf) +BU_MISC_1 (UNPACK_TF_0, "longdouble_dw0", CONST, unpacktf_0) +BU_MISC_1 (UNPACK_TF_1, "longdouble_dw1", CONST, unpacktf_1) + +BU_P7_MISC_2 (PACK_V1TI, "pack_vector_int128", CONST, packv1ti) +BU_P7_MISC_2 (UNPACK_V1TI, "unpack_vector_int128", CONST, unpackv1ti) + + /* 1 argument crypto functions. */ BU_CRYPTO_1 (VSBOX, "vsbox", CONST, crypto_vsbox) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index bab79df7760..0c983f9a105 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -3038,7 +3038,8 @@ rs6000_builtin_mask_calculate (void) | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL : 0) | ((TARGET_P8_VECTOR) ? RS6000_BTM_P8_VECTOR : 0) | ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0) - | ((TARGET_HTM) ? RS6000_BTM_HTM : 0)); + | ((TARGET_HTM) ? RS6000_BTM_HTM : 0) + | ((TARGET_DFP) ? RS6000_BTM_DFP : 0)); } /* Override command line options. Mostly we process the processor type and @@ -12396,7 +12397,15 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target) } } else if (icode == CODE_FOR_vsx_set_v2df - || icode == CODE_FOR_vsx_set_v2di) + || icode == CODE_FOR_vsx_set_v2di + || icode == CODE_FOR_bcdadd + || icode == CODE_FOR_bcdadd_lt + || icode == CODE_FOR_bcdadd_eq + || icode == CODE_FOR_bcdadd_gt + || icode == CODE_FOR_bcdsub + || icode == CODE_FOR_bcdsub_lt + || icode == CODE_FOR_bcdsub_eq + || icode == CODE_FOR_bcdsub_gt) { /* Only allow 1-bit unsigned literals. */ STRIP_NOPS (arg2); @@ -12407,6 +12416,44 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target) return const0_rtx; } } + else if (icode == CODE_FOR_dfp_ddedpd_dd + || icode == CODE_FOR_dfp_ddedpd_td) + { + /* Only allow 2-bit unsigned literals where the value is 0 or 2. */ + STRIP_NOPS (arg0); + if (TREE_CODE (arg0) != INTEGER_CST + || TREE_INT_CST_LOW (arg2) & ~0x3) + { + error ("argument 1 must be 0 or 2"); + return const0_rtx; + } + } + else if (icode == CODE_FOR_dfp_denbcd_dd + || icode == CODE_FOR_dfp_denbcd_td) + { + /* Only allow 1-bit unsigned literals. */ + STRIP_NOPS (arg0); + if (TREE_CODE (arg0) != INTEGER_CST + || TREE_INT_CST_LOW (arg0) & ~0x1) + { + error ("argument 1 must be a 1-bit unsigned literal"); + return const0_rtx; + } + } + else if (icode == CODE_FOR_dfp_dscli_dd + || icode == CODE_FOR_dfp_dscli_td + || icode == CODE_FOR_dfp_dscri_dd + || icode == CODE_FOR_dfp_dscri_td) + { + /* Only allow 6-bit unsigned literals. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST + || TREE_INT_CST_LOW (arg1) & ~0x3f) + { + error ("argument 2 must be a 6-bit unsigned literal"); + return const0_rtx; + } + } else if (icode == CODE_FOR_crypto_vshasigmaw || icode == CODE_FOR_crypto_vshasigmad) { @@ -13496,6 +13543,14 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode) error ("Builtin function %s requires the -mpaired option", name); else if ((fnmask & RS6000_BTM_SPE) != 0) error ("Builtin function %s requires the -mspe option", name); + else if ((fnmask & (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR)) + == (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR)) + error ("Builtin function %s requires the -mhard-dfp and" + "-mpower8-vector options", name); + else if ((fnmask & RS6000_BTM_DFP) != 0) + error ("Builtin function %s requires the -mhard-dfp option", name); + else if ((fnmask & RS6000_BTM_P8_VECTOR) != 0) + error ("Builtin function %s requires the -mpower8-vector option", name); else error ("Builtin function %s is not supported with the current options", name); @@ -13775,6 +13830,9 @@ rs6000_init_builtins (void) uintTI_type_internal_node = unsigned_intTI_type_node; float_type_internal_node = float_type_node; double_type_internal_node = double_type_node; + long_double_type_internal_node = long_double_type_node; + dfloat64_type_internal_node = dfloat64_type_node; + dfloat128_type_internal_node = dfloat128_type_node; void_type_internal_node = void_type_node; /* Initialize the modes for builtin_function_type, mapping a machine mode to @@ -13789,6 +13847,9 @@ rs6000_init_builtins (void) builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node; builtin_mode_to_type[SFmode][0] = float_type_node; builtin_mode_to_type[DFmode][0] = double_type_node; + builtin_mode_to_type[TFmode][0] = long_double_type_node; + builtin_mode_to_type[DDmode][0] = dfloat64_type_node; + builtin_mode_to_type[TDmode][0] = dfloat128_type_node; builtin_mode_to_type[V1TImode][0] = V1TI_type_node; builtin_mode_to_type[V1TImode][1] = unsigned_V1TI_type_node; builtin_mode_to_type[V2SImode][0] = V2SI_type_node; @@ -14881,6 +14942,8 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0, /* unsigned 1 argument functions. */ case CRYPTO_BUILTIN_VSBOX: case P8V_BUILTIN_VGBBD: + case MISC_BUILTIN_CDTBCD: + case MISC_BUILTIN_CBCDTD: h.uns_p[0] = 1; h.uns_p[1] = 1; break; @@ -14899,6 +14962,11 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0, case CRYPTO_BUILTIN_VPMSUMW: case CRYPTO_BUILTIN_VPMSUMD: case CRYPTO_BUILTIN_VPMSUM: + case MISC_BUILTIN_ADDG6S: + case MISC_BUILTIN_DIVWEU: + case MISC_BUILTIN_DIVWEUO: + case MISC_BUILTIN_DIVDEU: + case MISC_BUILTIN_DIVDEUO: h.uns_p[0] = 1; h.uns_p[1] = 1; h.uns_p[2] = 1; @@ -14960,9 +15028,18 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0, /* signed args, unsigned return. */ case VSX_BUILTIN_XVCVDPUXDS_UNS: case ALTIVEC_BUILTIN_FIXUNS_V4SF_V4SI: + case MISC_BUILTIN_UNPACK_TD: + case MISC_BUILTIN_UNPACK_V1TI: h.uns_p[0] = 1; break; + /* unsigned arguments for 128-bit pack instructions. */ + case MISC_BUILTIN_PACK_TD: + case MISC_BUILTIN_PACK_V1TI: + h.uns_p[1] = 1; + h.uns_p[2] = 1; + break; + default: break; } @@ -31226,6 +31303,7 @@ static struct rs6000_opt_mask const rs6000_builtin_mask_names[] = { "power8-vector", RS6000_BTM_P8_VECTOR, false, false }, { "crypto", RS6000_BTM_CRYPTO, false, false }, { "htm", RS6000_BTM_HTM, false, false }, + { "hard-dfp", RS6000_BTM_DFP, false, false }, }; /* Option variables that we want to support inside attribute((target)) and diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 9d0d61c74ea..2e677d5936e 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2516,6 +2516,7 @@ extern int frame_pointer_needed; #define RS6000_BTM_FRSQRTES MASK_POPCNTB /* FRSQRTES instruction. */ #define RS6000_BTM_POPCNTD MASK_POPCNTD /* Target supports ISA 2.06. */ #define RS6000_BTM_CELL MASK_FPRND /* Target is cell powerpc. */ +#define RS6000_BTM_DFP MASK_DFP /* Decimal floating point. */ #define RS6000_BTM_COMMON (RS6000_BTM_ALTIVEC \ | RS6000_BTM_VSX \ @@ -2527,7 +2528,8 @@ extern int frame_pointer_needed; | RS6000_BTM_FRSQRTES \ | RS6000_BTM_HTM \ | RS6000_BTM_POPCNTD \ - | RS6000_BTM_CELL) + | RS6000_BTM_CELL \ + | RS6000_BTM_DFP) /* Define builtin enum index. */ @@ -2622,6 +2624,9 @@ enum rs6000_builtin_type_index RS6000_BTI_UINTTI, /* unsigned_intTI_type_node */ RS6000_BTI_float, /* float_type_node */ RS6000_BTI_double, /* double_type_node */ + RS6000_BTI_long_double, /* long_double_type_node */ + RS6000_BTI_dfloat64, /* dfloat64_type_node */ + RS6000_BTI_dfloat128, /* dfloat128_type_node */ RS6000_BTI_void, /* void_type_node */ RS6000_BTI_MAX }; @@ -2673,6 +2678,9 @@ enum rs6000_builtin_type_index #define uintTI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTTI]) #define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float]) #define double_type_internal_node (rs6000_builtin_types[RS6000_BTI_double]) +#define long_double_type_internal_node (rs6000_builtin_types[RS6000_BTI_long_double]) +#define dfloat64_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat64]) +#define dfloat128_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat128]) #define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void]) extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX]; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index cdefc8f78c4..937eabf3727 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -125,6 +125,15 @@ UNSPEC_P8V_MTVSRD UNSPEC_P8V_XXPERMDI UNSPEC_P8V_RELOAD_FROM_VSX + UNSPEC_ADDG6S + UNSPEC_CDTBCD + UNSPEC_CBCDTD + UNSPEC_DIVE + UNSPEC_DIVEO + UNSPEC_DIVEU + UNSPEC_DIVEUO + UNSPEC_UNPACK_128BIT + UNSPEC_PACK_128BIT ]) ;; @@ -481,6 +490,10 @@ (V2DF "X,X,X,X,X") (V1TI "X,X,X,X,X")]) +;; Mode attribute to give the correct type for integer divides +(define_mode_attr idiv_ldiv [(SI "idiv") + (DI "ldiv")]) + ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. @@ -2755,10 +2768,7 @@ (match_operand:GPR 2 "gpc_reg_operand" "r")))] "" "div<wd>u %0,%1,%2" - [(set (attr "type") - (cond [(match_operand:SI 0 "" "") - (const_string "idiv")] - (const_string "ldiv")))]) + [(set_attr "type" "<idiv_ldiv>")]) ;; For powers of two we can do srai/aze for divide and then adjust for @@ -2782,10 +2792,7 @@ (match_operand:GPR 2 "gpc_reg_operand" "r")))] "" "div<wd> %0,%1,%2" - [(set (attr "type") - (cond [(match_operand:SI 0 "" "") - (const_string "idiv")] - (const_string "ldiv")))]) + [(set_attr "type" "<idiv_ldiv>")]) (define_expand "mod<mode>3" [(use (match_operand:GPR 0 "gpc_reg_operand" "")) @@ -15735,6 +15742,191 @@ }) +;; Miscellaneous ISA 2.06 (power7) instructions +(define_insn "addg6s" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r")] + UNSPEC_ADDG6S))] + "TARGET_POPCNTD" + "addg6s %0,%1,%2" + [(set_attr "type" "integer") + (set_attr "length" "4")]) + +(define_insn "cdtbcd" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r")] + UNSPEC_CDTBCD))] + "TARGET_POPCNTD" + "cdtbcd %0,%1" + [(set_attr "type" "integer") + (set_attr "length" "4")]) + +(define_insn "cbcdtd" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r")] + UNSPEC_CBCDTD))] + "TARGET_POPCNTD" + "cbcdtd %0,%1" + [(set_attr "type" "integer") + (set_attr "length" "4")]) + +(define_int_iterator UNSPEC_DIV_EXTEND [UNSPEC_DIVE + UNSPEC_DIVEO + UNSPEC_DIVEU + UNSPEC_DIVEUO]) + +(define_int_attr div_extend [(UNSPEC_DIVE "e") + (UNSPEC_DIVEO "eo") + (UNSPEC_DIVEU "eu") + (UNSPEC_DIVEUO "euo")]) + +(define_insn "div<div_extend>_<mode>" + [(set (match_operand:GPR 0 "register_operand" "=r") + (unspec:GPR [(match_operand:GPR 1 "register_operand" "r") + (match_operand:GPR 2 "register_operand" "r")] + UNSPEC_DIV_EXTEND))] + "TARGET_POPCNTD" + "div<wd><div_extend> %0,%1,%2" + [(set_attr "type" "<idiv_ldiv>")]) + + +;; Pack/unpack 128-bit floating point types that take 2 scalar registers + +; Type of the 64-bit part when packing/unpacking 128-bit floating point types +(define_mode_attr FP128_64 [(TF "DF") (TD "DI")]) + +(define_expand "unpack<mode>" + [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "") + (unspec:<FP128_64> + [(match_operand:FMOVE128 1 "register_operand" "") + (match_operand:QI 2 "const_0_to_1_operand" "")] + UNSPEC_UNPACK_128BIT))] + "" + "") + +;; The Advance Toolchain 7.0-3 added private builtins: __builtin_longdouble_dw0 +;; and __builtin_longdouble_dw1 to optimize glibc. Add support for these +;; builtins here. + +(define_expand "unpacktf_0" + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (unspec:DF [(match_operand:TF 1 "register_operand" "") + (const_int 0)] + UNSPEC_UNPACK_128BIT))] + "" + "") + +(define_expand "unpacktf_1" + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (unspec:DF [(match_operand:TF 1 "register_operand" "") + (const_int 1)] + UNSPEC_UNPACK_128BIT))] + "" + "") + +(define_insn_and_split "unpack<mode>_dm" + [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m,d,r,m") + (unspec:<FP128_64> + [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r") + (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")] + UNSPEC_UNPACK_128BIT))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 3))] +{ + unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]); + + if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno) + { + emit_note (NOTE_INSN_DELETED); + DONE; + } + + operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno); +} + [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store") + (set_attr "length" "4")]) + +(define_insn_and_split "unpack<mode>_nodm" + [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m") + (unspec:<FP128_64> + [(match_operand:FMOVE128 1 "register_operand" "d,d") + (match_operand:QI 2 "const_0_to_1_operand" "i,i")] + UNSPEC_UNPACK_128BIT))] + "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 3))] +{ + unsigned fp_regno = REGNO (operands[1]) + UINTVAL (operands[2]); + + if (REG_P (operands[0]) && REGNO (operands[0]) == fp_regno) + { + emit_note (NOTE_INSN_DELETED); + DONE; + } + + operands[3] = gen_rtx_REG (<FP128_64>mode, fp_regno); +} + [(set_attr "type" "fp,fpstore") + (set_attr "length" "4")]) + +(define_insn_and_split "pack<mode>" + [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d") + (unspec:FMOVE128 + [(match_operand:<FP128_64> 1 "register_operand" "0,d") + (match_operand:<FP128_64> 2 "register_operand" "d,d")] + UNSPEC_PACK_128BIT))] + "" + "@ + fmr %L0,%2 + #" + "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])" + [(set (match_dup 3) (match_dup 1)) + (set (match_dup 4) (match_dup 2))] +{ + unsigned dest_hi = REGNO (operands[0]); + unsigned dest_lo = dest_hi + 1; + + gcc_assert (!IN_RANGE (REGNO (operands[1]), dest_hi, dest_lo)); + gcc_assert (!IN_RANGE (REGNO (operands[2]), dest_hi, dest_lo)); + + operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi); + operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo); +} + [(set_attr "type" "fp,fp") + (set_attr "length" "4,8")]) + +(define_insn "unpackv1ti" + [(set (match_operand:DI 0 "register_operand" "=d,d") + (unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa") + (match_operand:QI 2 "const_0_to_1_operand" "O,i")] + UNSPEC_UNPACK_128BIT))] + "TARGET_VSX" +{ + if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0) + return ASM_COMMENT_START " xxpermdi to same register"; + + operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3); + return "xxpermdi %x0,%x1,%x1,%3"; +} + [(set_attr "type" "vecperm") + (set_attr "length" "4")]) + +(define_insn "packv1ti" + [(set (match_operand:V1TI 0 "register_operand" "=wa") + (unspec:V1TI + [(match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "register_operand" "d")] + UNSPEC_PACK_128BIT))] + "TARGET_VSX" + "xxpermdi %x0,%x1,%x2,0" + [(set_attr "type" "vecperm") + (set_attr "length" "4")]) + + (include "sync.md") (include "vector.md") diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index 2a657db59c1..a21c953b035 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -115,7 +115,6 @@ along with GCC; see the file COPYING3. If not see #define LIB_SPEC \ "%{!symbolic:\ %{pthreads|pthread:-lpthread} \ - %{pthreads|pthread|fprofile-generate*:" LIB_TLS_SPEC "} \ %{p|pg:-ldl} -lc}" #ifndef CROSS_DIRECTORY_STRUCTURE diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 8b6c647fc00..e2a4669e05d 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -5795,19 +5795,6 @@ } [(set_attr "type" "shift")]) -(define_insn "*ashlsi3_extend" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith_operand" "rI"))))] - "TARGET_ARCH64" -{ - if (GET_CODE (operands[2]) == CONST_INT) - operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return "sll\t%1, %2, %0"; -} - [(set_attr "type" "shift")]) - (define_expand "ashldi3" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (match_operand:DI 1 "register_operand" "r") diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt index c02aec59f06..64e40955a53 100644 --- a/gcc/config/sparc/sparc.opt +++ b/gcc/config/sparc/sparc.opt @@ -113,6 +113,10 @@ mrelax Target Optimize tail call instructions in assembler and linker +muser-mode +Target Report Mask(USER_MODE) +Do not generate code that can only run in supervisor mode + mcpu= Target RejectNegative Joined Var(sparc_cpu_and_features) Enum(sparc_processor_type) Init(PROCESSOR_V7) Use features of and schedule code for given CPU diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md index fd5691f73be..e6e237f256f 100644 --- a/gcc/config/sparc/sync.md +++ b/gcc/config/sparc/sync.md @@ -200,10 +200,27 @@ [(match_operand:I48MODE 2 "register_operand" "r") (match_operand:I48MODE 3 "register_operand" "0")] UNSPECV_CAS))] - "(TARGET_V9 || TARGET_LEON3) && (<MODE>mode != DImode || TARGET_ARCH64)" + "TARGET_V9 && (<MODE>mode != DImode || TARGET_ARCH64)" "cas<modesuffix>\t%1, %2, %0" [(set_attr "type" "multi")]) +(define_insn "*atomic_compare_and_swap_leon3_1" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "mem_noofs_operand" "+w")) + (set (match_dup 1) + (unspec_volatile:SI + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "0")] + UNSPECV_CAS))] + "TARGET_LEON3" +{ + if (TARGET_USER_MODE) + return "casa\t%1 0xa, %2, %0"; /* ASI for user data space. */ + else + return "casa\t%1 0xb, %2, %0"; /* ASI for supervisor data space. */ +} + [(set_attr "type" "multi")]) + (define_insn "*atomic_compare_and_swapdi_v8plus" [(set (match_operand:DI 0 "register_operand" "=h") (match_operand:DI 1 "mem_noofs_operand" "+w")) diff --git a/gcc/configure b/gcc/configure index 813ccce2257..d912261c1cf 100755 --- a/gcc/configure +++ b/gcc/configure @@ -882,6 +882,7 @@ enable_werror_always enable_checking enable_coverage enable_gather_detailed_mem_stats +enable_valgrind_annotations with_stabs enable_multilib enable_multiarch @@ -1591,6 +1592,8 @@ Optional Features: Values are opt, noopt, default is noopt --enable-gather-detailed-mem-stats enable detailed memory allocation stats gathering + --enable-valgrind-annotations + enable valgrind runtime interaction --enable-multilib enable library support for multiple ABIs --enable-multiarch enable support for multiarch paths --enable-__cxa_atexit enable __cxa_atexit for C++ @@ -6772,12 +6775,11 @@ fi -if test x$ac_valgrind_checking != x ; then - # It is certainly possible that there's valgrind but no valgrind.h. - # GCC relies on making annotations so we must have both. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5 +# It is certainly possible that there's valgrind but no valgrind.h. +# GCC relies on making annotations so we must have both. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5 $as_echo_n "checking for VALGRIND_DISCARD in <valgrind/memcheck.h>... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <valgrind/memcheck.h> #ifndef VALGRIND_DISCARD @@ -6790,11 +6792,11 @@ else gcc_cv_header_valgrind_memcheck_h=no fi rm -f conftest.err conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_valgrind_memcheck_h" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_valgrind_memcheck_h" >&5 $as_echo "$gcc_cv_header_valgrind_memcheck_h" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <memcheck.h>" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <memcheck.h>" >&5 $as_echo_n "checking for VALGRIND_DISCARD in <memcheck.h>... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <memcheck.h> #ifndef VALGRIND_DISCARD @@ -6807,8 +6809,20 @@ else gcc_cv_header_memcheck_h=no fi rm -f conftest.err conftest.$ac_ext - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_memcheck_h" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_memcheck_h" >&5 $as_echo "$gcc_cv_header_memcheck_h" >&6; } +if test $gcc_cv_header_valgrind_memcheck_h = yes; then + +$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h + +fi +if test $gcc_cv_header_memcheck_h = yes; then + +$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h + +fi + +if test x$ac_valgrind_checking != x ; then # Prepare PATH_SEPARATOR. # The user is always right. @@ -6887,16 +6901,6 @@ fi $as_echo "#define ENABLE_VALGRIND_CHECKING 1" >>confdefs.h - if test $gcc_cv_header_valgrind_memcheck_h = yes; then - -$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h - - fi - if test $gcc_cv_header_memcheck_h = yes; then - -$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h - - fi fi @@ -6939,6 +6943,25 @@ cat >>confdefs.h <<_ACEOF _ACEOF +# Check whether --enable-valgrind-annotations was given. +if test "${enable_valgrind_annotations+set}" = set; then : + enableval=$enable_valgrind_annotations; +else + enable_valgrind_annotations=no +fi + +if test x$enable_valgrind_annotations != xno \ + || test x$ac_valgrind_checking != x; then + if (test $have_valgrind_h = no \ + && test $gcc_cv_header_memcheck_h = no \ + && test $gcc_cv_header_valgrind_memcheck_h = no); then + as_fn_error "*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5 + fi + +$as_echo "#define ENABLE_VALGRIND_ANNOTATIONS 1" >>confdefs.h + +fi + # ------------------------------- # Miscenalleous configure options # ------------------------------- @@ -17971,7 +17994,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 17974 "configure" +#line 17997 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18077,7 +18100,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18080 "configure" +#line 18103 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -23306,13 +23329,8 @@ foo: .long 25 ;; i[34567]86-*-* | x86_64-*-*) case "$target" in - i[34567]86-*-solaris2.*) - on_solaris=yes - tga_func=___tls_get_addr - ;; - x86_64-*-solaris2.1[0-9]*) + i[34567]86-*-solaris2.* | x86_64-*-solaris2.1[0-9]*) on_solaris=yes - tga_func=__tls_get_addr ;; *) on_solaris=no @@ -23587,7 +23605,6 @@ foo: .long 25 case "$target" in sparc*-sun-solaris2.*) on_solaris=yes - tga_func=__tls_get_addr ;; *) on_solaris=no @@ -23711,101 +23728,6 @@ if test $gcc_cv_as_tls = yes; then set_have_as_tls=yes fi fi -case "$target" in - # TLS was introduced in the Solaris 9 FCS release. Support for GNU-style - # TLS on x86 was only introduced in Solaris 9 4/04, replacing the earlier - # Sun style that Sun ld and GCC don't support any longer. - *-*-solaris2.*) - ld_tls_support=yes - - save_LIBS="$LIBS" - save_LDFLAGS="$LDFLAGS" - LIBS= - LDFLAGS= - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking library containing $tga_func" >&5 -$as_echo_n "checking library containing $tga_func... " >&6; } - # Before Solaris 10, __tls_get_addr (SPARC/x64) resp. ___tls_get_addr - # (32-bit x86) only lived in libthread, so check for that. Keep - # set_have_as_tls if found, disable if not. - as_ac_Search=`$as_echo "ac_cv_search_$tga_func" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing $tga_func" >&5 -$as_echo_n "checking for library containing $tga_func... " >&6; } -if { as_var=$as_ac_Search; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $tga_func (); -int -main () -{ -return $tga_func (); - ; - return 0; -} -_ACEOF -for ac_lib in '' thread; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Search=\$ac_res" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if { as_var=$as_ac_Search; eval "test \"\${$as_var+set}\" = set"; }; then : - break -fi -done -if { as_var=$as_ac_Search; eval "test \"\${$as_var+set}\" = set"; }; then : - -else - eval "$as_ac_Search=no" -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -eval ac_res=\$$as_ac_Search - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -eval ac_res=\$$as_ac_Search -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -else - set_have_as_tls=no -fi - - ld_tls_libs="$LIBS" - # Clear LIBS if we cannot support TLS. - if test $set_have_as_tls = no; then - LIBS= - fi - # Always define LIB_TLS_SPEC, even without TLS support. - -cat >>confdefs.h <<_ACEOF -#define LIB_TLS_SPEC "$LIBS" -_ACEOF - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBS" >&5 -$as_echo "$LIBS" >&6; } - - LIBS="$save_LIBS" - LDFLAGS="$save_LDFLAGS" - ;; -esac if test $set_have_as_tls = yes ; then $as_echo "#define HAVE_AS_TLS 1" >>confdefs.h @@ -24496,7 +24418,7 @@ else .align 4 smac %g2, %g3, %g1 umac %g2, %g3, %g1 - cas [%g2], %g3, %g1' > conftest.s + casa [%g2] 0xb, %g3, %g1' > conftest.s if { ac_try='$gcc_cv_as $gcc_cv_as_flags -Aleon -o conftest.o conftest.s >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 (eval $ac_try) 2>&5 diff --git a/gcc/configure.ac b/gcc/configure.ac index 1235501bd49..5565524c89a 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -514,27 +514,36 @@ dnl # an if statement. This was the source of very frustrating bugs dnl # in converting to autoconf 2.5x! AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no) -if test x$ac_valgrind_checking != x ; then - # It is certainly possible that there's valgrind but no valgrind.h. - # GCC relies on making annotations so we must have both. - AC_MSG_CHECKING(for VALGRIND_DISCARD in <valgrind/memcheck.h>) - AC_PREPROC_IFELSE([AC_LANG_SOURCE( - [[#include <valgrind/memcheck.h> +# It is certainly possible that there's valgrind but no valgrind.h. +# GCC relies on making annotations so we must have both. +AC_MSG_CHECKING(for VALGRIND_DISCARD in <valgrind/memcheck.h>) +AC_PREPROC_IFELSE([AC_LANG_SOURCE( + [[#include <valgrind/memcheck.h> #ifndef VALGRIND_DISCARD #error VALGRIND_DISCARD not defined #endif]])], [gcc_cv_header_valgrind_memcheck_h=yes], [gcc_cv_header_valgrind_memcheck_h=no]) - AC_MSG_RESULT($gcc_cv_header_valgrind_memcheck_h) - AC_MSG_CHECKING(for VALGRIND_DISCARD in <memcheck.h>) - AC_PREPROC_IFELSE([AC_LANG_SOURCE( - [[#include <memcheck.h> +AC_MSG_RESULT($gcc_cv_header_valgrind_memcheck_h) +AC_MSG_CHECKING(for VALGRIND_DISCARD in <memcheck.h>) +AC_PREPROC_IFELSE([AC_LANG_SOURCE( + [[#include <memcheck.h> #ifndef VALGRIND_DISCARD #error VALGRIND_DISCARD not defined #endif]])], [gcc_cv_header_memcheck_h=yes], [gcc_cv_header_memcheck_h=no]) - AC_MSG_RESULT($gcc_cv_header_memcheck_h) +AC_MSG_RESULT($gcc_cv_header_memcheck_h) +if test $gcc_cv_header_valgrind_memcheck_h = yes; then + AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1, + [Define if valgrind's valgrind/memcheck.h header is installed.]) +fi +if test $gcc_cv_header_memcheck_h = yes; then + AC_DEFINE(HAVE_MEMCHECK_H, 1, + [Define if valgrind's memcheck.h header is installed.]) +fi + +if test x$ac_valgrind_checking != x ; then AM_PATH_PROG_WITH_TEST(valgrind_path, valgrind, [$ac_dir/$ac_word --version | grep valgrind- >/dev/null 2>&1]) if test "x$valgrind_path" = "x" \ @@ -548,14 +557,6 @@ if test x$ac_valgrind_checking != x ; then AC_DEFINE(ENABLE_VALGRIND_CHECKING, 1, [Define if you want to run subprograms and generated programs through valgrind (a memory checker). This is extremely expensive.]) - if test $gcc_cv_header_valgrind_memcheck_h = yes; then - AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1, - [Define if valgrind's valgrind/memcheck.h header is installed.]) - fi - if test $gcc_cv_header_memcheck_h = yes; then - AC_DEFINE(HAVE_MEMCHECK_H, 1, - [Define if valgrind's memcheck.h header is installed.]) - fi fi AC_SUBST(valgrind_path_defines) AC_SUBST(valgrind_command) @@ -594,6 +595,21 @@ gather_stats=`if test $enable_gather_detailed_mem_stats != no; then echo 1; else AC_DEFINE_UNQUOTED(GATHER_STATISTICS, $gather_stats, [Define to enable detailed memory allocation stats gathering.]) +AC_ARG_ENABLE(valgrind-annotations, +[AS_HELP_STRING([--enable-valgrind-annotations], + [enable valgrind runtime interaction])], [], +[enable_valgrind_annotations=no]) +if test x$enable_valgrind_annotations != xno \ + || test x$ac_valgrind_checking != x; then + if (test $have_valgrind_h = no \ + && test $gcc_cv_header_memcheck_h = no \ + && test $gcc_cv_header_valgrind_memcheck_h = no); then + AC_MSG_ERROR([*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h]) + fi + AC_DEFINE(ENABLE_VALGRIND_ANNOTATIONS, 1, +[Define to get calls to the valgrind runtime enabled.]) +fi + # ------------------------------- # Miscenalleous configure options # ------------------------------- @@ -2935,13 +2951,8 @@ foo: .long 25 ;; i[34567]86-*-* | x86_64-*-*) case "$target" in - i[34567]86-*-solaris2.*) - on_solaris=yes - tga_func=___tls_get_addr - ;; - x86_64-*-solaris2.1[0-9]*) + i[34567]86-*-solaris2.* | x86_64-*-solaris2.1[0-9]*) on_solaris=yes - tga_func=__tls_get_addr ;; *) on_solaris=no @@ -3217,7 +3228,6 @@ foo: .long 25 case "$target" in sparc*-sun-solaris2.*) on_solaris=yes - tga_func=__tls_get_addr ;; *) on_solaris=no @@ -3313,37 +3323,6 @@ else [$tls_first_major,$tls_first_minor,0], [$tls_as_opt], [$conftest_s],, [set_have_as_tls=yes]) fi -case "$target" in - # TLS was introduced in the Solaris 9 FCS release. Support for GNU-style - # TLS on x86 was only introduced in Solaris 9 4/04, replacing the earlier - # Sun style that Sun ld and GCC don't support any longer. - *-*-solaris2.*) - ld_tls_support=yes - - save_LIBS="$LIBS" - save_LDFLAGS="$LDFLAGS" - LIBS= - LDFLAGS= - - AC_MSG_CHECKING(library containing $tga_func) - # Before Solaris 10, __tls_get_addr (SPARC/x64) resp. ___tls_get_addr - # (32-bit x86) only lived in libthread, so check for that. Keep - # set_have_as_tls if found, disable if not. - AC_SEARCH_LIBS([$tga_func], [thread],, [set_have_as_tls=no]) - ld_tls_libs="$LIBS" - # Clear LIBS if we cannot support TLS. - if test $set_have_as_tls = no; then - LIBS= - fi - # Always define LIB_TLS_SPEC, even without TLS support. - AC_DEFINE_UNQUOTED(LIB_TLS_SPEC, "$LIBS", - [Define to the library containing __tls_get_addr/___tls_get_addr.]) - AC_MSG_RESULT($LIBS) - - LIBS="$save_LIBS" - LDFLAGS="$save_LDFLAGS" - ;; -esac if test $set_have_as_tls = yes ; then AC_DEFINE(HAVE_AS_TLS, 1, [Define if your assembler and linker support thread-local storage.]) @@ -3684,7 +3663,7 @@ foo: .align 4 smac %g2, %g3, %g1 umac %g2, %g3, %g1 - cas [[%g2]], %g3, %g1],, + casa [[%g2]] 0xb, %g3, %g1],, [AC_DEFINE(HAVE_AS_LEON, 1, [Define if your assembler supports LEON instructions.])]) ;; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ae213426553..a5f3829d705 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2014-04-28 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/59120 + * parser.c (cp_parser_alias_declaration): Check return value of + cp_parser_require. + +2014-04-24 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_atomic): Allow seq_cst before + atomic-clause, allow comma in between atomic-clause and + seq_cst. + 2014-04-24 Marc Glisse <marc.glisse@inria.fr> PR libstdc++/43622 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4e6a2b88f32..962cacedf80 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -16142,15 +16142,8 @@ cp_parser_alias_declaration (cp_parser* parser) if (parser->num_template_parameter_lists) parser->type_definition_forbidden_message = saved_message; - if (type == error_mark_node) - { - cp_parser_skip_to_end_of_block_or_statement (parser); - return error_mark_node; - } - - cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); - - if (cp_parser_error_occurred (parser)) + if (type == error_mark_node + || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) { cp_parser_skip_to_end_of_block_or_statement (parser); return error_mark_node; @@ -28534,6 +28527,20 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok) tree id = cp_lexer_peek_token (parser->lexer)->u.value; const char *p = IDENTIFIER_POINTER (id); + if (!strcmp (p, "seq_cst")) + { + seq_cst = true; + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME) + cp_lexer_consume_token (parser->lexer); + } + } + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + if (!strcmp (p, "read")) code = OMP_ATOMIC_READ; else if (!strcmp (p, "write")) @@ -28547,16 +28554,22 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok) if (p) cp_lexer_consume_token (parser->lexer); } - - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + if (!seq_cst) { - tree id = cp_lexer_peek_token (parser->lexer)->u.value; - const char *p = IDENTIFIER_POINTER (id); + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME) + cp_lexer_consume_token (parser->lexer); - if (!strcmp (p, "seq_cst")) + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { - seq_cst = true; - cp_lexer_consume_token (parser->lexer); + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + + if (!strcmp (p, "seq_cst")) + { + seq_cst = true; + cp_lexer_consume_token (parser->lexer); + } } } cp_parser_require_pragma_eol (parser, pragma_tok); diff --git a/gcc/cselib.c b/gcc/cselib.c index c55b02772ed..00a04baab6e 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -49,9 +49,6 @@ struct elt_list { cselib_val *elt; }; -/* See the documentation of cselib_find_slot below. */ -static enum machine_mode find_slot_memmode; - static bool cselib_record_memory; static bool cselib_preserve_constants; static bool cselib_any_perm_equivs; @@ -94,7 +91,14 @@ static rtx cselib_expand_value_rtx_1 (rtx, struct expand_value_data *, int); struct cselib_hasher : typed_noop_remove <cselib_val> { typedef cselib_val value_type; - typedef rtx_def compare_type; + struct compare_type { + /* The rtx value and its mode (needed separately for constant + integers). */ + enum machine_mode mode; + rtx x; + /* The mode of the contaning MEM, if any, otherwise VOIDmode. */ + enum machine_mode memmode; + }; static inline hashval_t hash (const value_type *); static inline bool equal (const value_type *, const compare_type *); }; @@ -118,27 +122,20 @@ inline bool cselib_hasher::equal (const value_type *v, const compare_type *x_arg) { struct elt_loc_list *l; - rtx x = CONST_CAST_RTX (x_arg); - enum machine_mode mode = GET_MODE (x); - - gcc_assert (!CONST_SCALAR_INT_P (x) && GET_CODE (x) != CONST_FIXED); + rtx x = x_arg->x; + enum machine_mode mode = x_arg->mode; + enum machine_mode memmode = x_arg->memmode; if (mode != GET_MODE (v->val_rtx)) return false; - /* Unwrap X if necessary. */ - if (GET_CODE (x) == CONST - && (CONST_SCALAR_INT_P (XEXP (x, 0)) - || GET_CODE (XEXP (x, 0)) == CONST_FIXED)) - x = XEXP (x, 0); - if (GET_CODE (x) == VALUE) return x == v->val_rtx; /* We don't guarantee that distinct rtx's have different hash values, so we need to do a comparison. */ for (l = v->locs; l; l = l->next) - if (rtx_equal_for_cselib_1 (l->loc, x, find_slot_memmode)) + if (rtx_equal_for_cselib_1 (l->loc, x, memmode)) { promote_debug_loc (l); return true; @@ -498,8 +495,11 @@ preserve_constants_and_equivs (cselib_val **x, void *info ATTRIBUTE_UNUSED) if (invariant_or_equiv_p (v)) { + cselib_hasher::compare_type lookup = { + GET_MODE (v->val_rtx), v->val_rtx, VOIDmode + }; cselib_val **slot - = cselib_preserved_hash_table.find_slot_with_hash (v->val_rtx, + = cselib_preserved_hash_table.find_slot_with_hash (&lookup, v->hash, INSERT); gcc_assert (!*slot); *slot = v; @@ -572,22 +572,19 @@ cselib_get_next_uid (void) /* Search for X, whose hashcode is HASH, in CSELIB_HASH_TABLE, INSERTing if requested. When X is part of the address of a MEM, - MEMMODE should specify the mode of the MEM. While searching the - table, MEMMODE is held in FIND_SLOT_MEMMODE, so that autoinc RTXs - in X can be resolved. */ + MEMMODE should specify the mode of the MEM. */ static cselib_val ** -cselib_find_slot (rtx x, hashval_t hash, enum insert_option insert, - enum machine_mode memmode) +cselib_find_slot (enum machine_mode mode, rtx x, hashval_t hash, + enum insert_option insert, enum machine_mode memmode) { cselib_val **slot = NULL; - find_slot_memmode = memmode; + cselib_hasher::compare_type lookup = { mode, x, memmode }; if (cselib_preserve_constants) - slot = cselib_preserved_hash_table.find_slot_with_hash (x, hash, + slot = cselib_preserved_hash_table.find_slot_with_hash (&lookup, hash, NO_INSERT); if (!slot) - slot = cselib_hash_table.find_slot_with_hash (x, hash, insert); - find_slot_memmode = VOIDmode; + slot = cselib_hash_table.find_slot_with_hash (&lookup, hash, insert); return slot; } @@ -1041,18 +1038,6 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, enum machine_mode memmode) return 1; } -/* We need to pass down the mode of constants through the hash table - functions. For that purpose, wrap them in a CONST of the appropriate - mode. */ -static rtx -wrap_constant (enum machine_mode mode, rtx x) -{ - if (!CONST_SCALAR_INT_P (x) && GET_CODE (x) != CONST_FIXED) - return x; - gcc_assert (mode != VOIDmode); - return gen_rtx_CONST (mode, x); -} - /* Hash an rtx. Return 0 if we couldn't hash the rtx. For registers and memory locations, we look up their cselib_val structure and return its VALUE element. @@ -1411,8 +1396,7 @@ cselib_lookup_mem (rtx x, int create) mem_elt = new_cselib_val (next_uid, mode, x); add_mem_for_addr (addr, mem_elt, x); - slot = cselib_find_slot (wrap_constant (mode, x), mem_elt->hash, - INSERT, mode); + slot = cselib_find_slot (mode, x, mem_elt->hash, INSERT, VOIDmode); *slot = mem_elt; return mem_elt; } @@ -2068,7 +2052,7 @@ cselib_lookup_1 (rtx x, enum machine_mode mode, } } REG_VALUES (i)->next = new_elt_list (REG_VALUES (i)->next, e); - slot = cselib_find_slot (x, e->hash, INSERT, memmode); + slot = cselib_find_slot (mode, x, e->hash, INSERT, memmode); *slot = e; return e; } @@ -2081,7 +2065,7 @@ cselib_lookup_1 (rtx x, enum machine_mode mode, if (! hashval) return 0; - slot = cselib_find_slot (wrap_constant (mode, x), hashval, + slot = cselib_find_slot (mode, x, hashval, create ? INSERT : NO_INSERT, memmode); if (slot == 0) return 0; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 347a94a3aee..9780d923804 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -12787,9 +12787,12 @@ float __builtin_recipdivf (float, float); float __builtin_rsqrtf (float); double __builtin_recipdiv (double, double); double __builtin_rsqrt (double); -long __builtin_bpermd (long, long); uint64_t __builtin_ppc_get_timebase (); unsigned long __builtin_ppc_mftb (); +double __builtin_unpack_longdouble (long double, int); +double __builtin_longdouble_dw0 (long double); +double __builtin_longdouble_dw1 (long double); +long double __builtin_pack_longdouble (double, double); @end smallexample The @code{vec_rsqrt}, @code{__builtin_rsqrt}, and @@ -12809,6 +12812,57 @@ The @code{__builtin_ppc_mftb} function always generates one instruction and returns the Time Base Register value as an unsigned long, throwing away the most significant word on 32-bit environments. +The following built-in functions are available for the PowerPC family +of processors, starting with ISA 2.06 or later (@option{-mcpu=power7} +or @option{-mpopcntd}): +@smallexample +long __builtin_bpermd (long, long); +int __builtin_divwe (int, int); +int __builtin_divweo (int, int); +unsigned int __builtin_divweu (unsigned int, unsigned int); +unsigned int __builtin_divweuo (unsigned int, unsigned int); +long __builtin_divde (long, long); +long __builtin_divdeo (long, long); +unsigned long __builtin_divdeu (unsigned long, unsigned long); +unsigned long __builtin_divdeuo (unsigned long, unsigned long); +unsigned int cdtbcd (unsigned int); +unsigned int cbcdtd (unsigned int); +unsigned int addg6s (unsigned int, unsigned int); +@end smallexample + +The @code{__builtin_divde}, @code{__builtin_divdeo}, +@code{__builitin_divdeu}, @code{__builtin_divdeou} functions require a +64-bit environment support ISA 2.06 or later. + +The following built-in functions are available for the PowerPC family +of processors when hardware decimal floating point +(@option{-mhard-dfp}) is available: +@smallexample +_Decimal64 __builtin_dxex (_Decimal64); +_Decimal128 __builtin_dxexq (_Decimal128); +_Decimal64 __builtin_ddedpd (int, _Decimal64); +_Decimal128 __builtin_ddedpdq (int, _Decimal128); +_Decimal64 __builtin_denbcd (int, _Decimal64); +_Decimal128 __builtin_denbcdq (int, _Decimal128); +_Decimal64 __builtin_diex (_Decimal64, _Decimal64); +_Decimal128 _builtin_diexq (_Decimal128, _Decimal128); +_Decimal64 __builtin_dscli (_Decimal64, int); +_Decimal128 __builitn_dscliq (_Decimal128, int); +_Decimal64 __builtin_dscri (_Decimal64, int); +_Decimal128 __builitn_dscriq (_Decimal128, int); +unsigned long long __builtin_unpack_dec128 (_Decimal128, int); +_Decimal128 __builtin_pack_dec128 (unsigned long long, unsigned long long); +@end smallexample + +The following built-in functions are available for the PowerPC family +of processors when the Vector Scalar (vsx) instruction set is +available: +@smallexample +unsigned long long __builtin_unpack_vector_int128 (vector __int128_t, int); +vector __int128_t __builtin_pack_vector_int128 (unsigned long long, + unsigned long long); +@end smallexample + @node PowerPC AltiVec/VSX Built-in Functions @subsection PowerPC AltiVec Built-in Functions @@ -15220,6 +15274,17 @@ vector __uint128_t vec_vsubcuq (vector __uint128_t, vector __uint128_t); __int128_t vec_vsubuqm (__int128_t, __int128_t); __uint128_t vec_vsubuqm (__uint128_t, __uint128_t); + +vector __int128_t __builtin_bcdadd (vector __int128_t, vector__int128_t); +int __builtin_bcdadd_lt (vector __int128_t, vector__int128_t); +int __builtin_bcdadd_eq (vector __int128_t, vector__int128_t); +int __builtin_bcdadd_gt (vector __int128_t, vector__int128_t); +int __builtin_bcdadd_ov (vector __int128_t, vector__int128_t); +vector __int128_t bcdsub (vector __int128_t, vector__int128_t); +int __builtin_bcdsub_lt (vector __int128_t, vector__int128_t); +int __builtin_bcdsub_eq (vector __int128_t, vector__int128_t); +int __builtin_bcdsub_gt (vector __int128_t, vector__int128_t); +int __builtin_bcdsub_ov (vector __int128_t, vector__int128_t); @end smallexample If the cryptographic instructions are enabled (@option{-mcrypto} or diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 0b2b3657577..7851b0061b3 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -2544,8 +2544,7 @@ Finally a @code{stagefeedback} compiler is built using the information collected Unlike standard bootstrap, several additional restrictions apply. The compiler used to build @code{stage1} needs to support a 64-bit integral type. -It is recommended to only use GCC for this. Also parallel make is currently -not supported since collisions in profile collecting may occur. +It is recommended to only use GCC for this. @html <hr /> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ff43f262323..da7a00ed00c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -993,6 +993,7 @@ See RS/6000 and PowerPC Options. -mhard-quad-float -msoft-quad-float @gol -mstack-bias -mno-stack-bias @gol -munaligned-doubles -mno-unaligned-doubles @gol +-muser-mode -mno-user-mode @gol -mv8plus -mno-v8plus -mvis -mno-vis @gol -mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol -mcbcond -mno-cbcond @gol @@ -20961,6 +20962,14 @@ Specifying this option avoids some rare compatibility problems with code generated by other compilers. It is not the default because it results in a performance loss, especially for floating-point code. +@item -muser-mode +@itemx -mno-user-mode +@opindex muser-mode +@opindex mno-user-mode +Do not generate code that can only run in supervisor mode. This is relevant +only for the @code{casa} instruction emitted for the LEON3 processor. The +default is @option{-mno-user-mode}. + @item -mno-faster-structs @itemx -mfaster-structs @opindex mno-faster-structs diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 2b2ab5dd831..da0b3f589c9 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -6917,14 +6917,13 @@ should_move_die_to_comdat (dw_die_ref die) case DW_TAG_structure_type: case DW_TAG_enumeration_type: case DW_TAG_union_type: - /* Don't move declarations, inlined instances, or types nested in a - subprogram. */ + /* Don't move declarations, inlined instances, types nested in a + subprogram, or types that contain subprogram definitions. */ if (is_declaration_die (die) || get_AT (die, DW_AT_abstract_origin) - || is_nested_in_subprogram (die)) + || is_nested_in_subprogram (die) + || contains_subprogram_definition (die)) return 0; - /* A type definition should never contain a subprogram definition. */ - gcc_assert (!contains_subprogram_definition (die)); return 1; case DW_TAG_array_type: case DW_TAG_interface_type: @@ -7013,6 +7012,7 @@ clone_as_declaration (dw_die_ref die) switch (a->dw_attr) { + case DW_AT_abstract_origin: case DW_AT_artificial: case DW_AT_containing_type: case DW_AT_external: @@ -7245,6 +7245,12 @@ generate_skeleton_bottom_up (skeleton_chain_node *parent) dw_die_ref clone = clone_die (c); move_all_children (c, clone); + /* If the original has a DW_AT_object_pointer attribute, + it would now point to a child DIE just moved to the + cloned tree, so we need to remove that attribute from + the original. */ + remove_AT (c, DW_AT_object_pointer); + replace_child (c, clone, prev); generate_skeleton_ancestor_tree (parent); add_child_die (parent->new_die, c); @@ -7386,28 +7392,38 @@ break_out_comdat_types (dw_die_ref die) } while (next != NULL); } -/* Like clone_tree, but additionally enter all the children into - the hash table decl_table. */ +/* Like clone_tree, but copy DW_TAG_subprogram DIEs as declarations. + Enter all the cloned children into the hash table decl_table. */ static dw_die_ref -clone_tree_hash (dw_die_ref die, decl_hash_type decl_table) +clone_tree_partial (dw_die_ref die, decl_hash_type decl_table) { dw_die_ref c; - dw_die_ref clone = clone_die (die); + dw_die_ref clone; struct decl_table_entry *entry; - decl_table_entry **slot = decl_table.find_slot_with_hash (die, - htab_hash_pointer (die), INSERT); + decl_table_entry **slot; + + if (die->die_tag == DW_TAG_subprogram) + clone = clone_as_declaration (die); + else + clone = clone_die (die); + + slot = decl_table.find_slot_with_hash (die, + htab_hash_pointer (die), INSERT); + /* Assert that DIE isn't in the hash table yet. If it would be there before, the ancestors would be necessarily there as well, therefore - clone_tree_hash wouldn't be called. */ + clone_tree_partial wouldn't be called. */ gcc_assert (*slot == HTAB_EMPTY_ENTRY); + entry = XCNEW (struct decl_table_entry); entry->orig = die; entry->copy = clone; *slot = entry; - FOR_EACH_CHILD (die, c, - add_child_die (clone, clone_tree_hash (c, decl_table))); + if (die->die_tag != DW_TAG_subprogram) + FOR_EACH_CHILD (die, c, + add_child_die (clone, clone_tree_partial (c, decl_table))); return clone; } @@ -7458,9 +7474,15 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table) entry->copy = copy; *slot = entry; - FOR_EACH_CHILD (targ, c, - add_child_die (copy, - clone_tree_hash (c, decl_table))); + /* If TARG is not a declaration DIE, we need to copy its + children. */ + if (!is_declaration_die (targ)) + { + FOR_EACH_CHILD ( + targ, c, + add_child_die (copy, + clone_tree_partial (c, decl_table))); + } /* Make sure the cloned tree is marked as part of the type unit. */ diff --git a/gcc/expr.c b/gcc/expr.c index fe95ebcbfa0..989a8780dc9 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -2365,6 +2365,18 @@ use_reg_mode (rtx *call_fusage, rtx reg, enum machine_mode mode) = gen_rtx_EXPR_LIST (mode, gen_rtx_USE (VOIDmode, reg), *call_fusage); } +/* Add a CLOBBER expression for REG to the (possibly empty) list pointed + to by CALL_FUSAGE. REG must denote a hard register. */ + +void +clobber_reg_mode (rtx *call_fusage, rtx reg, enum machine_mode mode) +{ + gcc_assert (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER); + + *call_fusage + = gen_rtx_EXPR_LIST (mode, gen_rtx_CLOBBER (VOIDmode, reg), *call_fusage); +} + /* Add USE expressions to *CALL_FUSAGE for each of NREGS consecutive regs, starting at REGNO. All of these registers must be hard registers. */ diff --git a/gcc/expr.h b/gcc/expr.h index 524da6731a9..1823febac26 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -346,6 +346,7 @@ extern void copy_blkmode_from_reg (rtx, rtx, tree); /* Mark REG as holding a parameter for the next CALL_INSN. Mode is TYPE_MODE of the non-promoted parameter, or VOIDmode. */ extern void use_reg_mode (rtx *, rtx, enum machine_mode); +extern void clobber_reg_mode (rtx *, rtx, enum machine_mode); extern rtx copy_blkmode_to_reg (enum machine_mode, tree); @@ -356,6 +357,13 @@ use_reg (rtx *fusage, rtx reg) use_reg_mode (fusage, reg, VOIDmode); } +/* Mark REG as clobbered by the call with FUSAGE as CALL_INSN_FUNCTION_USAGE. */ +static inline void +clobber_reg (rtx *fusage, rtx reg) +{ + clobber_reg_mode (fusage, reg, VOIDmode); +} + /* Mark NREGS consecutive regs, starting at REGNO, as holding parameters for the next CALL_INSN. */ extern void use_regs (rtx *, int, int); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 427c9b15ad8..5cf25134e30 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,23 @@ +2014-03-27 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/59604 + PR fortran/58003 + * gfortran.h (gfc_convert_mpz_to_signed): Add prototype. + * arith.c (gfc_int2int): Convert number to signed if + arithmetic overflow is not checked. + * simplify.c (convert_mpz_to_unsigned): Only trigger assert for + size if range checking is in force. + (convert_mpz_to_signed): Make non-static, rename to + (gfc_convert_mpz_to_signed). + (simplify_dshift): Use gfc_convert_mpz_to_signed. + (gfc_simplify_ibclr): Likewise. + (gfc_simplify_ibits): Likewise. + (gfc_simplify_ibset): Likewise. + (simplify_shift): Likewise. + (gfc_simplify_ishiftc): Likewise. + (gfc_simplify_maskr): Likewise. + (gfc_simplify_maskl): Likewise. + 2014-04-22 Tobias Burnus <burnus@net-b.de> PR fortran/60881 diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c index 053cf765e59..a05fa4907a4 100644 --- a/gcc/fortran/arith.c +++ b/gcc/fortran/arith.c @@ -1976,6 +1976,17 @@ gfc_int2int (gfc_expr *src, int kind) } } + /* If we do not trap numeric overflow, we need to convert the number to + signed, throwing away high-order bits if necessary. */ + if (gfc_option.flag_range_check == 0) + { + int k; + + k = gfc_validate_kind (BT_INTEGER, kind, false); + gfc_convert_mpz_to_signed (result->value.integer, + gfc_integer_kinds[k].bit_size); + } + return result; } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 14c202dd413..f0eed809ab8 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -3022,4 +3022,8 @@ typedef int (*walk_expr_fn_t) (gfc_expr **, int *, void *); int gfc_expr_walker (gfc_expr **, walk_expr_fn_t, void *); int gfc_code_walker (gfc_code **, walk_code_fn_t, walk_expr_fn_t, void *); +/* simplify.c */ + +void gfc_convert_mpz_to_signed (mpz_t, int); + #endif /* GCC_GFORTRAN_H */ diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index 96d0f21f36c..1b6cd5bc4c1 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -151,8 +151,10 @@ convert_mpz_to_unsigned (mpz_t x, int bitsize) if (mpz_sgn (x) < 0) { - /* Confirm that no bits above the signed range are unset. */ - gcc_assert (mpz_scan0 (x, bitsize-1) == ULONG_MAX); + /* Confirm that no bits above the signed range are unset if we + are doing range checking. */ + if (gfc_option.flag_range_check != 0) + gcc_assert (mpz_scan0 (x, bitsize-1) == ULONG_MAX); mpz_init_set_ui (mask, 1); mpz_mul_2exp (mask, mask, bitsize); @@ -175,13 +177,15 @@ convert_mpz_to_unsigned (mpz_t x, int bitsize) If the bitsize-1 bit is set, this is taken as a sign bit and the number is converted to the corresponding negative number. */ -static void -convert_mpz_to_signed (mpz_t x, int bitsize) +void +gfc_convert_mpz_to_signed (mpz_t x, int bitsize) { mpz_t mask; - /* Confirm that no bits above the unsigned range are set. */ - gcc_assert (mpz_scan1 (x, bitsize) == ULONG_MAX); + /* Confirm that no bits above the unsigned range are set if we are + doing range checking. */ + if (gfc_option.flag_range_check != 0) + gcc_assert (mpz_scan1 (x, bitsize) == ULONG_MAX); if (mpz_tstbit (x, bitsize - 1) == 1) { @@ -1943,7 +1947,7 @@ simplify_dshift (gfc_expr *arg1, gfc_expr *arg2, gfc_expr *shiftarg, mpz_setbit (result->value.integer, shift + i); /* Convert to a signed value. */ - convert_mpz_to_signed (result->value.integer, size); + gfc_convert_mpz_to_signed (result->value.integer, size); return result; } @@ -2561,7 +2565,7 @@ gfc_simplify_ibclr (gfc_expr *x, gfc_expr *y) mpz_clrbit (result->value.integer, pos); - convert_mpz_to_signed (result->value.integer, + gfc_convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size); return result; @@ -2619,7 +2623,7 @@ gfc_simplify_ibits (gfc_expr *x, gfc_expr *y, gfc_expr *z) free (bits); - convert_mpz_to_signed (result->value.integer, + gfc_convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size); return result; @@ -2646,7 +2650,7 @@ gfc_simplify_ibset (gfc_expr *x, gfc_expr *y) mpz_setbit (result->value.integer, pos); - convert_mpz_to_signed (result->value.integer, + gfc_convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size); return result; @@ -3093,7 +3097,7 @@ simplify_shift (gfc_expr *e, gfc_expr *s, const char *name, } } - convert_mpz_to_signed (result->value.integer, bitsize); + gfc_convert_mpz_to_signed (result->value.integer, bitsize); free (bits); return result; @@ -3234,7 +3238,7 @@ gfc_simplify_ishftc (gfc_expr *e, gfc_expr *s, gfc_expr *sz) } } - convert_mpz_to_signed (result->value.integer, isize); + gfc_convert_mpz_to_signed (result->value.integer, isize); free (bits); return result; @@ -3954,7 +3958,7 @@ gfc_simplify_maskr (gfc_expr *i, gfc_expr *kind_arg) mpz_mul_2exp (result->value.integer, result->value.integer, arg); mpz_sub_ui (result->value.integer, result->value.integer, 1); - convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size); + gfc_convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size); return result; } @@ -3990,7 +3994,7 @@ gfc_simplify_maskl (gfc_expr *i, gfc_expr *kind_arg) mpz_sub (result->value.integer, z, result->value.integer); mpz_clear (z); - convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size); + gfc_convert_mpz_to_signed (result->value.integer, gfc_integer_kinds[k].bit_size); return result; } diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index cf252d4269d..af9f26d2e9c 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -1111,14 +1111,17 @@ create_mul_imm_cand (gimple gs, tree base_in, tree stride_in, bool speed) X = Y * c ============================ X = (B + i') * (S * c) */ - base = base_cand->base_expr; - index = base_cand->index; temp = wi::to_widest (base_cand->stride) * wi::to_widest (stride_in); - stride = wide_int_to_tree (TREE_TYPE (stride_in), temp); - ctype = base_cand->cand_type; - if (has_single_use (base_in)) - savings = (base_cand->dead_savings - + stmt_cost (base_cand->cand_stmt, speed)); + if (wi::fits_to_tree_p (temp, TREE_TYPE (stride_in))) + { + base = base_cand->base_expr; + index = base_cand->index; + stride = wide_int_to_tree (TREE_TYPE (stride_in), temp); + ctype = base_cand->cand_type; + if (has_single_use (base_in)) + savings = (base_cand->dead_savings + + stmt_cost (base_cand->cand_stmt, speed)); + } } else if (base_cand->kind == CAND_ADD && integer_onep (base_cand->stride)) { diff --git a/gcc/gimplify.c b/gcc/gimplify.c index d7470fbb0a6..008a2528644 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -5796,7 +5796,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) to the contrary in the innermost scope, generate an error. */ static bool -omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, bool simd) +omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, int simd) { splay_tree_node n; @@ -5830,13 +5830,13 @@ omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, bool simd) else if ((n->value & GOVD_REDUCTION) != 0) error ("iteration variable %qE should not be reduction", DECL_NAME (decl)); - else if (simd && (n->value & GOVD_LASTPRIVATE) != 0) + else if (simd == 1 && (n->value & GOVD_LASTPRIVATE) != 0) error ("iteration variable %qE should not be lastprivate", DECL_NAME (decl)); else if (simd && (n->value & GOVD_PRIVATE) != 0) error ("iteration variable %qE should not be private", DECL_NAME (decl)); - else if (simd && (n->value & GOVD_LINEAR) != 0) + else if (simd == 2 && (n->value & GOVD_LINEAR) != 0) error ("iteration variable %qE is predetermined linear", DECL_NAME (decl)); } @@ -6602,8 +6602,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) orig_for_stmt = for_stmt = *expr_p; - simd = TREE_CODE (for_stmt) == OMP_SIMD - || TREE_CODE (for_stmt) == CILK_SIMD; + simd = (TREE_CODE (for_stmt) == OMP_SIMD + || TREE_CODE (for_stmt) == CILK_SIMD); gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, simd ? ORT_SIMD : ORT_WORKSHARE); @@ -6659,13 +6659,16 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) /* Make sure the iteration variable is private. */ tree c = NULL_TREE; + tree c2 = NULL_TREE; if (orig_for_stmt != for_stmt) /* Do this only on innermost construct for combined ones. */; else if (simd) { splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables, (splay_tree_key)decl); - omp_is_private (gimplify_omp_ctxp, decl, simd); + omp_is_private (gimplify_omp_ctxp, decl, + 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) + != 1)); if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0) omp_notice_variable (gimplify_omp_ctxp, decl, true); else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1) @@ -6691,13 +6694,14 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) : OMP_CLAUSE_PRIVATE); OMP_CLAUSE_DECL (c) = decl; OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt); + OMP_FOR_CLAUSES (for_stmt) = c; omp_add_variable (gimplify_omp_ctxp, decl, (lastprivate ? GOVD_LASTPRIVATE : GOVD_PRIVATE) - | GOVD_SEEN); + | GOVD_EXPLICIT | GOVD_SEEN); c = NULL_TREE; } } - else if (omp_is_private (gimplify_omp_ctxp, decl, simd)) + else if (omp_is_private (gimplify_omp_ctxp, decl, 0)) omp_notice_variable (gimplify_omp_ctxp, decl, true); else omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN); @@ -6714,7 +6718,25 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var)); - omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN); + if (simd && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1) + { + c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR); + OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1; + OMP_CLAUSE_LINEAR_NO_COPYOUT (c2) = 1; + OMP_CLAUSE_DECL (c2) = var; + OMP_CLAUSE_CHAIN (c2) = OMP_FOR_CLAUSES (for_stmt); + OMP_FOR_CLAUSES (for_stmt) = c2; + omp_add_variable (gimplify_omp_ctxp, var, + GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN); + if (c == NULL_TREE) + { + c = c2; + c2 = NULL_TREE; + } + } + else + omp_add_variable (gimplify_omp_ctxp, var, + GOVD_PRIVATE | GOVD_SEEN); } else var = decl; @@ -6817,13 +6839,22 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_unreachable (); } + if (c2) + { + gcc_assert (c); + OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c); + } + if ((var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1) && orig_for_stmt == for_stmt) { for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE - && OMP_CLAUSE_DECL (c) == decl - && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL) + if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE + && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL) + || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR + && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c) + && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL)) + && OMP_CLAUSE_DECL (c) == decl) { t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i); gcc_assert (TREE_CODE (t) == MODIFY_EXPR); @@ -6835,8 +6866,12 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_assert (TREE_OPERAND (t, 0) == var); t = build2 (TREE_CODE (t), TREE_TYPE (decl), decl, TREE_OPERAND (t, 1)); - gimplify_assign (decl, t, - &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)); + gimple_seq *seq; + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) + seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c); + else + seq = &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c); + gimplify_assign (decl, t, seq); } } } diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 966fd425d78..1a863b04dbc 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,16 @@ +2014-04-25 Chris Manghane <cmang@google.com> + + * go-gcc.cc: Include "cgraph.h" and "gimplify.h". + (Gcc_backend::return_statement): Push and pop function. + (Gcc_backend::label): Likewise. + (Gcc_backend::function_defer_statement): Likewise. + (Gcc_backend::switch_statement): Add function parameter. + (Gcc_backend::block): Don't permit function to be NULL. + (Gcc_backend::temporary_variable): Change go_assert to + gcc_assert. + (Gcc_backend::gc_root_variable): New function. + (Gcc_backend::write_global_definitions): New function. + 2014-04-22 Chris Manghane <cmang@google.com> * go-gcc.cc (Gcc_backend::temporary_variable): Push cfun around diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 50403e159ef..a0283fe12e0 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -29,9 +29,11 @@ #include "stor-layout.h" #include "varasm.h" #include "tree-iterator.h" +#include "cgraph.h" #include "convert.h" #include "basic-block.h" #include "gimple-expr.h" +#include "gimplify.h" #include "toplev.h" #include "output.h" #include "real.h" @@ -317,7 +319,7 @@ class Gcc_backend : public Backend Location); Bstatement* - switch_statement(Bexpression* value, + switch_statement(Bfunction* function, Bexpression* value, const std::vector<std::vector<Bexpression*> >& cases, const std::vector<Bstatement*>& statements, Location); @@ -376,6 +378,9 @@ class Gcc_backend : public Backend Location, Bstatement**); Bvariable* + gc_root_variable(Btype*, Bexpression*); + + Bvariable* immutable_struct(const std::string&, bool, bool, Btype*, Location); void @@ -420,6 +425,12 @@ class Gcc_backend : public Backend bool function_set_body(Bfunction* function, Bstatement* code_stmt); + void + write_global_definitions(const std::vector<Btype*>&, + const std::vector<Bexpression*>&, + const std::vector<Bfunction*>&, + const std::vector<Bvariable*>&); + private: // Make a Bexpression from a tree. Bexpression* @@ -1708,6 +1719,7 @@ Gcc_backend::return_statement(Bfunction* bfunction, tree result = DECL_RESULT(fntree); if (result == error_mark_node) return this->error_statement(); + tree ret; if (vals.empty()) ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, void_type_node, @@ -1731,7 +1743,14 @@ Gcc_backend::return_statement(Bfunction* bfunction, // statement. tree stmt_list = NULL_TREE; tree rettype = TREE_TYPE(result); + + if (DECL_STRUCT_FUNCTION(fntree) == NULL) + push_struct_function(fntree); + else + push_cfun(DECL_STRUCT_FUNCTION(fntree)); tree rettmp = create_tmp_var(rettype, "RESULT"); + pop_cfun(); + tree field = TYPE_FIELDS(rettype); for (std::vector<Bexpression*>::const_iterator p = vals.begin(); p != vals.end(); @@ -1817,6 +1836,7 @@ Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block, Bstatement* Gcc_backend::switch_statement( + Bfunction* function, Bexpression* value, const std::vector<std::vector<Bexpression*> >& cases, const std::vector<Bstatement*>& statements, @@ -1824,6 +1844,12 @@ Gcc_backend::switch_statement( { gcc_assert(cases.size() == statements.size()); + tree decl = function->get_tree(); + if (DECL_STRUCT_FUNCTION(decl) == NULL) + push_struct_function(decl); + else + push_cfun(DECL_STRUCT_FUNCTION(decl)); + tree stmt_list = NULL_TREE; std::vector<std::vector<Bexpression*> >::const_iterator pc = cases.begin(); for (std::vector<Bstatement*>::const_iterator ps = statements.begin(); @@ -1863,6 +1889,7 @@ Gcc_backend::switch_statement( append_to_statement_list(t, &stmt_list); } } + pop_cfun(); tree tv = value->get_tree(); if (tv == error_mark_node) @@ -1921,13 +1948,7 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing, tree block_tree = make_node(BLOCK); if (enclosing == NULL) { - // FIXME: Permitting FUNCTION to be NULL is a temporary measure - // until we have a proper representation of the init function. - tree fndecl; - if (function == NULL) - fndecl = current_function_decl; - else - fndecl = function->get_tree(); + tree fndecl = function->get_tree(); gcc_assert(fndecl != NULL_TREE); // We may have already created a block for local variables when @@ -1981,7 +2002,6 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing, void_type_node, BLOCK_VARS(block_tree), NULL_TREE, block_tree); TREE_SIDE_EFFECTS(bind_tree) = 1; - return new Bblock(bind_tree); } @@ -2213,7 +2233,7 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, return this->error_variable(); } - go_assert(function != NULL); + gcc_assert(function != NULL); tree decl = function->get_tree(); tree var; @@ -2262,6 +2282,28 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, return new Bvariable(var); } +// Make a GC root variable. + +Bvariable* +Gcc_backend::gc_root_variable(Btype* type, Bexpression* init) +{ + tree type_tree = type->get_tree(); + tree init_tree = init->get_tree(); + if (type_tree == error_mark_node || init_tree == error_mark_node) + return this->error_variable(); + + tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, + create_tmp_var_name("gc"), type_tree); + DECL_EXTERNAL(decl) = 0; + TREE_PUBLIC(decl) = 0; + TREE_STATIC(decl) = 1; + DECL_ARTIFICIAL(decl) = 1; + DECL_INITIAL(decl) = init_tree; + rest_of_decl_compilation(decl, 1, 0); + + return new Bvariable(decl); +} + // Create a named immutable initialized data structure. Bvariable* @@ -2276,9 +2318,9 @@ Gcc_backend::immutable_struct(const std::string& name, bool is_hidden, get_identifier_from_string(name), build_qualified_type(type_tree, TYPE_QUAL_CONST)); TREE_STATIC(decl) = 1; + TREE_USED(decl) = 1; TREE_READONLY(decl) = 1; TREE_CONSTANT(decl) = 1; - TREE_USED(decl) = 1; DECL_ARTIFICIAL(decl) = 1; if (!is_hidden) TREE_PUBLIC(decl) = 1; @@ -2368,7 +2410,17 @@ Gcc_backend::label(Bfunction* function, const std::string& name, { tree decl; if (name.empty()) - decl = create_artificial_label(location.gcc_location()); + { + tree func_tree = function->get_tree(); + if (DECL_STRUCT_FUNCTION(func_tree) == NULL) + push_struct_function(func_tree); + else + push_cfun(DECL_STRUCT_FUNCTION(func_tree)); + + decl = create_artificial_label(location.gcc_location()); + + pop_cfun(); + } else { tree id = get_identifier_from_string(name); @@ -2476,11 +2528,18 @@ Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer, { tree undefer_tree = undefer->get_tree(); tree defer_tree = defer->get_tree(); + tree fntree = function->get_tree(); if (undefer_tree == error_mark_node - || defer_tree == error_mark_node) + || defer_tree == error_mark_node + || fntree == error_mark_node) return this->error_statement(); + if (DECL_STRUCT_FUNCTION(fntree) == NULL) + push_struct_function(fntree); + else + push_cfun(DECL_STRUCT_FUNCTION(fntree)); + tree stmt_list = NULL; Blabel* blabel = this->label(function, "", location); Bstatement* label_def = this->label_definition_statement(blabel); @@ -2493,6 +2552,7 @@ Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer, tree try_catch = build2(TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body); append_to_statement_list(try_catch, &stmt_list); + pop_cfun(); return this->make_statement(stmt_list); } @@ -2537,6 +2597,88 @@ Gcc_backend::function_set_body(Bfunction* function, Bstatement* code_stmt) return true; } +// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, +// FUNCTION_DECLS, and VARIABLE_DECLS declared globally. + +void +Gcc_backend::write_global_definitions( + const std::vector<Btype*>& type_decls, + const std::vector<Bexpression*>& constant_decls, + const std::vector<Bfunction*>& function_decls, + const std::vector<Bvariable*>& variable_decls) +{ + size_t count_definitions = type_decls.size() + constant_decls.size() + + function_decls.size() + variable_decls.size(); + + tree* defs = new tree[count_definitions]; + + // Convert all non-erroneous declarations into Gimple form. + size_t i = 0; + for (std::vector<Bvariable*>::const_iterator p = variable_decls.begin(); + p != variable_decls.end(); + ++p) + { + if ((*p)->get_tree() != error_mark_node) + { + defs[i] = (*p)->get_tree(); + go_preserve_from_gc(defs[i]); + ++i; + } + } + + for (std::vector<Btype*>::const_iterator p = type_decls.begin(); + p != type_decls.end(); + ++p) + { + tree type_tree = (*p)->get_tree(); + if (type_tree != error_mark_node + && IS_TYPE_OR_DECL_P(type_tree)) + { + defs[i] = TYPE_NAME(type_tree); + gcc_assert(defs[i] != NULL); + go_preserve_from_gc(defs[i]); + ++i; + } + } + for (std::vector<Bexpression*>::const_iterator p = constant_decls.begin(); + p != constant_decls.end(); + ++p) + { + if ((*p)->get_tree() != error_mark_node) + { + defs[i] = (*p)->get_tree(); + go_preserve_from_gc(defs[i]); + ++i; + } + } + for (std::vector<Bfunction*>::const_iterator p = function_decls.begin(); + p != function_decls.end(); + ++p) + { + tree decl = (*p)->get_tree(); + if (decl != error_mark_node) + { + go_preserve_from_gc(decl); + gimplify_function_tree(decl); + cgraph_finalize_function(decl, true); + + defs[i] = decl; + ++i; + } + } + + // Pass everything back to the middle-end. + + wrapup_global_declarations(defs, i); + + finalize_compilation_unit(); + + check_global_declarations(defs, i); + emit_debug_global_declarations(defs, i); + + delete[] defs; +} + // The single backend. static Gcc_backend gcc_backend; diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index dd76204e70c..aca3dc6f90e 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -406,9 +406,9 @@ class Backend // integers, then STATEMENTS[i] is executed. STATEMENTS[i] will // either end with a goto statement or will fall through into // STATEMENTS[i + 1]. CASES[i] is empty for the default clause, - // which need not be last. + // which need not be last. FUNCTION is the current function. virtual Bstatement* - switch_statement(Bexpression* value, + switch_statement(Bfunction* function, Bexpression* value, const std::vector<std::vector<Bexpression*> >& cases, const std::vector<Bstatement*>& statements, Location) = 0; @@ -534,6 +534,12 @@ class Backend bool address_is_taken, Location location, Bstatement** pstatement) = 0; + // Create a GC root variable. TYPE is the __go_gc_root_list struct described + // in Gogo::register_gc_vars. INIT is the composite literal consisting of a + // pointer to the next GC root and the global variables registered. + virtual Bvariable* + gc_root_variable(Btype* type, Bexpression* init) = 0; + // Create a named immutable initialized data structure. This is // used for type descriptors, map descriptors, and function // descriptors. This returns a Bvariable because it corresponds to @@ -653,6 +659,16 @@ class Backend // true on success, false on failure. virtual bool function_set_body(Bfunction* function, Bstatement* code_stmt) = 0; + + // Utility. + + // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, + // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. + virtual void + write_global_definitions(const std::vector<Btype*>& type_decls, + const std::vector<Bexpression*>& constant_decls, + const std::vector<Bfunction*>& function_decls, + const std::vector<Bvariable*>& variable_decls) = 0; }; // The backend interface has to define this function. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 74ae9ddcd7d..27562639176 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3578,127 +3578,7 @@ Expression::make_unsafe_cast(Type* type, Expression* expr, return new Unsafe_type_conversion_expression(type, expr, location); } -// Unary expressions. - -class Unary_expression : public Expression -{ - public: - Unary_expression(Operator op, Expression* expr, Location location) - : Expression(EXPRESSION_UNARY, location), - op_(op), escapes_(true), create_temp_(false), expr_(expr), - issue_nil_check_(false) - { } - - // Return the operator. - Operator - op() const - { return this->op_; } - - // Return the operand. - Expression* - operand() const - { return this->expr_; } - - // Record that an address expression does not escape. - void - set_does_not_escape() - { - go_assert(this->op_ == OPERATOR_AND); - this->escapes_ = false; - } - - // Record that this is an address expression which should create a - // temporary variable if necessary. This is used for method calls. - void - set_create_temp() - { - go_assert(this->op_ == OPERATOR_AND); - this->create_temp_ = true; - } - - // Apply unary opcode OP to UNC, setting NC. Return true if this - // could be done, false if not. Issue errors for overflow. - static bool - eval_constant(Operator op, const Numeric_constant* unc, - Location, Numeric_constant* nc); - - static Expression* - do_import(Import*); - - protected: - int - do_traverse(Traverse* traverse) - { return Expression::traverse(&this->expr_, traverse); } - - Expression* - do_lower(Gogo*, Named_object*, Statement_inserter*, int); - - Expression* - do_flatten(Gogo*, Named_object*, Statement_inserter*); - - bool - do_is_constant() const; - - bool - do_is_immutable() const - { return this->expr_->is_immutable() - || (this->op_ == OPERATOR_AND && this->expr_->is_variable()); } - - bool - do_numeric_constant_value(Numeric_constant*) const; - - Type* - do_type(); - - void - do_determine_type(const Type_context*); - - void - do_check_types(Gogo*); - - Expression* - do_copy() - { - return Expression::make_unary(this->op_, this->expr_->copy(), - this->location()); - } - - bool - do_must_eval_subexpressions_in_order(int*) const - { return this->op_ == OPERATOR_MULT; } - - bool - do_is_addressable() const - { return this->op_ == OPERATOR_MULT; } - - tree - do_get_tree(Translate_context*); - - void - do_export(Export*) const; - - void - do_dump_expression(Ast_dump_context*) const; - - void - do_issue_nil_check() - { this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); } - - private: - // The unary operator to apply. - Operator op_; - // Normally true. False if this is an address expression which does - // not escape the current function. - bool escapes_; - // True if this is an address expression which should create a - // temporary variable if necessary. - bool create_temp_; - // The operand. - Expression* expr_; - // Whether or not to issue a nil check for this expression if its address - // is being taken. - bool issue_nil_check_; -}; +// Class Unary_expression. // If we are taking the address of a composite literal, and the // contents are not constant, then we want to make a heap expression @@ -4214,11 +4094,18 @@ Unary_expression::do_get_tree(Translate_context* context) } } - // Build a decl for a constant constructor. - if ((this->expr_->is_composite_literal() + if (this->is_gc_root_) + { + // Build a decl for a GC root variable. GC roots are mutable, so they + // cannot be represented as an immutable_struct in the backend. + Bvariable* gc_root = gogo->backend()->gc_root_variable(btype, bexpr); + bexpr = gogo->backend()->var_expression(gc_root, loc); + } + else if ((this->expr_->is_composite_literal() || this->expr_->string_expression() != NULL) && this->expr_->is_immutable()) { + // Build a decl for a constant constructor. static unsigned int counter; char buf[100]; snprintf(buf, sizeof buf, "C%u", counter); @@ -12508,6 +12395,14 @@ Fixed_array_construction_expression::do_get_tree(Translate_context* context) return expr_to_tree(this->get_constructor(context, btype)); } +Expression* +Expression::make_array_composite_literal(Type* type, Expression_list* vals, + Location location) +{ + go_assert(type->array_type() != NULL && !type->is_slice_type()); + return new Fixed_array_construction_expression(type, NULL, vals, location); +} + // Construct a slice. class Slice_construction_expression : public Array_construction_expression diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index dc9ad71c820..0936e00bae0 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -30,6 +30,7 @@ class Var_expression; class Temporary_reference_expression; class Set_and_use_temporary_expression; class String_expression; +class Unary_expression; class Binary_expression; class Call_expression; class Func_expression; @@ -327,6 +328,10 @@ class Expression static Expression* make_struct_composite_literal(Type*, Expression_list*, Location); + // Make an array composite literal. + static Expression* + make_array_composite_literal(Type*, Expression_list*, Location); + // Make a slice composite literal. static Expression* make_slice_composite_literal(Type*, Expression_list*, Location); @@ -533,6 +538,12 @@ class Expression Expression* deref(); + // If this is a unary expression, return the Unary_expression + // structure. Otherwise return NULL. + Unary_expression* + unary_expression() + { return this->convert<Unary_expression, EXPRESSION_UNARY>(); } + // If this is a binary expression, return the Binary_expression // structure. Otherwise return NULL. Binary_expression* @@ -1286,6 +1297,143 @@ class String_expression : public Expression Type* type_; }; +// A Unary expression. + +class Unary_expression : public Expression +{ + public: + Unary_expression(Operator op, Expression* expr, Location location) + : Expression(EXPRESSION_UNARY, location), + op_(op), escapes_(true), create_temp_(false), is_gc_root_(false), + expr_(expr), issue_nil_check_(false) + { } + + // Return the operator. + Operator + op() const + { return this->op_; } + + // Return the operand. + Expression* + operand() const + { return this->expr_; } + + // Record that an address expression does not escape. + void + set_does_not_escape() + { + go_assert(this->op_ == OPERATOR_AND); + this->escapes_ = false; + } + + // Record that this is an address expression which should create a + // temporary variable if necessary. This is used for method calls. + void + set_create_temp() + { + go_assert(this->op_ == OPERATOR_AND); + this->create_temp_ = true; + } + + // Record that this is an address expression of a GC root, which is a + // mutable composite literal. This used for registering GC variables. + void + set_is_gc_root() + { + go_assert(this->op_ == OPERATOR_AND); + this->is_gc_root_ = true; + } + + // Apply unary opcode OP to UNC, setting NC. Return true if this + // could be done, false if not. Issue errors for overflow. + static bool + eval_constant(Operator op, const Numeric_constant* unc, + Location, Numeric_constant* nc); + + static Expression* + do_import(Import*); + + protected: + int + do_traverse(Traverse* traverse) + { return Expression::traverse(&this->expr_, traverse); } + + Expression* + do_lower(Gogo*, Named_object*, Statement_inserter*, int); + + Expression* + do_flatten(Gogo*, Named_object*, Statement_inserter*); + + bool + do_is_constant() const; + + bool + do_is_immutable() const + { + return (this->expr_->is_immutable() + || (this->op_ == OPERATOR_AND && this->expr_->is_variable())); + } + + bool + do_numeric_constant_value(Numeric_constant*) const; + + Type* + do_type(); + + void + do_determine_type(const Type_context*); + + void + do_check_types(Gogo*); + + Expression* + do_copy() + { + return Expression::make_unary(this->op_, this->expr_->copy(), + this->location()); + } + + bool + do_must_eval_subexpressions_in_order(int*) const + { return this->op_ == OPERATOR_MULT; } + + bool + do_is_addressable() const + { return this->op_ == OPERATOR_MULT; } + + tree + do_get_tree(Translate_context*); + + void + do_export(Export*) const; + + void + do_dump_expression(Ast_dump_context*) const; + + void + do_issue_nil_check() + { this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); } + + private: + // The unary operator to apply. + Operator op_; + // Normally true. False if this is an address expression which does + // not escape the current function. + bool escapes_; + // True if this is an address expression which should create a + // temporary variable if necessary. + bool create_temp_; + // True if this is an address expression for a GC root. A GC root is a + // special struct composite literal that is mutable when addressed, meaning + // it cannot be represented as an immutable_struct in the backend. + bool is_gc_root_; + // The operand. + Expression* expr_; + // Whether or not to issue a nil check for this expression if its address + // is being taken. + bool issue_nil_check_; +}; + // A binary expression. class Binary_expression : public Expression diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc index c00e7d16011..6b19a1d82e1 100644 --- a/gcc/go/gofrontend/gogo-tree.cc +++ b/gcc/go/gofrontend/gogo-tree.cc @@ -236,830 +236,6 @@ Gogo::define_builtin_function_trees() false); } -// Add statements to INIT_STMT_LIST which run the initialization -// functions for imported packages. This is only used for the "main" -// package. - -void -Gogo::init_imports(tree* init_stmt_list) -{ - go_assert(this->is_main_package()); - - if (this->imported_init_fns_.empty()) - return; - - tree fntype = build_function_type(void_type_node, void_list_node); - - // We must call them in increasing priority order. - std::vector<Import_init> v; - for (std::set<Import_init>::const_iterator p = - this->imported_init_fns_.begin(); - p != this->imported_init_fns_.end(); - ++p) - v.push_back(*p); - std::sort(v.begin(), v.end()); - - for (std::vector<Import_init>::const_iterator p = v.begin(); - p != v.end(); - ++p) - { - std::string user_name = p->package_name() + ".init"; - tree decl = build_decl(UNKNOWN_LOCATION, FUNCTION_DECL, - get_identifier_from_string(user_name), - fntype); - const std::string& init_name(p->init_name()); - SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(init_name)); - TREE_PUBLIC(decl) = 1; - DECL_EXTERNAL(decl) = 1; - append_to_statement_list(build_call_expr(decl, 0), init_stmt_list); - } -} - -// Register global variables with the garbage collector. We need to -// register all variables which can hold a pointer value. They become -// roots during the mark phase. We build a struct that is easy to -// hook into a list of roots. - -// struct __go_gc_root_list -// { -// struct __go_gc_root_list* __next; -// struct __go_gc_root -// { -// void* __decl; -// size_t __size; -// } __roots[]; -// }; - -// The last entry in the roots array has a NULL decl field. - -void -Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc, - tree* init_stmt_list) -{ - if (var_gc.empty()) - return; - - size_t count = var_gc.size(); - - tree root_type = Gogo::builtin_struct(NULL, "__go_gc_root", NULL_TREE, 2, - "__next", - ptr_type_node, - "__size", - sizetype); - - tree index_type = build_index_type(size_int(count)); - tree array_type = build_array_type(root_type, index_type); - - tree root_list_type = make_node(RECORD_TYPE); - root_list_type = Gogo::builtin_struct(NULL, "__go_gc_root_list", - root_list_type, 2, - "__next", - build_pointer_type(root_list_type), - "__roots", - array_type); - - // Build an initialier for the __roots array. - - vec<constructor_elt, va_gc> *roots_init; - vec_alloc(roots_init, count + 1); - - size_t i = 0; - for (std::vector<Named_object*>::const_iterator p = var_gc.begin(); - p != var_gc.end(); - ++p, ++i) - { - vec<constructor_elt, va_gc> *init; - vec_alloc(init, 2); - - constructor_elt empty = {NULL, NULL}; - constructor_elt* elt = init->quick_push(empty); - tree field = TYPE_FIELDS(root_type); - elt->index = field; - Bvariable* bvar = (*p)->get_backend_variable(this, NULL); - tree decl = var_to_tree(bvar); - go_assert(TREE_CODE(decl) == VAR_DECL); - elt->value = build_fold_addr_expr(decl); - - elt = init->quick_push(empty); - field = DECL_CHAIN(field); - elt->index = field; - elt->value = DECL_SIZE_UNIT(decl); - - elt = roots_init->quick_push(empty); - elt->index = size_int(i); - elt->value = build_constructor(root_type, init); - } - - // The list ends with a NULL entry. - - vec<constructor_elt, va_gc> *init; - vec_alloc(init, 2); - - constructor_elt empty = {NULL, NULL}; - constructor_elt* elt = init->quick_push(empty); - tree field = TYPE_FIELDS(root_type); - elt->index = field; - elt->value = fold_convert(TREE_TYPE(field), null_pointer_node); - - elt = init->quick_push(empty); - field = DECL_CHAIN(field); - elt->index = field; - elt->value = size_zero_node; - - elt = roots_init->quick_push(empty); - elt->index = size_int(i); - elt->value = build_constructor(root_type, init); - - // Build a constructor for the struct. - - vec<constructor_elt, va_gc> *root_list_init; - vec_alloc(root_list_init, 2); - - elt = root_list_init->quick_push(empty); - field = TYPE_FIELDS(root_list_type); - elt->index = field; - elt->value = fold_convert(TREE_TYPE(field), null_pointer_node); - - elt = root_list_init->quick_push(empty); - field = DECL_CHAIN(field); - elt->index = field; - elt->value = build_constructor(array_type, roots_init); - - // Build a decl to register. - - tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, - create_tmp_var_name("gc"), root_list_type); - DECL_EXTERNAL(decl) = 0; - TREE_PUBLIC(decl) = 0; - TREE_STATIC(decl) = 1; - DECL_ARTIFICIAL(decl) = 1; - DECL_INITIAL(decl) = build_constructor(root_list_type, root_list_init); - rest_of_decl_compilation(decl, 1, 0); - - static tree register_gc_fndecl; - tree call = Gogo::call_builtin(®ister_gc_fndecl, - Linemap::predeclared_location(), - "__go_register_gc_roots", - 1, - void_type_node, - build_pointer_type(root_list_type), - build_fold_addr_expr(decl)); - if (call != error_mark_node) - append_to_statement_list(call, init_stmt_list); -} - -// Create the magic initialization function. INIT_STMT_LIST is the -// code that it needs to run. - -void -Gogo::write_initialization_function(Named_object* initfn, tree init_stmt_list) -{ - // Make sure that we thought we needed an initialization function, - // as otherwise we will not have reported it in the export data. - go_assert(this->is_main_package() || this->need_init_fn_); - - if (initfn == NULL) - initfn = this->initialization_function_decl(); - - Bfunction* fndecl = initfn->func_value()->get_or_make_decl(this, initfn); - Location loc = this->package_->location(); - std::vector<Bvariable*> vars; - this->backend()->block(fndecl, NULL, vars, loc, loc); - - if (!this->backend()->function_set_body(fndecl, tree_to_stat(init_stmt_list))) - { - go_assert(saw_errors()); - return; - } - gimplify_function_tree(function_to_tree(fndecl)); - cgraph_add_new_function(function_to_tree(fndecl), false); -} - -// Search for references to VAR in any statements or called functions. - -class Find_var : public Traverse -{ - public: - // A hash table we use to avoid looping. The index is the name of a - // named object. We only look through objects defined in this - // package. - typedef Unordered_set(const void*) Seen_objects; - - Find_var(Named_object* var, Seen_objects* seen_objects) - : Traverse(traverse_expressions), - var_(var), seen_objects_(seen_objects), found_(false) - { } - - // Whether the variable was found. - bool - found() const - { return this->found_; } - - int - expression(Expression**); - - private: - // The variable we are looking for. - Named_object* var_; - // Names of objects we have already seen. - Seen_objects* seen_objects_; - // True if the variable was found. - bool found_; -}; - -// See if EXPR refers to VAR, looking through function calls and -// variable initializations. - -int -Find_var::expression(Expression** pexpr) -{ - Expression* e = *pexpr; - - Var_expression* ve = e->var_expression(); - if (ve != NULL) - { - Named_object* v = ve->named_object(); - if (v == this->var_) - { - this->found_ = true; - return TRAVERSE_EXIT; - } - - if (v->is_variable() && v->package() == NULL) - { - Expression* init = v->var_value()->init(); - if (init != NULL) - { - std::pair<Seen_objects::iterator, bool> ins = - this->seen_objects_->insert(v); - if (ins.second) - { - // This is the first time we have seen this name. - if (Expression::traverse(&init, this) == TRAVERSE_EXIT) - return TRAVERSE_EXIT; - } - } - } - } - - // We traverse the code of any function we see. Note that this - // means that we will traverse the code of a function whose address - // is taken even if it is not called. - Func_expression* fe = e->func_expression(); - if (fe != NULL) - { - const Named_object* f = fe->named_object(); - if (f->is_function() && f->package() == NULL) - { - std::pair<Seen_objects::iterator, bool> ins = - this->seen_objects_->insert(f); - if (ins.second) - { - // This is the first time we have seen this name. - if (f->func_value()->block()->traverse(this) == TRAVERSE_EXIT) - return TRAVERSE_EXIT; - } - } - } - - Temporary_reference_expression* tre = e->temporary_reference_expression(); - if (tre != NULL) - { - Temporary_statement* ts = tre->statement(); - Expression* init = ts->init(); - if (init != NULL) - { - std::pair<Seen_objects::iterator, bool> ins = - this->seen_objects_->insert(ts); - if (ins.second) - { - // This is the first time we have seen this temporary - // statement. - if (Expression::traverse(&init, this) == TRAVERSE_EXIT) - return TRAVERSE_EXIT; - } - } - } - - return TRAVERSE_CONTINUE; -} - -// Return true if EXPR, PREINIT, or DEP refers to VAR. - -static bool -expression_requires(Expression* expr, Block* preinit, Named_object* dep, - Named_object* var) -{ - Find_var::Seen_objects seen_objects; - Find_var find_var(var, &seen_objects); - if (expr != NULL) - Expression::traverse(&expr, &find_var); - if (preinit != NULL) - preinit->traverse(&find_var); - if (dep != NULL) - { - Expression* init = dep->var_value()->init(); - if (init != NULL) - Expression::traverse(&init, &find_var); - if (dep->var_value()->has_pre_init()) - dep->var_value()->preinit()->traverse(&find_var); - } - - return find_var.found(); -} - -// Sort variable initializations. If the initialization expression -// for variable A refers directly or indirectly to the initialization -// expression for variable B, then we must initialize B before A. - -class Var_init -{ - public: - Var_init() - : var_(NULL), init_(NULL) - { } - - Var_init(Named_object* var, Bstatement* init) - : var_(var), init_(init) - { } - - // Return the variable. - Named_object* - var() const - { return this->var_; } - - // Return the initialization expression. - Bstatement* - init() const - { return this->init_; } - - private: - // The variable being initialized. - Named_object* var_; - // The initialization statement. - Bstatement* init_; -}; - -typedef std::list<Var_init> Var_inits; - -// Sort the variable initializations. The rule we follow is that we -// emit them in the order they appear in the array, except that if the -// initialization expression for a variable V1 depends upon another -// variable V2 then we initialize V1 after V2. - -static void -sort_var_inits(Gogo* gogo, Var_inits* var_inits) -{ - typedef std::pair<Named_object*, Named_object*> No_no; - typedef std::map<No_no, bool> Cache; - Cache cache; - - Var_inits ready; - while (!var_inits->empty()) - { - Var_inits::iterator p1 = var_inits->begin(); - Named_object* var = p1->var(); - Expression* init = var->var_value()->init(); - Block* preinit = var->var_value()->preinit(); - Named_object* dep = gogo->var_depends_on(var->var_value()); - - // Start walking through the list to see which variables VAR - // needs to wait for. - Var_inits::iterator p2 = p1; - ++p2; - - for (; p2 != var_inits->end(); ++p2) - { - Named_object* p2var = p2->var(); - No_no key(var, p2var); - std::pair<Cache::iterator, bool> ins = - cache.insert(std::make_pair(key, false)); - if (ins.second) - ins.first->second = expression_requires(init, preinit, dep, p2var); - if (ins.first->second) - { - // Check for cycles. - key = std::make_pair(p2var, var); - ins = cache.insert(std::make_pair(key, false)); - if (ins.second) - ins.first->second = - expression_requires(p2var->var_value()->init(), - p2var->var_value()->preinit(), - gogo->var_depends_on(p2var->var_value()), - var); - if (ins.first->second) - { - error_at(var->location(), - ("initialization expressions for %qs and " - "%qs depend upon each other"), - var->message_name().c_str(), - p2var->message_name().c_str()); - inform(p2->var()->location(), "%qs defined here", - p2var->message_name().c_str()); - p2 = var_inits->end(); - } - else - { - // We can't emit P1 until P2 is emitted. Move P1. - Var_inits::iterator p3 = p2; - ++p3; - var_inits->splice(p3, *var_inits, p1); - } - break; - } - } - - if (p2 == var_inits->end()) - { - // VAR does not depends upon any other initialization expressions. - - // Check for a loop of VAR on itself. We only do this if - // INIT is not NULL and there is no dependency; when INIT is - // NULL, it means that PREINIT sets VAR, which we will - // interpret as a loop. - if (init != NULL && dep == NULL - && expression_requires(init, preinit, NULL, var)) - error_at(var->location(), - "initialization expression for %qs depends upon itself", - var->message_name().c_str()); - ready.splice(ready.end(), *var_inits, p1); - } - } - - // Now READY is the list in the desired initialization order. - var_inits->swap(ready); -} - -// Write out the global definitions. - -void -Gogo::write_globals() -{ - this->build_interface_method_tables(); - - Bindings* bindings = this->current_bindings(); - - for (Bindings::const_declarations_iterator p = bindings->begin_declarations(); - p != bindings->end_declarations(); - ++p) - { - // If any function declarations needed a descriptor, make sure - // we build it. - Named_object* no = p->second; - if (no->is_function_declaration()) - no->func_declaration_value()->build_backend_descriptor(this); - } - - size_t count_definitions = bindings->size_definitions(); - size_t count = count_definitions; - - tree* vec = new tree[count]; - - Named_object* init_fndecl = NULL; - tree init_stmt_list = NULL_TREE; - - if (this->is_main_package()) - this->init_imports(&init_stmt_list); - - // A list of variable initializations. - Var_inits var_inits; - - // A list of variables which need to be registered with the garbage - // collector. - std::vector<Named_object*> var_gc; - var_gc.reserve(count); - - tree var_init_stmt_list = NULL_TREE; - size_t i = 0; - for (Bindings::const_definitions_iterator p = bindings->begin_definitions(); - p != bindings->end_definitions(); - ++p, ++i) - { - Named_object* no = *p; - - go_assert(i < count); - - go_assert(!no->is_type_declaration() && !no->is_function_declaration()); - // There is nothing to do for a package. - if (no->is_package()) - { - --i; - --count; - continue; - } - - // There is nothing to do for an object which was imported from - // a different package into the global scope. - if (no->package() != NULL) - { - --i; - --count; - continue; - } - - // Skip blank named functions and constants. - if ((no->is_function() && no->func_value()->is_sink()) - || (no->is_const() && no->const_value()->is_sink())) - { - --i; - --count; - continue; - } - - // There is nothing useful we can output for constants which - // have ideal or non-integral type. - if (no->is_const()) - { - Type* type = no->const_value()->type(); - if (type == NULL) - type = no->const_value()->expr()->type(); - if (type->is_abstract() || type->integer_type() == NULL) - { - --i; - --count; - continue; - } - } - - if (!no->is_variable()) - { - vec[i] = no->get_tree(this, NULL); - if (vec[i] == error_mark_node) - { - go_assert(saw_errors()); - --i; - --count; - continue; - } - } - else - { - Bvariable* var = no->get_backend_variable(this, NULL); - vec[i] = var_to_tree(var); - if (vec[i] == error_mark_node) - { - go_assert(saw_errors()); - --i; - --count; - continue; - } - - // Check for a sink variable, which may be used to run an - // initializer purely for its side effects. - bool is_sink = no->name()[0] == '_' && no->name()[1] == '.'; - - Bstatement* var_init_stmt = NULL; - if (!no->var_value()->has_pre_init()) - { - Bexpression* var_binit = no->var_value()->get_init(this, NULL); - if (var_binit == NULL) - ; - else if (TREE_CONSTANT(expr_to_tree(var_binit))) - { - if (expression_requires(no->var_value()->init(), NULL, - this->var_depends_on(no->var_value()), - no)) - error_at(no->location(), - "initialization expression for %qs depends " - "upon itself", - no->message_name().c_str()); - this->backend()->global_variable_set_init(var, var_binit); - } - else if (is_sink) - var_init_stmt = - this->backend()->expression_statement(var_binit); - else - { - Location loc = no->var_value()->location(); - Bexpression* var_expr = - this->backend()->var_expression(var, loc); - var_init_stmt = - this->backend()->assignment_statement(var_expr, var_binit, - loc); - } - } - else - { - // We are going to create temporary variables which - // means that we need an fndecl. - if (init_fndecl == NULL) - init_fndecl = this->initialization_function_decl(); - - Bvariable* var_decl = is_sink ? NULL : var; - var_init_stmt = - no->var_value()->get_init_block(this, init_fndecl, var_decl); - } - - if (var_init_stmt != NULL) - { - if (no->var_value()->init() == NULL - && !no->var_value()->has_pre_init()) - append_to_statement_list(stat_to_tree(var_init_stmt), - &var_init_stmt_list); - else - var_inits.push_back(Var_init(no, var_init_stmt)); - } - else if (this->var_depends_on(no->var_value()) != NULL) - { - // This variable is initialized from something that is - // not in its init or preinit. This variable needs to - // participate in dependency analysis sorting, in case - // some other variable depends on this one. - Btype* int_btype = - Type::lookup_integer_type("int")->get_backend(this); - Bexpression* zero = this->backend()->zero_expression(int_btype); - Bstatement* zero_stmt = - this->backend()->expression_statement(zero); - var_inits.push_back(Var_init(no, zero_stmt)); - } - - if (!is_sink && no->var_value()->type()->has_pointer()) - var_gc.push_back(no); - } - } - - // Register global variables with the garbage collector. - this->register_gc_vars(var_gc, &init_stmt_list); - - // Simple variable initializations, after all variables are - // registered. - append_to_statement_list(var_init_stmt_list, &init_stmt_list); - - // Complex variable initializations, first sorting them into a - // workable order. - if (!var_inits.empty()) - { - sort_var_inits(this, &var_inits); - for (Var_inits::const_iterator p = var_inits.begin(); - p != var_inits.end(); - ++p) - append_to_statement_list(stat_to_tree(p->init()), &init_stmt_list); - } - - // After all the variables are initialized, call the "init" - // functions if there are any. - for (std::vector<Named_object*>::const_iterator p = - this->init_functions_.begin(); - p != this->init_functions_.end(); - ++p) - { - tree decl = (*p)->get_tree(this, NULL); - tree call = build_call_expr(decl, 0); - append_to_statement_list(call, &init_stmt_list); - } - - // Set up a magic function to do all the initialization actions. - // This will be called if this package is imported. - if (init_stmt_list != NULL - || this->need_init_fn_ - || this->is_main_package()) - this->write_initialization_function(init_fndecl, init_stmt_list); - - // We should not have seen any new bindings created during the - // conversion. - go_assert(count_definitions == this->current_bindings()->size_definitions()); - - // Pass everything back to the middle-end. - - wrapup_global_declarations(vec, count); - - finalize_compilation_unit(); - - check_global_declarations(vec, count); - emit_debug_global_declarations(vec, count); - - delete[] vec; -} - -// Get a tree for a named object. - -tree -Named_object::get_tree(Gogo* gogo, Named_object* function) -{ - if (this->tree_ != NULL_TREE) - return this->tree_; - - if (Gogo::is_erroneous_name(this->name_)) - { - this->tree_ = error_mark_node; - return error_mark_node; - } - - tree decl; - switch (this->classification_) - { - case NAMED_OBJECT_CONST: - { - Translate_context subcontext(gogo, function, NULL, NULL); - Type* type = this->u_.const_value->type(); - Location loc = this->location(); - - Expression* const_ref = Expression::make_const_reference(this, loc); - Bexpression* const_decl = - tree_to_expr(const_ref->get_tree(&subcontext)); - if (type != NULL && type->is_numeric_type()) - { - Btype* btype = type->get_backend(gogo); - std::string name = this->get_id(gogo); - const_decl = - gogo->backend()->named_constant_expression(btype, name, - const_decl, loc); - } - decl = expr_to_tree(const_decl); - } - break; - - case NAMED_OBJECT_TYPE: - { - Named_type* named_type = this->u_.type_value; - tree type_tree = type_to_tree(named_type->get_backend(gogo)); - if (type_tree == error_mark_node) - decl = error_mark_node; - else - { - decl = TYPE_NAME(type_tree); - go_assert(decl != NULL_TREE); - - // We need to produce a type descriptor for every named - // type, and for a pointer to every named type, since - // other files or packages might refer to them. We need - // to do this even for hidden types, because they might - // still be returned by some function. Simply calling the - // type_descriptor method is enough to create the type - // descriptor, even though we don't do anything with it. - if (this->package_ == NULL) - { - named_type-> - type_descriptor_pointer(gogo, - Linemap::predeclared_location()); - Type* pn = Type::make_pointer_type(named_type); - pn->type_descriptor_pointer(gogo, - Linemap::predeclared_location()); - } - } - } - break; - - case NAMED_OBJECT_TYPE_DECLARATION: - error("reference to undefined type %qs", - this->message_name().c_str()); - return error_mark_node; - - case NAMED_OBJECT_VAR: - case NAMED_OBJECT_RESULT_VAR: - case NAMED_OBJECT_SINK: - go_unreachable(); - - case NAMED_OBJECT_FUNC: - { - Function* func = this->u_.func_value; - decl = function_to_tree(func->get_or_make_decl(gogo, this)); - if (decl != error_mark_node) - { - if (func->block() != NULL) - { - if (DECL_STRUCT_FUNCTION(decl) == NULL) - push_struct_function(decl); - else - push_cfun(DECL_STRUCT_FUNCTION(decl)); - - cfun->function_start_locus = func->location().gcc_location(); - cfun->function_end_locus = - func->block()->end_location().gcc_location(); - - func->build(gogo, this); - - gimplify_function_tree(decl); - - cgraph_finalize_function(decl, true); - - pop_cfun(); - } - } - } - break; - - case NAMED_OBJECT_ERRONEOUS: - decl = error_mark_node; - break; - - default: - go_unreachable(); - } - - if (TREE_TYPE(decl) == error_mark_node) - decl = error_mark_node; - - tree ret = decl; - - this->tree_ = ret; - - if (ret != error_mark_node) - go_preserve_from_gc(ret); - - return ret; -} - // Get the backend representation. Bfunction* @@ -1106,15 +282,6 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) return this->fndecl_; } -// Return the function's decl after it has been built. - -tree -Function::get_decl() const -{ - go_assert(this->fndecl_ != NULL); - return function_to_tree(this->fndecl_); -} - // Build the descriptor for a function declaration. This won't // necessarily happen if the package has just a declaration for the // function and no other reference to it, but we may still need the @@ -1214,55 +381,6 @@ go_type_for_mode(enum machine_mode mode, int unsignedp) return NULL_TREE; } -// Build a builtin struct with a list of fields. The name is -// STRUCT_NAME. STRUCT_TYPE is NULL_TREE or an empty RECORD_TYPE -// node; this exists so that the struct can have fields which point to -// itself. If PTYPE is not NULL, store the result in *PTYPE. There -// are NFIELDS fields. Each field is a name (a const char*) followed -// by a type (a tree). - -tree -Gogo::builtin_struct(tree* ptype, const char* struct_name, tree struct_type, - int nfields, ...) -{ - if (ptype != NULL && *ptype != NULL_TREE) - return *ptype; - - va_list ap; - va_start(ap, nfields); - - tree fields = NULL_TREE; - for (int i = 0; i < nfields; ++i) - { - const char* field_name = va_arg(ap, const char*); - tree type = va_arg(ap, tree); - if (type == error_mark_node) - { - if (ptype != NULL) - *ptype = error_mark_node; - return error_mark_node; - } - tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL, - get_identifier(field_name), type); - DECL_CHAIN(field) = fields; - fields = field; - } - - va_end(ap); - - if (struct_type == NULL_TREE) - struct_type = make_node(RECORD_TYPE); - finish_builtin_struct(struct_type, struct_name, fields, NULL_TREE); - - if (ptype != NULL) - { - go_preserve_from_gc(struct_type); - *ptype = struct_type; - } - - return struct_type; -} - // Build a constructor for a slice. SLICE_TYPE_TREE is the type of // the slice. VALUES is the value pointer and COUNT is the number of // entries. If CAPACITY is not NULL, it is the capacity; otherwise diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index ac9510ed9a6..c6ff9886090 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -575,6 +575,164 @@ Gogo::current_bindings() const return this->globals_; } +// Add statements to INIT_STMTS which run the initialization +// functions for imported packages. This is only used for the "main" +// package. + +void +Gogo::init_imports(std::vector<Bstatement*>& init_stmts) +{ + go_assert(this->is_main_package()); + + if (this->imported_init_fns_.empty()) + return; + + Location unknown_loc = Linemap::unknown_location(); + Function_type* func_type = + Type::make_function_type(NULL, NULL, NULL, unknown_loc); + Btype* fntype = func_type->get_backend_fntype(this); + + // We must call them in increasing priority order. + std::vector<Import_init> v; + for (std::set<Import_init>::const_iterator p = + this->imported_init_fns_.begin(); + p != this->imported_init_fns_.end(); + ++p) + v.push_back(*p); + std::sort(v.begin(), v.end()); + + // We build calls to the init functions, which take no arguments. + std::vector<Bexpression*> empty_args; + for (std::vector<Import_init>::const_iterator p = v.begin(); + p != v.end(); + ++p) + { + std::string user_name = p->package_name() + ".init"; + const std::string& init_name(p->init_name()); + + Bfunction* pfunc = this->backend()->function(fntype, user_name, init_name, + true, true, true, false, + false, unknown_loc); + Bexpression* pfunc_code = + this->backend()->function_code_expression(pfunc, unknown_loc); + Bexpression* pfunc_call = + this->backend()->call_expression(pfunc_code, empty_args, unknown_loc); + init_stmts.push_back(this->backend()->expression_statement(pfunc_call)); + } +} + +// Register global variables with the garbage collector. We need to +// register all variables which can hold a pointer value. They become +// roots during the mark phase. We build a struct that is easy to +// hook into a list of roots. + +// struct __go_gc_root_list +// { +// struct __go_gc_root_list* __next; +// struct __go_gc_root +// { +// void* __decl; +// size_t __size; +// } __roots[]; +// }; + +// The last entry in the roots array has a NULL decl field. + +void +Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc, + std::vector<Bstatement*>& init_stmts) +{ + if (var_gc.empty()) + return; + + Type* pvt = Type::make_pointer_type(Type::make_void_type()); + Type* uint_type = Type::lookup_integer_type("uint"); + Struct_type* root_type = Type::make_builtin_struct_type(2, + "__decl", pvt, + "__size", uint_type); + + Location builtin_loc = Linemap::predeclared_location(); + size_t count = var_gc.size(); + mpz_t lenval; + mpz_init_set_ui(lenval, count); + Expression* length = Expression::make_integer(&lenval, NULL, builtin_loc); + mpz_clear(lenval); + + Array_type* root_array_type = Type::make_array_type(root_type, length); + Type* ptdt = Type::make_type_descriptor_ptr_type(); + Struct_type* root_list_type = + Type::make_builtin_struct_type(2, + "__next", ptdt, + "__roots", root_array_type); + + // Build an initializer for the __roots array. + + Expression_list* roots_init = new Expression_list(); + + size_t i = 0; + for (std::vector<Named_object*>::const_iterator p = var_gc.begin(); + p != var_gc.end(); + ++p, ++i) + { + Expression_list* init = new Expression_list(); + + Location no_loc = (*p)->location(); + Expression* decl = Expression::make_var_reference(*p, no_loc); + Expression* decl_addr = + Expression::make_unary(OPERATOR_AND, decl, no_loc); + init->push_back(decl_addr); + + Expression* decl_size = + Expression::make_type_info(decl->type(), Expression::TYPE_INFO_SIZE); + init->push_back(decl_size); + + Expression* root_ctor = + Expression::make_struct_composite_literal(root_type, init, no_loc); + roots_init->push_back(root_ctor); + } + + // The list ends with a NULL entry. + + Expression_list* null_init = new Expression_list(); + Expression* nil = Expression::make_nil(builtin_loc); + null_init->push_back(nil); + + mpz_t zval; + mpz_init_set_ui(zval, 0UL); + Expression* zero = Expression::make_integer(&zval, NULL, builtin_loc); + mpz_clear(zval); + null_init->push_back(zero); + + Expression* null_root_ctor = + Expression::make_struct_composite_literal(root_type, null_init, + builtin_loc); + roots_init->push_back(null_root_ctor); + + // Build a constructor for the struct. + + Expression_list* root_list_init = new Expression_list(); + root_list_init->push_back(nil); + + Expression* roots_ctor = + Expression::make_array_composite_literal(root_array_type, roots_init, + builtin_loc); + root_list_init->push_back(roots_ctor); + + Expression* root_list_ctor = + Expression::make_struct_composite_literal(root_list_type, root_list_init, + builtin_loc); + + Expression* root_addr = Expression::make_unary(OPERATOR_AND, root_list_ctor, + builtin_loc); + root_addr->unary_expression()->set_is_gc_root(); + Expression* register_roots = Runtime::make_call(Runtime::REGISTER_GC_ROOTS, + builtin_loc, 1, root_addr); + + Translate_context context(this, NULL, NULL, NULL); + Bexpression* bcall = tree_to_expr(register_roots->get_tree(&context)); + init_stmts.push_back(this->backend()->expression_statement(bcall)); +} + // Get the name to use for the import control function. If there is a // global function or variable, then we know that that name must be // unique in the link, and we use it as the basis for our name. @@ -614,6 +772,521 @@ Gogo::initialization_function_decl() return Named_object::make_function(name, NULL, initfn); } +// Create the magic initialization function. CODE_STMT is the +// code that it needs to run. + +Named_object* +Gogo::create_initialization_function(Named_object* initfn, + Bstatement* code_stmt) +{ + // Make sure that we thought we needed an initialization function, + // as otherwise we will not have reported it in the export data. + go_assert(this->is_main_package() || this->need_init_fn_); + + if (initfn == NULL) + initfn = this->initialization_function_decl(); + + // Bind the initialization function code to a block. + Bfunction* fndecl = initfn->func_value()->get_or_make_decl(this, initfn); + Location pkg_loc = this->package_->location(); + std::vector<Bvariable*> vars; + this->backend()->block(fndecl, NULL, vars, pkg_loc, pkg_loc); + + if (!this->backend()->function_set_body(fndecl, code_stmt)) + { + go_assert(saw_errors()); + return NULL; + } + return initfn; +} + +// Search for references to VAR in any statements or called functions. + +class Find_var : public Traverse +{ + public: + // A hash table we use to avoid looping. The index is the name of a + // named object. We only look through objects defined in this + // package. + typedef Unordered_set(const void*) Seen_objects; + + Find_var(Named_object* var, Seen_objects* seen_objects) + : Traverse(traverse_expressions), + var_(var), seen_objects_(seen_objects), found_(false) + { } + + // Whether the variable was found. + bool + found() const + { return this->found_; } + + int + expression(Expression**); + + private: + // The variable we are looking for. + Named_object* var_; + // Names of objects we have already seen. + Seen_objects* seen_objects_; + // True if the variable was found. + bool found_; +}; + +// See if EXPR refers to VAR, looking through function calls and +// variable initializations. + +int +Find_var::expression(Expression** pexpr) +{ + Expression* e = *pexpr; + + Var_expression* ve = e->var_expression(); + if (ve != NULL) + { + Named_object* v = ve->named_object(); + if (v == this->var_) + { + this->found_ = true; + return TRAVERSE_EXIT; + } + + if (v->is_variable() && v->package() == NULL) + { + Expression* init = v->var_value()->init(); + if (init != NULL) + { + std::pair<Seen_objects::iterator, bool> ins = + this->seen_objects_->insert(v); + if (ins.second) + { + // This is the first time we have seen this name. + if (Expression::traverse(&init, this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } + } + } + } + + // We traverse the code of any function we see. Note that this + // means that we will traverse the code of a function whose address + // is taken even if it is not called. + Func_expression* fe = e->func_expression(); + if (fe != NULL) + { + const Named_object* f = fe->named_object(); + if (f->is_function() && f->package() == NULL) + { + std::pair<Seen_objects::iterator, bool> ins = + this->seen_objects_->insert(f); + if (ins.second) + { + // This is the first time we have seen this name. + if (f->func_value()->block()->traverse(this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } + } + } + + Temporary_reference_expression* tre = e->temporary_reference_expression(); + if (tre != NULL) + { + Temporary_statement* ts = tre->statement(); + Expression* init = ts->init(); + if (init != NULL) + { + std::pair<Seen_objects::iterator, bool> ins = + this->seen_objects_->insert(ts); + if (ins.second) + { + // This is the first time we have seen this temporary + // statement. + if (Expression::traverse(&init, this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } + } + } + + return TRAVERSE_CONTINUE; +} + +// Return true if EXPR, PREINIT, or DEP refers to VAR. + +static bool +expression_requires(Expression* expr, Block* preinit, Named_object* dep, + Named_object* var) +{ + Find_var::Seen_objects seen_objects; + Find_var find_var(var, &seen_objects); + if (expr != NULL) + Expression::traverse(&expr, &find_var); + if (preinit != NULL) + preinit->traverse(&find_var); + if (dep != NULL) + { + Expression* init = dep->var_value()->init(); + if (init != NULL) + Expression::traverse(&init, &find_var); + if (dep->var_value()->has_pre_init()) + dep->var_value()->preinit()->traverse(&find_var); + } + + return find_var.found(); +} + +// Sort variable initializations. If the initialization expression +// for variable A refers directly or indirectly to the initialization +// expression for variable B, then we must initialize B before A. + +class Var_init +{ + public: + Var_init() + : var_(NULL), init_(NULL) + { } + + Var_init(Named_object* var, Bstatement* init) + : var_(var), init_(init) + { } + + // Return the variable. + Named_object* + var() const + { return this->var_; } + + // Return the initialization expression. + Bstatement* + init() const + { return this->init_; } + + private: + // The variable being initialized. + Named_object* var_; + // The initialization statement. + Bstatement* init_; +}; + +typedef std::list<Var_init> Var_inits; + +// Sort the variable initializations. The rule we follow is that we +// emit them in the order they appear in the array, except that if the +// initialization expression for a variable V1 depends upon another +// variable V2 then we initialize V1 after V2. + +static void +sort_var_inits(Gogo* gogo, Var_inits* var_inits) +{ + typedef std::pair<Named_object*, Named_object*> No_no; + typedef std::map<No_no, bool> Cache; + Cache cache; + + Var_inits ready; + while (!var_inits->empty()) + { + Var_inits::iterator p1 = var_inits->begin(); + Named_object* var = p1->var(); + Expression* init = var->var_value()->init(); + Block* preinit = var->var_value()->preinit(); + Named_object* dep = gogo->var_depends_on(var->var_value()); + + // Start walking through the list to see which variables VAR + // needs to wait for. + Var_inits::iterator p2 = p1; + ++p2; + + for (; p2 != var_inits->end(); ++p2) + { + Named_object* p2var = p2->var(); + No_no key(var, p2var); + std::pair<Cache::iterator, bool> ins = + cache.insert(std::make_pair(key, false)); + if (ins.second) + ins.first->second = expression_requires(init, preinit, dep, p2var); + if (ins.first->second) + { + // Check for cycles. + key = std::make_pair(p2var, var); + ins = cache.insert(std::make_pair(key, false)); + if (ins.second) + ins.first->second = + expression_requires(p2var->var_value()->init(), + p2var->var_value()->preinit(), + gogo->var_depends_on(p2var->var_value()), + var); + if (ins.first->second) + { + error_at(var->location(), + ("initialization expressions for %qs and " + "%qs depend upon each other"), + var->message_name().c_str(), + p2var->message_name().c_str()); + inform(p2->var()->location(), "%qs defined here", + p2var->message_name().c_str()); + p2 = var_inits->end(); + } + else + { + // We can't emit P1 until P2 is emitted. Move P1. + Var_inits::iterator p3 = p2; + ++p3; + var_inits->splice(p3, *var_inits, p1); + } + break; + } + } + + if (p2 == var_inits->end()) + { + // VAR does not depends upon any other initialization expressions. + + // Check for a loop of VAR on itself. We only do this if + // INIT is not NULL and there is no dependency; when INIT is + // NULL, it means that PREINIT sets VAR, which we will + // interpret as a loop. + if (init != NULL && dep == NULL + && expression_requires(init, preinit, NULL, var)) + error_at(var->location(), + "initialization expression for %qs depends upon itself", + var->message_name().c_str()); + ready.splice(ready.end(), *var_inits, p1); + } + } + + // Now READY is the list in the desired initialization order. + var_inits->swap(ready); +} + +// Write out the global definitions. + +void +Gogo::write_globals() +{ + this->build_interface_method_tables(); + + Bindings* bindings = this->current_bindings(); + + for (Bindings::const_declarations_iterator p = bindings->begin_declarations(); + p != bindings->end_declarations(); + ++p) + { + // If any function declarations needed a descriptor, make sure + // we build it. + Named_object* no = p->second; + if (no->is_function_declaration()) + no->func_declaration_value()->build_backend_descriptor(this); + } + + // Lists of globally declared types, variables, constants, and functions + // that must be defined. + std::vector<Btype*> type_decls; + std::vector<Bvariable*> var_decls; + std::vector<Bexpression*> const_decls; + std::vector<Bfunction*> func_decls; + + // The init function declaration, if necessary. + Named_object* init_fndecl = NULL; + + std::vector<Bstatement*> init_stmts; + std::vector<Bstatement*> var_init_stmts; + + if (this->is_main_package()) + this->init_imports(init_stmts); + + // A list of variable initializations. + Var_inits var_inits; + + // A list of variables which need to be registered with the garbage + // collector. + size_t count_definitions = bindings->size_definitions(); + std::vector<Named_object*> var_gc; + var_gc.reserve(count_definitions); + + for (Bindings::const_definitions_iterator p = bindings->begin_definitions(); + p != bindings->end_definitions(); + ++p) + { + Named_object* no = *p; + go_assert(!no->is_type_declaration() && !no->is_function_declaration()); + + // There is nothing to do for a package. + if (no->is_package()) + continue; + + // There is nothing to do for an object which was imported from + // a different package into the global scope. + if (no->package() != NULL) + continue; + + // Skip blank named functions and constants. + if ((no->is_function() && no->func_value()->is_sink()) + || (no->is_const() && no->const_value()->is_sink())) + continue; + + // There is nothing useful we can output for constants which + // have ideal or non-integral type. + if (no->is_const()) + { + Type* type = no->const_value()->type(); + if (type == NULL) + type = no->const_value()->expr()->type(); + if (type->is_abstract() || !type->is_numeric_type()) + continue; + } + + if (!no->is_variable()) + no->get_backend(this, const_decls, type_decls, func_decls); + else + { + Variable* var = no->var_value(); + Bvariable* bvar = no->get_backend_variable(this, NULL); + var_decls.push_back(bvar); + + // Check for a sink variable, which may be used to run an + // initializer purely for its side effects. + bool is_sink = no->name()[0] == '_' && no->name()[1] == '.'; + + Bstatement* var_init_stmt = NULL; + if (!var->has_pre_init()) + { + Bexpression* var_binit = var->get_init(this, NULL); + + // If the backend representation of the variable initializer is + // constant, we can just set the initial value using + // global_var_set_init instead of during the init() function. + // The initializer is constant if it is the zero-value of the + // variable's type or if the initial value is an immutable value + // that is not copied to the heap. + bool is_constant_initializer = false; + if (var->init() == NULL) + is_constant_initializer = true; + else + { + Type* var_type = var->type(); + Expression* init = var->init(); + Expression* init_cast = + Expression::make_cast(var_type, init, var->location()); + is_constant_initializer = + init_cast->is_immutable() && !var_type->has_pointer(); + } + + if (var_binit == NULL) + ; + else if (is_constant_initializer) + { + if (expression_requires(var->init(), NULL, + this->var_depends_on(var), no)) + error_at(no->location(), + "initialization expression for %qs depends " + "upon itself", + no->message_name().c_str()); + this->backend()->global_variable_set_init(bvar, var_binit); + } + else if (is_sink) + var_init_stmt = + this->backend()->expression_statement(var_binit); + else + { + Location loc = var->location(); + Bexpression* var_expr = + this->backend()->var_expression(bvar, loc); + var_init_stmt = + this->backend()->assignment_statement(var_expr, var_binit, + loc); + } + } + else + { + // We are going to create temporary variables which + // means that we need an fndecl. + if (init_fndecl == NULL) + init_fndecl = this->initialization_function_decl(); + + Bvariable* var_decl = is_sink ? NULL : bvar; + var_init_stmt = var->get_init_block(this, init_fndecl, var_decl); + } + + if (var_init_stmt != NULL) + { + if (var->init() == NULL && !var->has_pre_init()) + var_init_stmts.push_back(var_init_stmt); + else + var_inits.push_back(Var_init(no, var_init_stmt)); + } + else if (this->var_depends_on(var) != NULL) + { + // This variable is initialized from something that is + // not in its init or preinit. This variable needs to + // participate in dependency analysis sorting, in case + // some other variable depends on this one. + Btype* btype = no->var_value()->type()->get_backend(this); + Bexpression* zero = this->backend()->zero_expression(btype); + Bstatement* zero_stmt = + this->backend()->expression_statement(zero); + var_inits.push_back(Var_init(no, zero_stmt)); + } + + if (!is_sink && var->type()->has_pointer()) + var_gc.push_back(no); + } + } + + // Register global variables with the garbage collector. + this->register_gc_vars(var_gc, init_stmts); + + // Simple variable initializations, after all variables are + // registered. + init_stmts.push_back(this->backend()->statement_list(var_init_stmts)); + + // Complete variable initializations, first sorting them into a + // workable order. + if (!var_inits.empty()) + { + sort_var_inits(this, &var_inits); + for (Var_inits::const_iterator p = var_inits.begin(); + p != var_inits.end(); + ++p) + init_stmts.push_back(p->init()); + } + + // After all the variables are initialized, call the init + // functions if there are any. Init functions take no arguments, so + // we pass in EMPTY_ARGS to call them. + std::vector<Bexpression*> empty_args; + for (std::vector<Named_object*>::const_iterator p = + this->init_functions_.begin(); + p != this->init_functions_.end(); + ++p) + { + Location func_loc = (*p)->location(); + Function* func = (*p)->func_value(); + Bfunction* initfn = func->get_or_make_decl(this, *p); + Bexpression* func_code = + this->backend()->function_code_expression(initfn, func_loc); + Bexpression* call = this->backend()->call_expression(func_code, + empty_args, + func_loc); + init_stmts.push_back(this->backend()->expression_statement(call)); + } + + // Set up a magic function to do all the initialization actions. + // This will be called if this package is imported. + Bstatement* init_fncode = this->backend()->statement_list(init_stmts); + if (this->need_init_fn_ || this->is_main_package()) + { + init_fndecl = + this->create_initialization_function(init_fndecl, init_fncode); + if (init_fndecl != NULL) + func_decls.push_back(init_fndecl->func_value()->get_decl()); + } + + // We should not have seen any new bindings created during the conversion. + go_assert(count_definitions == this->current_bindings()->size_definitions()); + + // Define all globally declared values. + if (!saw_errors()) + this->backend()->write_global_definitions(type_decls, const_decls, + func_decls, var_decls); +} + // Return the current block. Block* @@ -4182,6 +4855,15 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no) return this->fndecl_; } +// Return the function's decl after it has been built. + +Bfunction* +Function::get_decl() const +{ + go_assert(this->fndecl_ != NULL); + return this->fndecl_; +} + // Build the backend representation for the function code. void @@ -5266,8 +5948,7 @@ Variable::get_init_block(Gogo* gogo, Named_object* function, { Location loc = this->location(); Expression* val_expr = - Expression::convert_for_assignment(gogo, this->type(), - this->init_, this->location()); + Expression::make_cast(this->type(), this->init_, loc); Bexpression* val = tree_to_expr(val_expr->get_tree(&context)); Bexpression* var_ref = gogo->backend()->var_expression(var_decl, loc); decl_init = gogo->backend()->assignment_statement(var_ref, val, loc); @@ -5353,8 +6034,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function, } else { - tree fndecl = function->func_value()->get_decl(); - Bfunction* bfunction = tree_to_function(fndecl); + Bfunction* bfunction = function->func_value()->get_decl(); bool is_address_taken = (this->is_non_escaping_address_taken_ && !this->is_in_heap()); if (is_parameter) @@ -5391,8 +6071,7 @@ Result_variable::get_backend_variable(Gogo* gogo, Named_object* function, if (this->is_in_heap()) type = Type::make_pointer_type(type); Btype* btype = type->get_backend(gogo); - tree fndecl = function->func_value()->get_decl(); - Bfunction* bfunction = tree_to_function(fndecl); + Bfunction* bfunction = function->func_value()->get_decl(); std::string n = Gogo::unpack_hidden_name(name); bool is_address_taken = (this->is_non_escaping_address_taken_ && !this->is_in_heap()); @@ -5482,6 +6161,33 @@ Named_constant::import_const(Import* imp, std::string* pname, Type** ptype, imp->require_c_string(";\n"); } +// Get the backend representation. + +Bexpression* +Named_constant::get_backend(Gogo* gogo, Named_object* const_no) +{ + if (this->bconst_ == NULL) + { + Translate_context subcontext(gogo, NULL, NULL, NULL); + Type* type = this->type(); + Location loc = this->location(); + + Expression* const_ref = Expression::make_const_reference(const_no, loc); + Bexpression* const_decl = + tree_to_expr(const_ref->get_tree(&subcontext)); + if (type != NULL && type->is_numeric_type()) + { + Btype* btype = type->get_backend(gogo); + std::string name = const_no->get_id(gogo); + const_decl = + gogo->backend()->named_constant_expression(btype, name, + const_decl, loc); + } + this->bconst_ = const_decl; + } + return this->bconst_; +} + // Add a method. Named_object* @@ -5552,8 +6258,7 @@ Unknown_name::set_real_named_object(Named_object* no) Named_object::Named_object(const std::string& name, const Package* package, Classification classification) - : name_(name), package_(package), classification_(classification), - tree_(NULL) + : name_(name), package_(package), classification_(classification) { if (Gogo::is_sink_name(name)) go_assert(classification == NAMED_OBJECT_SINK); @@ -5928,6 +6633,72 @@ Named_object::get_id(Gogo* gogo) return decl_name; } +// Get the backend representation for this named object. + +void +Named_object::get_backend(Gogo* gogo, std::vector<Bexpression*>& const_decls, + std::vector<Btype*>& type_decls, + std::vector<Bfunction*>& func_decls) +{ + switch (this->classification_) + { + case NAMED_OBJECT_CONST: + if (!Gogo::is_erroneous_name(this->name_)) + const_decls.push_back(this->u_.const_value->get_backend(gogo, this)); + break; + + case NAMED_OBJECT_TYPE: + { + Named_type* named_type = this->u_.type_value; + if (!Gogo::is_erroneous_name(this->name_)) + type_decls.push_back(named_type->get_backend(gogo)); + + // We need to produce a type descriptor for every named + // type, and for a pointer to every named type, since + // other files or packages might refer to them. We need + // to do this even for hidden types, because they might + // still be returned by some function. Simply calling the + // type_descriptor method is enough to create the type + // descriptor, even though we don't do anything with it. + if (this->package_ == NULL) + { + named_type-> + type_descriptor_pointer(gogo, Linemap::predeclared_location()); + Type* pn = Type::make_pointer_type(named_type); + pn->type_descriptor_pointer(gogo, Linemap::predeclared_location()); + } + } + break; + + case NAMED_OBJECT_TYPE_DECLARATION: + error("reference to undefined type %qs", + this->message_name().c_str()); + return; + + case NAMED_OBJECT_VAR: + case NAMED_OBJECT_RESULT_VAR: + case NAMED_OBJECT_SINK: + go_unreachable(); + + case NAMED_OBJECT_FUNC: + { + Function* func = this->u_.func_value; + if (!Gogo::is_erroneous_name(this->name_)) + func_decls.push_back(func->get_or_make_decl(gogo, this)); + + if (func->block() != NULL) + func->build(gogo, this); + } + break; + + case NAMED_OBJECT_ERRONEOUS: + break; + + default: + go_unreachable(); + } +} + // Class Bindings. Bindings::Bindings(Bindings* enclosing) @@ -6400,8 +7171,7 @@ Label::get_backend_label(Translate_context* context) if (this->blabel_ == NULL) { Function* function = context->function()->func_value(); - tree fndecl = function->get_decl(); - Bfunction* bfunction = tree_to_function(fndecl); + Bfunction* bfunction = function->get_decl(); this->blabel_ = context->backend()->label(bfunction, this->name_, this->location_); } @@ -6427,8 +7197,7 @@ Unnamed_label::get_blabel(Translate_context* context) if (this->blabel_ == NULL) { Function* function = context->function()->func_value(); - tree fndecl = function->get_decl(); - Bfunction* bfunction = tree_to_function(fndecl); + Bfunction* bfunction = function->get_decl(); this->blabel_ = context->backend()->label(bfunction, "", this->location_); } diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index dd43d269f40..0be81b2aafe 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -44,6 +44,7 @@ class Backend; class Export; class Import; class Bexpression; +class Btype; class Bstatement; class Bblock; class Bvariable; @@ -591,11 +592,6 @@ class Gogo Expression* runtime_error(int code, Location); - // Build a builtin struct with a list of fields. - static tree - builtin_struct(tree* ptype, const char* struct_name, tree struct_type, - int nfields, ...); - // Mark a function declaration as a builtin library function. static void mark_fndecl_as_builtin_library(tree fndecl); @@ -650,17 +646,18 @@ class Gogo Named_object* initialization_function_decl(); - // Write the magic initialization function. - void - write_initialization_function(Named_object* fndecl, tree init_stmt_list); + // Create the magic initialization function. + Named_object* + create_initialization_function(Named_object* fndecl, Bstatement* code_stmt); // Initialize imported packages. void - init_imports(tree*); + init_imports(std::vector<Bstatement*>&); // Register variables with the garbage collector. void - register_gc_vars(const std::vector<Named_object*>&, tree*); + register_gc_vars(const std::vector<Named_object*>&, + std::vector<Bstatement*>&); // Type used to map import names to packages. typedef std::map<std::string, Package*> Imports; @@ -1086,7 +1083,7 @@ class Function get_or_make_decl(Gogo*, Named_object*); // Return the function's decl after it has been built. - tree + Bfunction* get_decl() const; // Set the function decl to hold a backend representation of the function @@ -1675,7 +1672,7 @@ class Named_constant Named_constant(Type* type, Expression* expr, int iota_value, Location location) : type_(type), expr_(expr), iota_value_(iota_value), location_(location), - lowering_(false), is_sink_(false) + lowering_(false), is_sink_(false), bconst_(NULL) { } Type* @@ -1737,6 +1734,10 @@ class Named_constant static void import_const(Import*, std::string*, Type**, Expression**); + // Get the backend representation of the constant value. + Bexpression* + get_backend(Gogo*, Named_object*); + private: // The type of the constant. Type* type_; @@ -1754,6 +1755,8 @@ class Named_constant bool lowering_; // Whether this constant is blank named and needs only type checking. bool is_sink_; + // The backend representation of the constant value. + Bexpression* bconst_; }; // A type declaration. @@ -2176,9 +2179,10 @@ class Named_object std::string get_id(Gogo*); - // Return a tree representing this object. - tree - get_tree(Gogo*, Named_object* function); + // Get the backend representation of this object. + void + get_backend(Gogo*, std::vector<Bexpression*>&, std::vector<Btype*>&, + std::vector<Bfunction*>&); // Define a type declaration. void @@ -2219,8 +2223,6 @@ class Named_object Function_declaration* func_declaration_value; Package* package_value; } u_; - // The DECL tree for this object if we have already converted it. - tree tree_; }; // A binding contour. This binds names to objects. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 49a864faa44..dabf1a83af6 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -434,15 +434,9 @@ Temporary_statement::do_get_backend(Translate_context* context) { go_assert(this->bvariable_ == NULL); - // FIXME: Permitting FUNCTION to be NULL here is a temporary measure - // until we have a better representation of the init function. Named_object* function = context->function(); - Bfunction* bfunction; - if (function == NULL) - bfunction = NULL; - else - bfunction = tree_to_function(function->func_value()->get_decl()); - + go_assert(function != NULL); + Bfunction* bfunction = function->func_value()->get_decl(); Btype* btype = this->type()->get_backend(context->gogo()); Bexpression* binit; @@ -2781,8 +2775,6 @@ Return_statement::do_get_backend(Translate_context* context) Location loc = this->location(); Function* function = context->function()->func_value(); - tree fndecl = function->get_decl(); - Function::Results* results = function->result_variables(); std::vector<Bexpression*> retvals; if (results != NULL && !results->empty()) @@ -2797,7 +2789,7 @@ Return_statement::do_get_backend(Translate_context* context) } } - return context->backend()->return_statement(tree_to_function(fndecl), + return context->backend()->return_statement(function->get_decl(), retvals, loc); } @@ -3803,8 +3795,10 @@ Constant_switch_statement::do_get_backend(Translate_context* context) this->clauses_->get_backend(context, break_label, &all_cases, &all_statements); + Bfunction* bfunction = context->function()->func_value()->get_decl(); Bstatement* switch_statement; - switch_statement = context->backend()->switch_statement(switch_val_expr, + switch_statement = context->backend()->switch_statement(bfunction, + switch_val_expr, all_cases, all_statements, this->location()); @@ -4980,7 +4974,9 @@ Select_clauses::get_backend(Translate_context* context, std::vector<Bstatement*> statements; statements.reserve(2); - Bstatement* switch_stmt = context->backend()->switch_statement(bcall, + Bfunction* bfunction = context->function()->func_value()->get_decl(); + Bstatement* switch_stmt = context->backend()->switch_statement(bfunction, + bcall, cases, clauses, location); diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c index 821f0846ef2..635e21a8519 100644 --- a/gcc/graphite-scop-detection.c +++ b/gcc/graphite-scop-detection.c @@ -474,8 +474,10 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop, result.exits = false; /* Mark bbs terminating a SESE region difficult, if they start - a condition. */ - if (!single_succ_p (bb)) + a condition or if the block it exits to cannot be split + with make_forwarder_block. */ + if (!single_succ_p (bb) + || bb_has_abnormal_pred (single_succ (bb))) result.difficult = true; else result.exit = single_succ (bb); diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 2d66e5cab6a..5d16b4d0f94 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -1299,7 +1299,7 @@ recompute_todo_spec (rtx next, bool for_backtrack) { HARD_REG_SET t; - find_all_hard_reg_sets (prev, &t); + find_all_hard_reg_sets (prev, &t, true); if (TEST_HARD_REG_BIT (t, regno)) return HARD_DEP; if (prev == pro) @@ -3082,7 +3082,7 @@ check_clobbered_conditions (rtx insn) if ((current_sched_info->flags & DO_PREDICATION) == 0) return; - find_all_hard_reg_sets (insn, &t); + find_all_hard_reg_sets (insn, &t, true); restart: for (i = 0; i < ready.n_ready; i++) diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 5411e00a3c4..a0f024a76ef 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1730,6 +1730,9 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) scan_array_reductions = true; + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR + && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)) + scan_array_reductions = true; break; case OMP_CLAUSE_SHARED: @@ -1816,6 +1819,9 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)) scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx); + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR + && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)) + scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx); } /* Create a new name for omp child function. Returns an identifier. */ @@ -3801,6 +3807,14 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list, OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)); OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL; } + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR + && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)) + { + lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx); + gimple_seq_add_seq (stmt_list, + OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)); + OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL; + } x = build_outer_var_ref (var, ctx); if (is_reference (var)) diff --git a/gcc/passes.c b/gcc/passes.c index 2be7856f29b..c0a76d62d21 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -132,7 +132,7 @@ opt_pass::opt_pass (const pass_data &data, context *ctxt) void pass_manager::execute_early_local_passes () { - execute_pass_list (pass_early_local_passes_1->sub); + execute_pass_list (cfun, pass_early_local_passes_1->sub); } unsigned int @@ -1498,27 +1498,17 @@ pass_manager::pass_manager (context *ctxt) call CALLBACK on the current function. */ static void -do_per_function (void (*callback) (void *data), void *data) +do_per_function (void (*callback) (function *, void *data), void *data) { if (current_function_decl) - callback (data); + callback (cfun, data); else { struct cgraph_node *node; FOR_EACH_DEFINED_FUNCTION (node) if (node->analyzed && gimple_has_body_p (node->decl) && (!node->clone_of || node->decl != node->clone_of->decl)) - { - push_cfun (DECL_STRUCT_FUNCTION (node->decl)); - callback (data); - if (!flag_wpa) - { - free_dominance_info (CDI_DOMINATORS); - free_dominance_info (CDI_POST_DOMINATORS); - } - pop_cfun (); - ggc_collect (); - } + callback (DECL_STRUCT_FUNCTION (node->decl), data); } } @@ -1533,12 +1523,12 @@ static GTY ((length ("nnodes"))) cgraph_node_ptr *order; call CALLBACK on the current function. This function is global so that plugins can use it. */ void -do_per_function_toporder (void (*callback) (void *data), void *data) +do_per_function_toporder (void (*callback) (function *, void *data), void *data) { int i; if (current_function_decl) - callback (data); + callback (cfun, data); else { gcc_assert (!order); @@ -1554,15 +1544,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data) order[i] = NULL; node->process = 0; if (cgraph_function_with_gimple_body_p (node)) - { - cgraph_get_body (node); - push_cfun (DECL_STRUCT_FUNCTION (node->decl)); - callback (data); - free_dominance_info (CDI_DOMINATORS); - free_dominance_info (CDI_POST_DOMINATORS); - pop_cfun (); - ggc_collect (); - } + callback (DECL_STRUCT_FUNCTION (node->decl), data); } } ggc_free (order); @@ -1573,14 +1555,16 @@ do_per_function_toporder (void (*callback) (void *data), void *data) /* Helper function to perform function body dump. */ static void -execute_function_dump (void *data) +execute_function_dump (function *fn, void *data) { opt_pass *pass = (opt_pass *)data; - if (dump_file && current_function_decl) + if (dump_file) { - if (cfun->curr_properties & PROP_trees) - dump_function_to_file (current_function_decl, dump_file, dump_flags); + push_cfun (fn); + + if (fn->curr_properties & PROP_trees) + dump_function_to_file (fn->decl, dump_file, dump_flags); else print_rtl_with_bb (dump_file, get_insns (), dump_flags); @@ -1588,7 +1572,7 @@ execute_function_dump (void *data) close the file before aborting. */ fflush (dump_file); - if ((cfun->curr_properties & PROP_cfg) + if ((fn->curr_properties & PROP_cfg) && (dump_flags & TDF_GRAPH)) { if (!pass->graph_dump_initialized) @@ -1596,8 +1580,10 @@ execute_function_dump (void *data) clean_graph_dump_file (dump_file_name); pass->graph_dump_initialized = true; } - print_graph_cfg (dump_file_name, cfun); + print_graph_cfg (dump_file_name, fn); } + + pop_cfun (); } } @@ -1728,13 +1714,15 @@ pass_manager::dump_profile_report () const /* Perform all TODO actions that ought to be done on each function. */ static void -execute_function_todo (void *data) +execute_function_todo (function *fn, void *data) { unsigned int flags = (size_t)data; - flags &= ~cfun->last_verified; + flags &= ~fn->last_verified; if (!flags) return; + push_cfun (fn); + /* Always cleanup the CFG before trying to update SSA. */ if (flags & TODO_cleanup_cfg) { @@ -1774,7 +1762,10 @@ execute_function_todo (void *data) /* If we've seen errors do not bother running any verifiers. */ if (seen_error ()) - return; + { + pop_cfun (); + return; + } #if defined ENABLE_CHECKING if (flags & TODO_verify_ssa @@ -1793,7 +1784,9 @@ execute_function_todo (void *data) verify_rtl_sharing (); #endif - cfun->last_verified = flags & TODO_verify_all; + fn->last_verified = flags & TODO_verify_all; + + pop_cfun (); } /* Perform all TODO actions. */ @@ -1855,9 +1848,9 @@ verify_interpass_invariants (void) /* Clear the last verified flag. */ static void -clear_last_verified (void *data ATTRIBUTE_UNUSED) +clear_last_verified (function *fn, void *data ATTRIBUTE_UNUSED) { - cfun->last_verified = 0; + fn->last_verified = 0; } /* Helper function. Verify that the properties has been turn into the @@ -1865,10 +1858,10 @@ clear_last_verified (void *data ATTRIBUTE_UNUSED) #ifdef ENABLE_CHECKING static void -verify_curr_properties (void *data) +verify_curr_properties (function *fn, void *data) { unsigned int props = (size_t)data; - gcc_assert ((cfun->curr_properties & props) == props); + gcc_assert ((fn->curr_properties & props) == props); } #endif @@ -1927,11 +1920,11 @@ pass_fini_dump_file (opt_pass *pass) properties. */ static void -update_properties_after_pass (void *data) +update_properties_after_pass (function *fn, void *data) { opt_pass *pass = (opt_pass *) data; - cfun->curr_properties = (cfun->curr_properties | pass->properties_provided) - & ~pass->properties_destroyed; + fn->curr_properties = (fn->curr_properties | pass->properties_provided) + & ~pass->properties_destroyed; } /* Execute summary generation for all of the passes in IPA_PASS. */ @@ -2039,20 +2032,6 @@ execute_all_ipa_transforms (void) } } -/* Callback for do_per_function to apply all IPA transforms. */ - -static void -apply_ipa_transforms (void *data) -{ - struct cgraph_node *node = cgraph_get_node (current_function_decl); - if (!node->global.inlined_to && node->ipa_transforms_to_apply.exists ()) - { - *(bool *)data = true; - execute_all_ipa_transforms (); - rebuild_cgraph_edges (); - } -} - /* Check if PASS is explicitly disabled or enabled and return the gate status. FUNC is the function to be processed, and GATE_STATUS is the gate status determined by pass manager by @@ -2124,8 +2103,26 @@ execute_one_pass (opt_pass *pass) Apply all trnasforms first. */ if (pass->type == SIMPLE_IPA_PASS) { + struct cgraph_node *node; bool applied = false; - do_per_function (apply_ipa_transforms, (void *)&applied); + FOR_EACH_DEFINED_FUNCTION (node) + if (node->analyzed + && cgraph_function_with_gimple_body_p (node) + && (!node->clone_of || node->decl != node->clone_of->decl)) + { + if (!node->global.inlined_to + && node->ipa_transforms_to_apply.exists ()) + { + cgraph_get_body (node); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + execute_all_ipa_transforms (); + rebuild_cgraph_edges (); + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + pop_cfun (); + applied = true; + } + } if (applied) symtab_remove_unreachable_nodes (true, dump_file); /* Restore current_pass. */ @@ -2202,20 +2199,33 @@ execute_one_pass (opt_pass *pass) return true; } -void -execute_pass_list (opt_pass *pass) +static void +execute_pass_list_1 (opt_pass *pass) { do { gcc_assert (pass->type == GIMPLE_PASS || pass->type == RTL_PASS); if (execute_one_pass (pass) && pass->sub) - execute_pass_list (pass->sub); + execute_pass_list_1 (pass->sub); pass = pass->next; } while (pass); } +void +execute_pass_list (function *fn, opt_pass *pass) +{ + push_cfun (fn); + execute_pass_list_1 (pass); + if (fn->cfg) + { + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + } + pop_cfun (); +} + /* Write out all LTO data. */ static void write_lto (void) @@ -2539,7 +2549,8 @@ execute_ipa_pass_list (opt_pass *pass) if (pass->sub->type == GIMPLE_PASS) { invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL); - do_per_function_toporder ((void (*)(void *))execute_pass_list, + do_per_function_toporder ((void (*)(function *, void *)) + execute_pass_list, pass->sub); invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL); } diff --git a/gcc/rtl.h b/gcc/rtl.h index cccb884ae88..f62c334351d 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2231,7 +2231,7 @@ extern const_rtx set_of (const_rtx, const_rtx); extern void record_hard_reg_sets (rtx, const_rtx, void *); extern void record_hard_reg_uses (rtx *, void *); #ifdef HARD_CONST -extern void find_all_hard_reg_sets (const_rtx, HARD_REG_SET *); +extern void find_all_hard_reg_sets (const_rtx, HARD_REG_SET *, bool); #endif extern void note_stores (const_rtx, void (*) (rtx, const_rtx, void *), void *); extern void note_uses (rtx *, void (*) (rtx *, void *), void *); diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 98c652894fb..82cfc1bf70b 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -1046,14 +1046,20 @@ record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data) /* Examine INSN, and compute the set of hard registers written by it. Store it in *PSET. Should only be called after reload. */ void -find_all_hard_reg_sets (const_rtx insn, HARD_REG_SET *pset) +find_all_hard_reg_sets (const_rtx insn, HARD_REG_SET *pset, bool implicit) { rtx link; CLEAR_HARD_REG_SET (*pset); note_stores (PATTERN (insn), record_hard_reg_sets, pset); if (CALL_P (insn)) - IOR_HARD_REG_SET (*pset, call_used_reg_set); + { + if (implicit) + IOR_HARD_REG_SET (*pset, call_used_reg_set); + + for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) + record_hard_reg_sets (XEXP (link, 0), NULL, pset); + } for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_INC) record_hard_reg_sets (XEXP (link, 0), NULL, pset); diff --git a/gcc/system.h b/gcc/system.h index 8b5089a28d7..b20b5cfde1d 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -1035,7 +1035,7 @@ helper_const_non_const_cast (const char *p) #endif #endif -#ifdef ENABLE_VALGRIND_CHECKING +#ifdef ENABLE_VALGRIND_ANNOTATIONS # ifdef HAVE_VALGRIND_MEMCHECK_H # include <valgrind/memcheck.h> # elif defined HAVE_MEMCHECK_H diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 70a0f89d592..261bb98a3a4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,10 +1,156 @@ -i2014-04-24 Alan Lawrence <alan.lawrence@arm.com> +2014-04-28 Richard Biener <rguenther@suse.de> + + * gcc.dg/tree-ssa/vrp91.c: New testcase. + * gcc.dg/Wstrict-overflow-14.c: XFAIL. + * gcc.dg/Wstrict-overflow-15.c: Likewise. + * gcc.dg/Wstrict-overflow-18.c: Remove XFAIL. + +2014-04-28 Richard Biener <rguenther@suse.de> + + PR tree-optimization/60979 + * gcc.dg/graphite/pr60979.c: New testcase. + +2014-04-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR c/60983 + * gcc.dg/pr60114.c: Use signed chars. + +2014-04-28 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/59120 + * g++.dg/cpp0x/alias-decl-43.C: New. + +2014-03-27 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/59604 + PR fortran/58003 + * gfortran.dg/no_range_check_3.f90: New test. + +2014-04-26 Jerry DeLisle <jvdelisle@gcc.gnu> + + PR libfortran/52539 + * gfortran.dg/namelist_utf8.f90: New test. + +2014-04-26 Uros Bizjak <ubizjak@gmail.com> + + * gcc.dg/tree-ssa/alias-30.c (dg-options): Dump only fre1 details. + * gcc.dg/vect/pr60505.c: Cleanup vect tree dump. + * g++.dg/ipa/devirt-27.C (dg-options): Remove -fdump-ipa-devirt. + +2014-04-25 Cary Coutant <ccoutant@google.com> + + PR debug/60929 + * g++.dg/debug/dwarf2/dwarf4-nested.C: New test case. + * g++.dg/debug/dwarf2/dwarf4-typedef.C: Add + -fdebug-types-section flag. + +2014-04-25 Jiong Wang <jiong.wang@arm.com> + + * gcc.target/arm/tail-long-call.c: New test. + +2014-04-25 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + PR tree-optimization/60930 + * gcc.dg/torture/pr60930.c: New test. + +2014-04-25 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/60960 + * gcc.c-torture/execute/pr60960.c: New test. + +2014-04-25 Marek Polacek <polacek@redhat.com> + + * gcc.dg/pr18079-2.c: Fix quoting in dg-warning. + +2014-04-25 Marek Polacek <polacek@redhat.com> + + PR c/18079 + * gcc.dg/pr18079.c: New test. + * gcc.dg/pr18079-2.c: New test. + +2014-04-25 Uros Bizjak <ubizjak@gmail.com> + + * c-c++-common/gomp/pr60823-2.c: Require effective target + vect_simd_clones. + +2014-04-25 Marek Polacek <polacek@redhat.com> + + PR c/60114 + * gcc.dg/pr60114.c: New test. + +2014-04-25 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.c-torture/execute/20140425-1.c: New test. + +2014-04-25 Marek Polacek <polacek@redhat.com> + + PR c/60156 + * c-c++-common/pr60156.c: New test. + +2014-04-25 Richard Biener <rguenther@suse.de> + + PR ipa/60912 + * g++.dg/opt/pr60912.C: New testcase. + +2014-04-25 Richard Biener <rguenther@suse.de> + + PR ipa/60911 + * gcc.dg/lto/pr60911_0.c: New testcase. + +2014-04-24 Cong Hou <congh@google.com> + + PR tree-optimization/60896 + * g++.dg/vect/pr60896.cc: New test. + +2014-04-24 Michael Meissner <meissner@linux.vnet.ibm.com> + + * gcc.target/powerpc/pack01.c: New test to test the new pack and + unpack builtin functionss for 128-bit types. + * gcc.target/powerpc/pack02.c: Likewise. + * gcc.target/powerpc/pack03.c: Likewise. + * gcc.target/powerpc/extend-divide-1.c: New test to test extended + divide builtin functionss. + * gcc.target/powerpc/extend-divide-2.c: Likewise. + * gcc.target/powerpc/bcd-1.c: New test for the new BCD builtin + functions. + * gcc.target/powerpc/bcd-2.c: Likewise. + * gcc.target/powerpc/bcd-3.c: Likewise. + * gcc.target/powerpc/dfp-builtin-1.c: New test for the new DFP + builtin functionss. + * gcc.target/powerpc/dfp-builtin-2.c: Likewise. + +2014-04-24 Vishnu K S <Vishnu.k_s@atmel.com> + + * gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c: Skip test if + keeps_null_pointer_checks. + * gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c: Ditto. + * gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c: Ditto. + * gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c: Ditto. + * gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c: Ditto. + +2014-04-24 Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/gomp/atomic-16.c: Remove all dg-error directives. + Replace load with read and store with write. + +2014-04-24 Jeff Law <law@redhat.com> + + PR target/60822 + * gcc.c-torture/pr60822.c: New test. + * gcc.c-torture/pr60822.x: New test. + +2014-04-24 Dinar Temirbulatov <dtemirbulatov@gmail.com> + + PR c++/57958 + * testsuite/g++.dg/cpp0x/pr57958.C: New test. + +2014-04-24 Alan Lawrence <alan.lawrence@arm.com> * lib/target-supports.exp (check_effective_target_vect_perm): Return true for aarch64_be. 2014-04-24 Radovan Obradovic <robradovic@mips.com> - Tom de Vries <tom@codesourcery.com> + Tom de Vries <tom@codesourcery.com> * gcc.dg/fuse-caller-save.c: New test. @@ -36,7 +182,7 @@ i2014-04-24 Alan Lawrence <alan.lawrence@arm.com> 2014-04-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com> - * gcc.target/aarch64/rev16_1.c: New test. + * gcc.target/aarch64/rev16_1.c: New test. 2014-04-23 Richard Biener <rguenther@suse.de> @@ -241,7 +387,7 @@ i2014-04-24 Alan Lawrence <alan.lawrence@arm.com> PR tree-optimization/60836 * g++.dg/vect/pr60836.cc: New testcase. -2014-04-17 Richard Biener <rguenther@suse.de> +2014-04-17 Richard Biener <rguenther@suse.de> PR tree-optimization/60841 * gcc.dg/vect/pr60841.c: New testcase. @@ -1924,8 +2070,7 @@ i2014-04-24 Alan Lawrence <alan.lawrence@arm.com> 2014-02-19 Paul Pluzhnikov <ppluzhnikov@google.com> - * gcc.dg/vect/no-vfa-vect-depend-2.c (main1): Fix buffer - overflow. + * gcc.dg/vect/no-vfa-vect-depend-2.c (main1): Fix buffer overflow. 2014-02-19 Jakub Jelinek <jakub@redhat.com> @@ -2234,8 +2379,7 @@ i2014-04-24 Alan Lawrence <alan.lawrence@arm.com> 2014-02-10 Jakub Jelinek <jakub@redhat.com> - * gcc.dg/vect/pr59984.c: Require effective target - vect_simd_clones. + * gcc.dg/vect/pr59984.c: Require effective target vect_simd_clones. 2014-02-09 Paul Thomas <pault@gcc.gnu.org> diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-16.c b/gcc/testsuite/c-c++-common/gomp/atomic-16.c index 87fbaa23317..9332396eaa5 100644 --- a/gcc/testsuite/c-c++-common/gomp/atomic-16.c +++ b/gcc/testsuite/c-c++-common/gomp/atomic-16.c @@ -7,28 +7,28 @@ void foo () { int v; - #pragma omp atomic seq_cst load /* { dg-error "expected end of line" } */ - v = x; /* { dg-error "invalid form" } */ - #pragma omp atomic seq_cst, load /* { dg-error "expected end of line" } */ - v = x; /* { dg-error "invalid form" } */ - #pragma omp atomic seq_cst store /* { dg-error "expected end of line" } */ - x = v; /* { dg-error "invalid form" } */ - #pragma omp atomic seq_cst ,store /* { dg-error "expected end of line" } */ - x = v; /* { dg-error "invalid form" } */ - #pragma omp atomic seq_cst update /* { dg-error "expected end of line" } */ + #pragma omp atomic seq_cst read + v = x; + #pragma omp atomic seq_cst, read + v = x; + #pragma omp atomic seq_cst write + x = v; + #pragma omp atomic seq_cst ,write + x = v; + #pragma omp atomic seq_cst update x += v; - #pragma omp atomic seq_cst , update /* { dg-error "expected end of line" } */ + #pragma omp atomic seq_cst , update x += v; - #pragma omp atomic seq_cst capture /* { dg-error "expected end of line" } */ - v = x += 2; /* { dg-error "invalid form" } */ - #pragma omp atomic seq_cst, capture /* { dg-error "expected end of line" } */ - v = x += 2; /* { dg-error "invalid form" } */ - #pragma omp atomic load , seq_cst /* { dg-error "expected end of line" } */ - v = x; /* { dg-error "invalid form" } */ - #pragma omp atomic store ,seq_cst /* { dg-error "expected end of line" } */ - x = v; /* { dg-error "invalid form" } */ - #pragma omp atomic update, seq_cst /* { dg-error "expected end of line" } */ + #pragma omp atomic seq_cst capture + v = x += 2; + #pragma omp atomic seq_cst, capture + v = x += 2; + #pragma omp atomic read , seq_cst + v = x; + #pragma omp atomic write ,seq_cst + x = v; + #pragma omp atomic update, seq_cst x += v; - #pragma omp atomic capture, seq_cst /* { dg-error "expected end of line" } */ + #pragma omp atomic capture, seq_cst v = x += 2; } diff --git a/gcc/testsuite/c-c++-common/gomp/pr60823-2.c b/gcc/testsuite/c-c++-common/gomp/pr60823-2.c index e0bf570ddca..4c87620076a 100644 --- a/gcc/testsuite/c-c++-common/gomp/pr60823-2.c +++ b/gcc/testsuite/c-c++-common/gomp/pr60823-2.c @@ -1,5 +1,6 @@ /* PR tree-optimization/60823 */ /* { dg-do run } */ +/* { dg-require-effective-target vect_simd_clones } */ /* { dg-options "-O2 -fopenmp-simd" } */ #pragma omp declare simd simdlen(4) notinbranch diff --git a/gcc/testsuite/c-c++-common/pr60156.c b/gcc/testsuite/c-c++-common/pr60156.c new file mode 100644 index 00000000000..1e8204c99c7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr60156.c @@ -0,0 +1,9 @@ +/* PR c/60156 */ +/* { dg-do compile } */ +/* { dg-options "-Wpedantic" } */ + +int +main (int argc, char *argv[], ...) /* { dg-warning "declared as variadic function" } */ +{ + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-43.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-43.C new file mode 100644 index 00000000000..02eb33643ac --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-43.C @@ -0,0 +1,4 @@ +// PR c++/59120 +// { dg-do compile { target c++11 } } + +template<typename T> using X = int T::T*; // { dg-error "expected" } diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-nested.C b/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-nested.C new file mode 100644 index 00000000000..160694c3c9f --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-nested.C @@ -0,0 +1,55 @@ +// { dg-do compile } +// { dg-options "--std=c++11 -dA -gdwarf-4 -fdebug-types-section -fno-merge-debug-strings" } + +// Check that -fdebug-types-sections does not copy a full referenced type +// into a type unit. + +// Checks that at least one type unit is generated. +// +// { dg-final { scan-assembler "DIE \\(\[^\n\]*\\) DW_TAG_type_unit" } } +// +// Check that func is declared exactly once in the debug info (in the +// compile unit). +// +// { dg-final { scan-assembler-times "\\.ascii \"func\\\\0\"\[^\n\]*DW_AT_name" 1 } } +// +// Check to make sure that no type unit contains a DIE with DW_AT_low_pc +// or DW_AT_ranges. These patterns assume that the compile unit is always +// emitted after all type units. +// +// { dg-final { scan-assembler-not "\\.quad\[^\n\]*DW_AT_low_pc.*DIE \\(\[^\n\]*\\) DW_TAG_compile_unit" } } +// { dg-final { scan-assembler-not "\\.quad\[^\n\]*DW_AT_ranges.*DIE \\(\[^\n\]*\\) DW_TAG_compile_unit" } } + +struct A { + A(); + virtual ~A(); + virtual void foo(); + private: + int data; +}; + +struct B { + B(); + virtual ~B(); +}; + +extern B* table[]; + +struct D { + template <typename T> + T* get(int i) + { + B*& cell = table[i]; + if (cell == 0) + cell = new T(); + return static_cast<T*>(cell); + } +}; + +void func(D* d) +{ + struct C : B { + A a; + }; + d->get<C>(0)->a.foo(); +} diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C b/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C index c5520fa72b0..89a6bb44e10 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-gdwarf-4" } */ +/* { dg-options "-gdwarf-4 -fdebug-types-section" } */ /* Regression test for an ICE in output_die when using -gdwarf-4. */ diff --git a/gcc/testsuite/g++.dg/ipa/devirt-27.C b/gcc/testsuite/g++.dg/ipa/devirt-27.C index 1dcf76cc3c1..749f40af151 100644 --- a/gcc/testsuite/g++.dg/ipa/devirt-27.C +++ b/gcc/testsuite/g++.dg/ipa/devirt-27.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -fdump-ipa-devirt -fdump-tree-optimized" } */ +/* { dg-options "-O3 -fdump-tree-optimized" } */ struct A { int a; diff --git a/gcc/testsuite/g++.dg/opt/pr60912.C b/gcc/testsuite/g++.dg/opt/pr60912.C new file mode 100644 index 00000000000..ad51ba72570 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr60912.C @@ -0,0 +1,18 @@ +// { dg-do run } +// { dg-options "-O -fno-inline -fipa-pta" } + +struct IFoo +{ + virtual void Foo () = 0; +}; + +struct Bar:IFoo +{ + void Foo () {} +}; + +int main () +{ + (new Bar ())->Foo (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/vect/pr60896.cc b/gcc/testsuite/g++.dg/vect/pr60896.cc new file mode 100644 index 00000000000..c6ce68b82a2 --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/pr60896.cc @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +struct A +{ + int m_fn1 (); + short *m_fn2 (); +}; + +struct B +{ + void *fC; +}; + +int a, b; +unsigned char i; +void fn1 (unsigned char *p1, A &p2) +{ + int c = p2.m_fn1 (); + for (int d = 0; c; d++) + { + short *e = p2.m_fn2 (); + unsigned char *f = &p1[0]; + for (int g = 0; g < a; g++) + { + int h = e[0]; + b += h * f[g]; + } + } +} + +void fn2 (A &p1, A &p2, B &p3) +{ + int j = p2.m_fn1 (); + for (int k = 0; j; k++) + if (0) + ; + else + fn1 (&i, p1); + if (p3.fC) + ; + else + ; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/20140425-1.c b/gcc/testsuite/gcc.c-torture/execute/20140425-1.c new file mode 100644 index 00000000000..c447ef95b6c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20140425-1.c @@ -0,0 +1,23 @@ +/* PR target/60941 */ +/* Reported by Martin Husemann <martin@netbsd.org> */ + +extern void abort (void); + +static void __attribute__((noinline)) +set (unsigned long *l) +{ + *l = 31; +} + +int main (void) +{ + unsigned long l; + int i; + + set (&l); + i = (int) l; + l = (unsigned long)(2U << i); + if (l != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60822.c b/gcc/testsuite/gcc.c-torture/execute/pr60822.c new file mode 100644 index 00000000000..d2253310e69 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr60822.c @@ -0,0 +1,24 @@ +struct X { + char fill0[800000]; + int a; + char fill1[900000]; + int b; +}; + +int __attribute__((noinline,noclone)) +Avg(struct X *p, int s) +{ + return (s * (long long)(p->a + p->b)) >> 17; +} + +struct X x; + +int main() +{ + x.a = 1 << 17; + x.b = 2 << 17; + if (Avg(&x, 1) != 3) + __builtin_abort(); + return 0; +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60822.x b/gcc/testsuite/gcc.c-torture/execute/pr60822.x new file mode 100644 index 00000000000..4efed4c325f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr60822.x @@ -0,0 +1,7 @@ +load_lib target-supports.exp + +if { [check_effective_target_int32plus] } { + return 0 +} + +return 1; diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60960.c b/gcc/testsuite/gcc.c-torture/execute/pr60960.c new file mode 100644 index 00000000000..b4f08d4c543 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr60960.c @@ -0,0 +1,38 @@ +/* PR tree-optimization/60960 */ + +typedef unsigned char v4qi __attribute__ ((vector_size (4))); + +__attribute__((noinline, noclone)) v4qi +f1 (v4qi v) +{ + return v / 2; +} + +__attribute__((noinline, noclone)) v4qi +f2 (v4qi v) +{ + return v / (v4qi) { 2, 2, 2, 2 }; +} + +__attribute__((noinline, noclone)) v4qi +f3 (v4qi x, v4qi y) +{ + return x / y; +} + +int +main () +{ + v4qi x = { 5, 5, 5, 5 }; + v4qi y = { 2, 2, 2, 2 }; + v4qi z = f1 (x); + if (__builtin_memcmp (&y, &z, sizeof (y)) != 0) + __builtin_abort (); + z = f2 (x); + if (__builtin_memcmp (&y, &z, sizeof (y)) != 0) + __builtin_abort (); + z = f3 (x, y); + if (__builtin_memcmp (&y, &z, sizeof (y)) != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c index 6f3c5a24fd1..dda07ea733b 100644 --- a/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c +++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c @@ -10,6 +10,6 @@ foo (int j) int sum = 0; for (i = 1; i < j; i += i) - sum += i / 16; /* { dg-warning "assuming signed overflow does not occur" "" } */ + sum += i / 16; /* { dg-warning "assuming signed overflow does not occur" "" { xfail *-*-* } } */ return sum; } diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c index d1627d2f47b..c9e275c0bd6 100644 --- a/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c +++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c @@ -10,6 +10,6 @@ foo (int j) int sum = 0; for (i = 1; i < j; i += i) - sum += __builtin_abs (i); /* { dg-warning "assuming signed overflow does not occur" "" } */ + sum += __builtin_abs (i); /* { dg-warning "assuming signed overflow does not occur" "" { xfail *-*-* } } */ return sum; } diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c index 2767c44fbf2..7bf111a50ea 100644 --- a/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c +++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c @@ -17,7 +17,7 @@ foo (struct c *p) for (i = 0; i < p->a - p->b; ++i) { - if (i > 0) /* { dg-bogus "warning" "" { xfail *-*-* } } */ + if (i > 0) /* { dg-bogus "warning" "" } */ sum += 2; bar (p); } diff --git a/gcc/testsuite/gcc.dg/graphite/pr60979.c b/gcc/testsuite/gcc.dg/graphite/pr60979.c new file mode 100644 index 00000000000..0004a51248d --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr60979.c @@ -0,0 +1,37 @@ +/* { dg-options "-O -fgraphite-identity" } */ + +#include <setjmp.h> + +struct x; + +typedef struct x **(*a)(struct x *); + +struct x { + union { + struct { + union { + a *i; + } l; + int s; + } y; + } e; +}; + +jmp_buf c; + +void +b(struct x *r) +{ + int f; + static int w = 0; + volatile jmp_buf m; + f = (*(((struct x *)r)->e.y.l.i[2]((struct x *)r)))->e.y.s; + if (w++ != 0) + __builtin_memcpy((char *)m, (const char *)c, sizeof(jmp_buf)); + if (setjmp (c) == 0) { + int z; + for (z = 0; z < 0; ++z) + ; + } + d((const char *)m); +} diff --git a/gcc/testsuite/gcc.dg/lto/pr60911_0.c b/gcc/testsuite/gcc.dg/lto/pr60911_0.c new file mode 100644 index 00000000000..e4820a20497 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr60911_0.c @@ -0,0 +1,21 @@ +// { dg-lto-do run } +// { dg-lto-options { { -O2 -flto -fipa-pta } } } + +int __attribute__ ((__noinline__)) f (unsigned *p, int *x) +{ + int y = *p++ & 0xfff; + *x++ = y; + *x = *p; + return y; +} + +int +main () +{ + unsigned u[2] = { 0x3aad, 0x5ad1 }; + int x[2] = { 17689, 23456 }; + + if (f (u, x) != 0xaad || x[0] != 0xaad || x[1] != 0x5ad1) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr18079-2.c b/gcc/testsuite/gcc.dg/pr18079-2.c new file mode 100644 index 00000000000..2c83b701e10 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr18079-2.c @@ -0,0 +1,16 @@ +/* PR c/18079 */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +__attribute__ ((always_inline)) void fndecl1 (void); +__attribute__ ((noinline)) void fndecl1 (void); /* { dg-warning "attribute 'noinline' follows declaration with attribute 'always_inline'" } */ + +__attribute__ ((noinline)) void fndecl2 (void); +__attribute__ ((always_inline)) void fndecl2 (void); /* { dg-warning "attribute 'always_inline' follows declaration with attribute 'noinline'" } */ + + +__attribute__ ((hot)) void fndecl3 (void); +__attribute__ ((cold)) void fndecl3 (void); /* { dg-warning "attribute 'cold' follows declaration with attribute 'hot'" } */ + +__attribute__ ((cold)) void fndecl4 (void); +__attribute__ ((hot)) void fndecl4 (void); /* { dg-warning "attribute 'hot' follows declaration with attribute 'cold'" } */ diff --git a/gcc/testsuite/gcc.dg/pr18079.c b/gcc/testsuite/gcc.dg/pr18079.c new file mode 100644 index 00000000000..b84cdebde3f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr18079.c @@ -0,0 +1,33 @@ +/* PR c/18079 */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +__attribute__ ((noinline)) +__attribute__ ((always_inline)) +int +fn1 (int r) +{ /* { dg-warning "attribute ignored due to conflict" } */ + return r & 4; +} + +__attribute__ ((noinline, always_inline)) +int +fn2 (int r) +{ /* { dg-warning "attribute ignored due to conflict" } */ + return r & 4; +} + +__attribute__ ((always_inline)) +__attribute__ ((noinline)) +inline int +fn3 (int r) +{ /* { dg-warning "attribute ignored due to conflict" } */ + return r & 8; +} + +__attribute__ ((always_inline, noinline)) +inline int +fn4 (int r) +{ /* { dg-warning "attribute ignored due to conflict" } */ + return r & 8; +} diff --git a/gcc/testsuite/gcc.dg/pr60114.c b/gcc/testsuite/gcc.dg/pr60114.c new file mode 100644 index 00000000000..c656a9586aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr60114.c @@ -0,0 +1,31 @@ +/* PR c/60114 */ +/* { dg-do compile } */ +/* { dg-options "-Wconversion" } */ + +struct S { int n, u[2]; }; +const signed char z[] = { + [0] = 0x100, /* { dg-warning "9:overflow in implicit constant conversion" } */ + [2] = 0x101, /* { dg-warning "9:overflow in implicit constant conversion" } */ +}; +int A[] = { + 0, 0x80000000, /* { dg-warning "16:conversion of unsigned constant value to negative integer" } */ + 0xA, 0x80000000, /* { dg-warning "18:conversion of unsigned constant value to negative integer" } */ + 0xA, 0xA, 0x80000000 /* { dg-warning "23:conversion of unsigned constant value to negative integer" } */ + }; +int *p = (int []) { 0x80000000 }; /* { dg-warning "21:conversion of unsigned constant value to negative integer" } */ +union { int k; } u = { .k = 0x80000000 }; /* { dg-warning "29:conversion of unsigned constant value to negative integer" } */ +typedef int H[]; +void +foo (void) +{ + signed char a[][3] = { { 0x100, /* { dg-warning "28:overflow in implicit constant conversion" } */ + 1, 0x100 }, /* { dg-warning "24:overflow in implicit constant conversion" } */ + { '\0', 0x100, '\0' } /* { dg-warning "27:overflow in implicit constant conversion" } */ + }; + (const signed char []) { 0x100 }; /* { dg-warning "28:overflow in implicit constant conversion" } */ + (const float []) { 1e0, 1e1, 1e100 }; /* { dg-warning "32:conversion" } */ + struct S s1 = { 0x80000000 }; /* { dg-warning "19:conversion of unsigned constant value to negative integer" } */ + struct S s2 = { .n = 0x80000000 }; /* { dg-warning "24:conversion of unsigned constant value to negative integer" } */ + struct S s3 = { .u[1] = 0x80000000 }; /* { dg-warning "27:conversion of unsigned constant value to negative integer" } */ + H h = { 1, 2, 0x80000000 }; /* { dg-warning "17:conversion of unsigned constant value to negative integer" } */ +} diff --git a/gcc/testsuite/gcc.dg/torture/pr60930.c b/gcc/testsuite/gcc.dg/torture/pr60930.c new file mode 100644 index 00000000000..5e35f19882d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr60930.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ + +int x = 1; + +__attribute__((noinline, noclone)) void +foo (unsigned long long t) +{ + asm volatile ("" : : "r" (&t)); + if (t == 1) + __builtin_abort (); +} + +int +main () +{ +#if __SIZEOF_LONG_LONG__ >= 8 + unsigned long long t = 0xffffffffffffffffULL * (0xffffffffUL * x); + if (t != 0xffffffff00000001ULL) + foo (t);; +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-30.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-30.c index addf1284057..7ef830d1937 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/alias-30.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-30.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-fre-details" } */ +/* { dg-options "-O -fdump-tree-fre1-details" } */ extern int posix_memalign(void **memptr, __SIZE_TYPE__ alignment, __SIZE_TYPE__ size); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c index f1f3101d3d2..3ed98aeb857 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c @@ -1,6 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-isolate-paths" } */ +/* { dg-skip-if "" keeps_null_pointer_checks } */ struct demangle_component diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c index bfcaa2b01da..912d98e2246 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fisolate-erroneous-paths-attribute -fdump-tree-isolate-paths -fdump-tree-phicprop1" } */ +/* { dg-skip-if "" keeps_null_pointer_checks } */ int z; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c index 7dddd8062c0..9c2c5d55c27 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-isolate-paths" } */ +/* { dg-skip-if "" keeps_null_pointer_checks } */ typedef long unsigned int size_t; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c index c9c074df62b..d50a2b27f47 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fisolate-erroneous-paths-attribute -fdump-tree-isolate-paths -fdump-tree-phicprop1" } */ +/* { dg-skip-if "" keeps_null_pointer_checks } */ extern void foo(void *) __attribute__ ((__nonnull__ (1))); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c index 4d01d5c6399..e6ae37a7f74 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-isolate-paths -fdump-tree-optimized" } */ +/* { dg-skip-if "" keeps_null_pointer_checks } */ struct demangle_component { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c new file mode 100644 index 00000000000..68d8fd33a0b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp91.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-S -O2 -fdump-tree-vrp2" } */ + +unsigned short data; +void foo () +{ + unsigned char x16; + unsigned int i; + for (i = 0; i < 8; i++) + { + x16 = data & 1; + data >>= 1; + if (x16 == 1) + { + data ^= 0x4; + } + data >>= 1; + } +} + +/* { dg-final { scan-tree-dump "\\\[0, 7\\\]" "vrp2" } } */ +/* { dg-final { cleanup-tree-dump "vrp2" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr60505.c b/gcc/testsuite/gcc.dg/vect/pr60505.c index 694051320ce..70e2ec06fe5 100644 --- a/gcc/testsuite/gcc.dg/vect/pr60505.c +++ b/gcc/testsuite/gcc.dg/vect/pr60505.c @@ -10,3 +10,5 @@ void foo(char *in, char *out, int num) out[i] = (ovec[i] = in[i]); out[num] = ovec[num/2]; } + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.target/arm/tail-long-call.c b/gcc/testsuite/gcc.target/arm/tail-long-call.c new file mode 100644 index 00000000000..9b274686849 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/tail-long-call.c @@ -0,0 +1,12 @@ +/* { dg-skip-if "need at least armv5te" { *-*-* } { "-march=armv[234]*" "-mthumb" } { "" } } */ +/* { dg-options "-O2 -march=armv5te -marm" } */ +/* { dg-final { scan-assembler "bx" } } */ +/* { dg-final { scan-assembler-not "blx" } } */ + +int lcal (int) __attribute__ ((long_call)); + +int +dec (int a) +{ + return lcal (a); +} diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-1.c b/gcc/testsuite/gcc.target/powerpc/bcd-1.c new file mode 100644 index 00000000000..c7496c23579 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/bcd-1.c @@ -0,0 +1,27 @@ +/* { dg-do compile { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-mcpu=power7 -O2" } */ +/* { dg-final { scan-assembler-times "cdtbcd " 1 } } */ +/* { dg-final { scan-assembler-times "cbcdtd " 1 } } */ +/* { dg-final { scan-assembler-times "addg6s " 1 } } */ +/* { dg-final { scan-assembler-not "bl __builtin" } } */ + +unsigned int +to_bcd (unsigned int a) +{ + return __builtin_cdtbcd (a); +} + +unsigned int +from_bcd (unsigned int a) +{ + return __builtin_cbcdtd (a); +} + +unsigned int +bcd_arith (unsigned int a, unsigned int b) +{ + return __builtin_addg6s (a, b); +} diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-2.c b/gcc/testsuite/gcc.target/powerpc/bcd-2.c new file mode 100644 index 00000000000..d330b742376 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/bcd-2.c @@ -0,0 +1,44 @@ +/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mcpu=power8 -O2" } */ +/* { dg-final { scan-assembler-times "bcdadd\[.\] " 2 } } */ +/* { dg-final { scan-assembler-times "bcdsub\[.\] " 2 } } */ +/* { dg-final { scan-assembler-not "bl __builtin" } } */ +/* { dg-final { scan-assembler-not "mtvsr" } } */ +/* { dg-final { scan-assembler-not "mfvsr" } } */ +/* { dg-final { scan-assembler-not "lvx" } } */ +/* { dg-final { scan-assembler-not "lxvw4x" } } */ +/* { dg-final { scan-assembler-not "lxvd2x" } } */ +/* { dg-final { scan-assembler-not "stvx" } } */ +/* { dg-final { scan-assembler-not "stxvw4x" } } */ +/* { dg-final { scan-assembler-not "stxvd2x" } } */ + +typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t; +typedef __int128_t scalar_128_t; +typedef unsigned long long scalar_64_t; + +vector_128_t +do_add_0 (vector_128_t a, vector_128_t b) +{ + return __builtin_bcdadd (a, b, 0); +} + +vector_128_t +do_add_1 (vector_128_t a, vector_128_t b) +{ + return __builtin_bcdadd (a, b, 1); +} + +vector_128_t +do_sub_0 (vector_128_t a, vector_128_t b) +{ + return __builtin_bcdsub (a, b, 0); +} + +vector_128_t +do_sub_1 (vector_128_t a, vector_128_t b) +{ + return __builtin_bcdsub (a, b, 1); +} diff --git a/gcc/testsuite/gcc.target/powerpc/bcd-3.c b/gcc/testsuite/gcc.target/powerpc/bcd-3.c new file mode 100644 index 00000000000..436cecf6fff --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/bcd-3.c @@ -0,0 +1,103 @@ +/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mcpu=power8 -O2" } */ +/* { dg-final { scan-assembler-times "bcdadd\[.\] " 4 } } */ +/* { dg-final { scan-assembler-times "bcdsub\[.\] " 4 } } */ +/* { dg-final { scan-assembler-not "bl __builtin" } } */ +/* { dg-final { scan-assembler-not "mtvsr" } } */ +/* { dg-final { scan-assembler-not "mfvsr" } } */ +/* { dg-final { scan-assembler-not "lvx" } } */ +/* { dg-final { scan-assembler-not "lxvw4x" } } */ +/* { dg-final { scan-assembler-not "lxvd2x" } } */ +/* { dg-final { scan-assembler-not "stvx" } } */ +/* { dg-final { scan-assembler-not "stxvw4x" } } */ +/* { dg-final { scan-assembler-not "stxvd2x" } } */ + +typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t; +typedef __int128_t scalar_128_t; +typedef unsigned long long scalar_64_t; + +/* Test whether the peephole works to allow folding a bcdadd, with a + bcdadd_<test> into a single instruction. */ + +vector_128_t +do_add_lt (vector_128_t a, vector_128_t b, int *p) +{ + vector_128_t ret = __builtin_bcdadd (a, b, 0); + if (__builtin_bcdadd_lt (a, b, 0)) + *p = 1; + + return ret; +} + +vector_128_t +do_add_eq (vector_128_t a, vector_128_t b, int *p) +{ + vector_128_t ret = __builtin_bcdadd (a, b, 0); + if (__builtin_bcdadd_eq (a, b, 0)) + *p = 1; + + return ret; +} + +vector_128_t +do_add_gt (vector_128_t a, vector_128_t b, int *p) +{ + vector_128_t ret = __builtin_bcdadd (a, b, 0); + if (__builtin_bcdadd_gt (a, b, 0)) + *p = 1; + + return ret; +} + +vector_128_t +do_add_ov (vector_128_t a, vector_128_t b, int *p) +{ + vector_128_t ret = __builtin_bcdadd (a, b, 0); + if (__builtin_bcdadd_ov (a, b, 0)) + *p = 1; + + return ret; +} + +vector_128_t +do_sub_lt (vector_128_t a, vector_128_t b, int *p) +{ + vector_128_t ret = __builtin_bcdsub (a, b, 0); + if (__builtin_bcdsub_lt (a, b, 0)) + *p = 1; + + return ret; +} + +vector_128_t +do_sub_eq (vector_128_t a, vector_128_t b, int *p) +{ + vector_128_t ret = __builtin_bcdsub (a, b, 0); + if (__builtin_bcdsub_eq (a, b, 0)) + *p = 1; + + return ret; +} + +vector_128_t +do_sub_gt (vector_128_t a, vector_128_t b, int *p) +{ + vector_128_t ret = __builtin_bcdsub (a, b, 0); + if (__builtin_bcdsub_gt (a, b, 0)) + *p = 1; + + return ret; +} + +vector_128_t +do_sub_ov (vector_128_t a, vector_128_t b, int *p) +{ + vector_128_t ret = __builtin_bcdsub (a, b, 0); + if (__builtin_bcdsub_ov (a, b, 0)) + *p = 1; + + return ret; +} diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c new file mode 100644 index 00000000000..614f272642c --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/dfp-builtin-1.c @@ -0,0 +1,88 @@ +/* { dg-do compile { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-mcpu=power7 -O2" } */ +/* { dg-final { scan-assembler-times "ddedpd " 4 } } */ +/* { dg-final { scan-assembler-times "denbcd " 2 } } */ +/* { dg-final { scan-assembler-times "dxex " 1 } } */ +/* { dg-final { scan-assembler-times "diex " 1 } } */ +/* { dg-final { scan-assembler-times "dscli " 2 } } */ +/* { dg-final { scan-assembler-times "dscri " 2 } } */ +/* { dg-final { scan-assembler-not "bl __builtin" } } */ +/* { dg-final { scan-assembler-not "dctqpq" } } */ +/* { dg-final { scan-assembler-not "drdpq" } } */ +/* { dg-final { scan-assembler-not "stfd" } } */ +/* { dg-final { scan-assembler-not "lfd" } } */ + +_Decimal64 +do_dedpd_0 (_Decimal64 a) +{ + return __builtin_ddedpd (0, a); +} + +_Decimal64 +do_dedpd_1 (_Decimal64 a) +{ + return __builtin_ddedpd (1, a); +} + +_Decimal64 +do_dedpd_2 (_Decimal64 a) +{ + return __builtin_ddedpd (2, a); +} + +_Decimal64 +do_dedpd_3 (_Decimal64 a) +{ + return __builtin_ddedpd (3, a); +} + +_Decimal64 +do_enbcd_0 (_Decimal64 a) +{ + return __builtin_denbcd (0, a); +} + +_Decimal64 +do_enbcd_1 (_Decimal64 a) +{ + return __builtin_denbcd (1, a); +} + +_Decimal64 +do_xex (_Decimal64 a) +{ + return __builtin_dxex (a); +} + +_Decimal64 +do_iex (_Decimal64 a, _Decimal64 b) +{ + return __builtin_diex (a, b); +} + +_Decimal64 +do_scli_1 (_Decimal64 a) +{ + return __builtin_dscli (a, 1); +} + +_Decimal64 +do_scli_10 (_Decimal64 a) +{ + return __builtin_dscli (a, 10); +} + +_Decimal64 +do_scri_1 (_Decimal64 a) +{ + return __builtin_dscri (a, 1); +} + +_Decimal64 +do_scri_10 (_Decimal64 a) +{ + return __builtin_dscri (a, 10); +} diff --git a/gcc/testsuite/gcc.target/powerpc/dfp-builtin-2.c b/gcc/testsuite/gcc.target/powerpc/dfp-builtin-2.c new file mode 100644 index 00000000000..189bc9ad6ae --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/dfp-builtin-2.c @@ -0,0 +1,88 @@ +/* { dg-do compile { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-mcpu=power7 -O2" } */ +/* { dg-final { scan-assembler-times "ddedpdq " 4 } } */ +/* { dg-final { scan-assembler-times "denbcdq " 2 } } */ +/* { dg-final { scan-assembler-times "dxexq " 1 } } */ +/* { dg-final { scan-assembler-times "diexq " 1 } } */ +/* { dg-final { scan-assembler-times "dscliq " 2 } } */ +/* { dg-final { scan-assembler-times "dscriq " 2 } } */ +/* { dg-final { scan-assembler-not "bl __builtin" } } */ +/* { dg-final { scan-assembler-not "dctqpq" } } */ +/* { dg-final { scan-assembler-not "drdpq" } } */ +/* { dg-final { scan-assembler-not "stfd" } } */ +/* { dg-final { scan-assembler-not "lfd" } } */ + +_Decimal128 +do_dedpdq_0 (_Decimal128 a) +{ + return __builtin_ddedpdq (0, a); +} + +_Decimal128 +do_dedpdq_1 (_Decimal128 a) +{ + return __builtin_ddedpdq (1, a); +} + +_Decimal128 +do_dedpdq_2 (_Decimal128 a) +{ + return __builtin_ddedpdq (2, a); +} + +_Decimal128 +do_dedpdq_3 (_Decimal128 a) +{ + return __builtin_ddedpdq (3, a); +} + +_Decimal128 +do_enbcdq_0 (_Decimal128 a) +{ + return __builtin_denbcdq (0, a); +} + +_Decimal128 +do_enbcdq_1 (_Decimal128 a) +{ + return __builtin_denbcdq (1, a); +} + +_Decimal128 +do_xexq (_Decimal128 a) +{ + return __builtin_dxexq (a); +} + +_Decimal128 +do_iexq (_Decimal128 a, _Decimal128 b) +{ + return __builtin_diexq (a, b); +} + +_Decimal128 +do_scliq_1 (_Decimal128 a) +{ + return __builtin_dscliq (a, 1); +} + +_Decimal128 +do_scliq_10 (_Decimal128 a) +{ + return __builtin_dscliq (a, 10); +} + +_Decimal128 +do_scriq_1 (_Decimal128 a) +{ + return __builtin_dscriq (a, 1); +} + +_Decimal128 +do_scriq_10 (_Decimal128 a) +{ + return __builtin_dscriq (a, 10); +} diff --git a/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c b/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c new file mode 100644 index 00000000000..5f948b7212f --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/extend-divide-1.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-mcpu=power7 -O2" } */ +/* { dg-final { scan-assembler-times "divwe " 1 } } */ +/* { dg-final { scan-assembler-times "divweo " 1 } } */ +/* { dg-final { scan-assembler-times "divweu " 1 } } */ +/* { dg-final { scan-assembler-times "divweuo " 1 } } */ +/* { dg-final { scan-assembler-not "bl __builtin" } } */ + +int +div_we (int a, int b) +{ + return __builtin_divwe (a, b); +} + +int +div_weo (int a, int b) +{ + return __builtin_divweo (a, b); +} + +unsigned int +div_weu (unsigned int a, unsigned int b) +{ + return __builtin_divweu (a, b); +} + +unsigned int +div_weuo (unsigned int a, unsigned int b) +{ + return __builtin_divweuo (a, b); +} diff --git a/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c b/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c new file mode 100644 index 00000000000..8ee6c8cf768 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/extend-divide-2.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target { powerpc*-*-linux* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-mcpu=power7 -O2" } */ +/* { dg-final { scan-assembler-times "divde " 1 } } */ +/* { dg-final { scan-assembler-times "divdeo " 1 } } */ +/* { dg-final { scan-assembler-times "divdeu " 1 } } */ +/* { dg-final { scan-assembler-times "divdeuo " 1 } } */ +/* { dg-final { scan-assembler-not "bl __builtin" } } */ + +long +div_de (long a, long b) +{ + return __builtin_divde (a, b); +} + +long +div_deo (long a, long b) +{ + return __builtin_divdeo (a, b); +} + +unsigned long +div_deu (unsigned long a, unsigned long b) +{ + return __builtin_divdeu (a, b); +} + +unsigned long +div_deuo (unsigned long a, unsigned long b) +{ + return __builtin_divdeuo (a, b); +} diff --git a/gcc/testsuite/gcc.target/powerpc/pack01.c b/gcc/testsuite/gcc.target/powerpc/pack01.c new file mode 100644 index 00000000000..efac4087c78 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pack01.c @@ -0,0 +1,91 @@ +/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target p8vector_hw } */ +/* { dg-options "-mcpu=power8 -O2" } */ + +#include <stddef.h> +#include <stdlib.h> +#include <altivec.h> + +#ifdef DEBUG +#include <stdio.h> +#endif + +typedef __int128_t __attribute__((__vector_size__(16))) vector_128_t; +typedef __int128_t scalar_128_t; +typedef unsigned long long scalar_64_t; + +volatile scalar_64_t one = 1; +volatile scalar_64_t two = 2; + +int +main (void) +{ + scalar_128_t a = (((scalar_128_t)one) << 64) | ((scalar_128_t)two); + vector_128_t v1 = (vector_128_t) { a }; + vector_128_t v2 = __builtin_pack_vector_int128 (one, two); + scalar_64_t x0 = __builtin_unpack_vector_int128 (v1, 0); + scalar_64_t x1 = __builtin_unpack_vector_int128 (v1, 1); + vector_128_t v3 = __builtin_pack_vector_int128 (x0, x1); + + size_t i; + union { + scalar_128_t i128; + vector_128_t v128; + scalar_64_t u64; + unsigned char uc[sizeof (scalar_128_t)]; + char c[sizeof (scalar_128_t)]; + } u, u2; + +#ifdef DEBUG + { + printf ("a = 0x"); + u.i128 = a; + for (i = 0; i < sizeof (scalar_128_t); i++) + printf ("%.2x", u.uc[i]); + + printf ("\nv1 = 0x"); + u.v128 = v1; + for (i = 0; i < sizeof (scalar_128_t); i++) + printf ("%.2x", u.uc[i]); + + printf ("\nv2 = 0x"); + u.v128 = v2; + for (i = 0; i < sizeof (scalar_128_t); i++) + printf ("%.2x", u.uc[i]); + + printf ("\nv3 = 0x"); + u.v128 = v3; + for (i = 0; i < sizeof (scalar_128_t); i++) + printf ("%.2x", u.uc[i]); + + printf ("\nx0 = 0x"); + u.u64 = x0; + for (i = 0; i < sizeof (scalar_64_t); i++) + printf ("%.2x", u.uc[i]); + + printf ("\nx1 = 0x"); + u.u64 = x1; + for (i = 0; i < sizeof (scalar_64_t); i++) + printf ("%.2x", u.uc[i]); + + printf ("\n"); + } +#endif + + u2.i128 = a; + u.v128 = v1; + if (memcmp (u.c, u2.c, sizeof (scalar_128_t)) != 0) + abort (); + + u.v128 = v2; + if (memcmp (u.c, u2.c, sizeof (scalar_128_t)) != 0) + abort (); + + u.v128 = v3; + if (memcmp (u.c, u2.c, sizeof (scalar_128_t)) != 0) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pack02.c b/gcc/testsuite/gcc.target/powerpc/pack02.c new file mode 100644 index 00000000000..74b6cd04dcc --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pack02.c @@ -0,0 +1,95 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-O2" } */ + +#include <stddef.h> +#include <stdlib.h> +#include <math.h> + +#ifdef DEBUG +#include <stdio.h> +#endif + +int +main (void) +{ + double high = pow (2.0, 60); + double low = 2.0; + long double a = ((long double)high) + ((long double)low); + double x0 = __builtin_unpack_longdouble (a, 0); + double x1 = __builtin_unpack_longdouble (a, 1); + long double b = __builtin_pack_longdouble (x0, x1); + +#ifdef DEBUG + { + size_t i; + union { + long double ld; + double d; + unsigned char uc[sizeof (long double)]; + char c[sizeof (long double)]; + } u; + + printf ("a = 0x"); + u.ld = a; + for (i = 0; i < sizeof (long double); i++) + printf ("%.2x", u.uc[i]); + + printf (", %Lg\n", a); + + printf ("b = 0x"); + u.ld = b; + for (i = 0; i < sizeof (long double); i++) + printf ("%.2x", u.uc[i]); + + printf (", %Lg\n", b); + + printf ("hi = 0x"); + u.d = high; + for (i = 0; i < sizeof (double); i++) + printf ("%.2x", u.uc[i]); + + printf (",%*s %g\n", (int)(2 * (sizeof (long double) - sizeof (double))), "", high); + + printf ("lo = 0x"); + u.d = low; + for (i = 0; i < sizeof (double); i++) + printf ("%.2x", u.uc[i]); + + printf (",%*s %g\n", (int)(2 * (sizeof (long double) - sizeof (double))), "", low); + + printf ("x0 = 0x"); + u.d = x0; + for (i = 0; i < sizeof (double); i++) + printf ("%.2x", u.uc[i]); + + printf (",%*s %g\n", (int)(2 * (sizeof (long double) - sizeof (double))), "", x0); + + printf ("x1 = 0x"); + u.d = x1; + for (i = 0; i < sizeof (double); i++) + printf ("%.2x", u.uc[i]); + + printf (",%*s %g\n", (int)(2 * (sizeof (long double) - sizeof (double))), "", x1); + } +#endif + + if (high != x0) + abort (); + + if (low != x1) + abort (); + + if (a != b) + abort (); + + if (x0 != high) + abort (); + + if (x1 != low) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pack03.c b/gcc/testsuite/gcc.target/powerpc/pack03.c new file mode 100644 index 00000000000..59f0e74ba9c --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pack03.c @@ -0,0 +1,88 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-O2" } */ + +#include <stddef.h> +#include <stdlib.h> +#include <math.h> + +#ifdef DEBUG +#include <stdio.h> +#endif + +int +main (void) +{ + _Decimal128 one = (_Decimal128)1.0; + _Decimal128 two = (_Decimal128)2.0; + _Decimal128 ten = (_Decimal128)10.0; + _Decimal128 a = one; + _Decimal128 b; + _Decimal128 c; + unsigned long long x0; + unsigned long long x1; + size_t i; + + for (i = 0; i < 25; i++) + a *= ten; + + a += two; + + x0 = __builtin_unpack_dec128 (a, 0); + x1 = __builtin_unpack_dec128 (a, 1); + b = __builtin_pack_dec128 (x0, x1); + c = __builtin_dscliq (one, 25) + two; + +#ifdef DEBUG + { + union { + _Decimal128 d; + unsigned long long ull; + unsigned char uc[sizeof (_Decimal128)]; + } u; + + printf ("a = 0x"); + u.d = a; + for (i = 0; i < sizeof (_Decimal128); i++) + printf ("%.2x", u.uc[i]); + + printf (", %Lg\n", (long double)a); + + printf ("b = 0x"); + u.d = b; + for (i = 0; i < sizeof (_Decimal128); i++) + printf ("%.2x", u.uc[i]); + + printf (", %Lg\n", (long double)b); + + printf ("c = 0x"); + u.d = c; + for (i = 0; i < sizeof (_Decimal128); i++) + printf ("%.2x", u.uc[i]); + + printf (", %Lg\n", (long double)c); + + printf ("x0 = 0x"); + u.ull = x0; + for (i = 0; i < sizeof (unsigned long long); i++) + printf ("%.2x", u.uc[i]); + + printf ("\nx1 = 0x"); + u.ull = x1; + for (i = 0; i < sizeof (unsigned long long); i++) + printf ("%.2x", u.uc[i]); + + printf ("\n"); + } +#endif + + if (a != b) + abort (); + + if (a != c) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gfortran.dg/namelist_utf8.f90 b/gcc/testsuite/gfortran.dg/namelist_utf8.f90 new file mode 100644 index 00000000000..c494b8c3b77 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/namelist_utf8.f90 @@ -0,0 +1,30 @@ +! { dg-do run } +! PR52539 UTF-8 support for namelist read and write + +character(len=10, kind=4) :: str, str2 +character(len=25, kind=4) :: str3 + +namelist /nml/ str + +str = 4_'a'//char (int (z'4F60'),4) & + //char (int (z'597D'), 4)//4_'b' + +open(99, encoding='utf-8',form='formatted') +write(99, '(3a)') '&nml str = "', str, '" /' +write(99, '(a)') str +rewind(99) + +str = 4_'XXXX' +str2 = 4_'YYYY' +read(99,nml=nml) +read(99, *) str2 +if (str2 /= str) call abort +rewind(99) + +read(99,'(A)') str3 +if (str3 /= 4_'&nml str = "' // str // 4_'" /') call abort +read(99,'(A)') str3 +if (str3 /= str) call abort + +close(99, status='delete') +end diff --git a/gcc/testsuite/gfortran.dg/no_range_check_3.f90 b/gcc/testsuite/gfortran.dg/no_range_check_3.f90 new file mode 100644 index 00000000000..24223af5b38 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/no_range_check_3.f90 @@ -0,0 +1,12 @@ +! { dg-do run } +! { dg-options "-fno-range-check" } +program test + integer :: i + i = int(z'FFFFFFFF',kind(i)) + if (i /= -1) call abort + if (int(z'FFFFFFFF',kind(i)) /= -1) call abort + + if (popcnt(int(z'0F00F00080000001',8)) /= 10) call abort + if (popcnt(int(z'800F0001',4)) /= 6) call abort + +end program test diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index df6923f76ef..9c175de4e9d 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -1082,6 +1082,11 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) need_stmts = true; goto do_decl_clause; + case OMP_CLAUSE_LINEAR: + if (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause)) + need_stmts = true; + goto do_decl_clause; + case OMP_CLAUSE_PRIVATE: case OMP_CLAUSE_FIRSTPRIVATE: case OMP_CLAUSE_COPYPRIVATE: @@ -1157,6 +1162,12 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause)); break; + case OMP_CLAUSE_LINEAR: + walk_body (convert_nonlocal_reference_stmt, + convert_nonlocal_reference_op, info, + &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause)); + break; + default: break; } @@ -1605,6 +1616,11 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) need_stmts = true; goto do_decl_clause; + case OMP_CLAUSE_LINEAR: + if (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause)) + need_stmts = true; + goto do_decl_clause; + case OMP_CLAUSE_PRIVATE: case OMP_CLAUSE_FIRSTPRIVATE: case OMP_CLAUSE_COPYPRIVATE: @@ -1685,6 +1701,12 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause)); break; + case OMP_CLAUSE_LINEAR: + walk_body (convert_local_reference_stmt, + convert_local_reference_op, info, + &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (clause)); + break; + default: break; } diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 46dc00c38a3..0d941019f0e 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -586,7 +586,7 @@ extern gimple_opt_pass *make_pass_convert_switch (gcc::context *ctxt); extern opt_pass *current_pass; extern bool execute_one_pass (opt_pass *); -extern void execute_pass_list (opt_pass *); +extern void execute_pass_list (function *, opt_pass *); extern void execute_ipa_pass_list (opt_pass *); extern void execute_ipa_summary_passes (ipa_opt_pass_d *); extern void execute_all_ipa_transforms (void); @@ -614,7 +614,7 @@ extern bool function_called_by_processed_nodes_p (void); extern bool first_pass_instance; /* Declare for plugins. */ -extern void do_per_function_toporder (void (*) (void *), void *); +extern void do_per_function_toporder (void (*) (function *, void *), void *); extern void disable_pass (const char *); extern void enable_pass (const char *); diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index e040c4fc58d..5074142f6f2 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -7243,10 +7243,7 @@ ipa_pta_execute (void) tree ptr; struct function *fn; unsigned i; - varinfo_t fi; basic_block bb; - struct pt_solution uses, clobbers; - struct cgraph_edge *e; /* Nodes without a body are not interesting. */ if (!cgraph_function_with_gimple_body_p (node) || node->clone_of) @@ -7262,21 +7259,6 @@ ipa_pta_execute (void) find_what_p_points_to (ptr); } - /* Compute the call-use and call-clobber sets for all direct calls. */ - fi = lookup_vi_for_tree (node->decl); - gcc_assert (fi->is_fn_info); - clobbers - = find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers)); - uses = find_what_var_points_to (first_vi_for_offset (fi, fi_uses)); - for (e = node->callers; e; e = e->next_caller) - { - if (!e->call_stmt) - continue; - - *gimple_call_clobber_set (e->call_stmt) = clobbers; - *gimple_call_use_set (e->call_stmt) = uses; - } - /* Compute the call-use and call-clobber sets for indirect calls and calls to external functions. */ FOR_EACH_BB_FN (bb, fn) @@ -7287,17 +7269,27 @@ ipa_pta_execute (void) { gimple stmt = gsi_stmt (gsi); struct pt_solution *pt; - varinfo_t vi; + varinfo_t vi, fi; tree decl; if (!is_gimple_call (stmt)) continue; - /* Handle direct calls to external functions. */ + /* Handle direct calls to functions with body. */ decl = gimple_call_fndecl (stmt); if (decl - && (!(fi = lookup_vi_for_tree (decl)) - || !fi->is_fn_info)) + && (fi = lookup_vi_for_tree (decl)) + && fi->is_fn_info) + { + *gimple_call_clobber_set (stmt) + = find_what_var_points_to + (first_vi_for_offset (fi, fi_clobbers)); + *gimple_call_use_set (stmt) + = find_what_var_points_to + (first_vi_for_offset (fi, fi_uses)); + } + /* Handle direct calls to external functions. */ + else if (decl) { pt = gimple_call_use_set (stmt); if (gimple_call_flags (stmt) & ECF_CONST) @@ -7341,10 +7333,9 @@ ipa_pta_execute (void) pt->nonlocal = 1; } } - /* Handle indirect calls. */ - if (!decl - && (fi = get_fi_for_callee (stmt))) + else if (!decl + && (fi = get_fi_for_callee (stmt))) { /* We need to accumulate all clobbers/uses of all possible callees. */ diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 8a0103b1637..7621348944f 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -398,7 +398,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e, ssa_op_iter iter; if (backedge_seen) - FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_DEFS) + FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF) { /* This call only invalidates equivalences created by PHI nodes. This is by design to keep the cost of diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 9ac111772f4..e22ce2cc71d 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -969,7 +969,8 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type if (!optimize || !VECTOR_INTEGER_TYPE_P (type) - || TREE_CODE (rhs2) != VECTOR_CST) + || TREE_CODE (rhs2) != VECTOR_CST + || !VECTOR_MODE_P (TYPE_MODE (type))) break; ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code); diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 75116177fed..094cf047e05 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -392,6 +392,8 @@ vect_recog_dot_prod_pattern (vec<gimple> *stmts, tree *type_in, gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_internal_def); oprnd00 = gimple_assign_rhs1 (stmt); oprnd01 = gimple_assign_rhs2 (stmt); + STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (last_stmt)) + = STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo); } else { @@ -3065,8 +3067,7 @@ vect_mark_pattern_stmts (gimple orig_stmt, gimple pattern_stmt, } gimple_set_bb (def_stmt, gimple_bb (orig_stmt)); STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt; - STMT_VINFO_DEF_TYPE (def_stmt_info) - = STMT_VINFO_DEF_TYPE (orig_stmt_info); + STMT_VINFO_DEF_TYPE (def_stmt_info) = vect_internal_def; if (STMT_VINFO_VECTYPE (def_stmt_info) == NULL_TREE) STMT_VINFO_VECTYPE (def_stmt_info) = pattern_vectype; } diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 2e2a27f874f..7951805e473 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -3949,52 +3949,6 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, } } -/* Return true if VAR may overflow at STMT. This checks any available - loop information to see if we can determine that VAR does not - overflow. */ - -static bool -vrp_var_may_overflow (tree var, gimple stmt) -{ - struct loop *l; - tree chrec, init, step; - - if (current_loops == NULL) - return true; - - l = loop_containing_stmt (stmt); - if (l == NULL - || !loop_outer (l)) - return true; - - chrec = instantiate_parameters (l, analyze_scalar_evolution (l, var)); - if (TREE_CODE (chrec) != POLYNOMIAL_CHREC) - return true; - - init = initial_condition_in_loop_num (chrec, l->num); - step = evolution_part_in_loop_num (chrec, l->num); - - if (step == NULL_TREE - || !is_gimple_min_invariant (step) - || !valid_value_p (init)) - return true; - - /* If we get here, we know something useful about VAR based on the - loop information. If it wraps, it may overflow. */ - - if (scev_probably_wraps_p (init, step, stmt, get_chrec_loop (chrec), - true)) - return true; - - if (dump_file && (dump_flags & TDF_DETAILS) != 0) - { - print_generic_expr (dump_file, var, 0); - fprintf (dump_file, ": loop information indicates does not overflow\n"); - } - - return false; -} - /* Given two numeric value ranges VR0, VR1 and a comparison code COMP: @@ -8382,32 +8336,32 @@ vrp_visit_phi_node (gimple phi) && (cmp_min != 0 || cmp_max != 0)) goto varying; - /* If the new minimum is smaller or larger than the previous - one, go all the way to -INF. In the first case, to avoid - iterating millions of times to reach -INF, and in the - other case to avoid infinite bouncing between different - minimums. */ - if (cmp_min > 0 || cmp_min < 0) - { - if (!needs_overflow_infinity (TREE_TYPE (vr_result.min)) - || !vrp_var_may_overflow (lhs, phi)) - vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)); - else if (supports_overflow_infinity (TREE_TYPE (vr_result.min))) - vr_result.min = - negative_overflow_infinity (TREE_TYPE (vr_result.min)); - } - - /* Similarly, if the new maximum is smaller or larger than - the previous one, go all the way to +INF. */ - if (cmp_max < 0 || cmp_max > 0) - { - if (!needs_overflow_infinity (TREE_TYPE (vr_result.max)) - || !vrp_var_may_overflow (lhs, phi)) - vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max)); - else if (supports_overflow_infinity (TREE_TYPE (vr_result.max))) - vr_result.max = - positive_overflow_infinity (TREE_TYPE (vr_result.max)); - } + /* If the new minimum is larger than than the previous one + retain the old value. If the new minimum value is smaller + than the previous one and not -INF go all the way to -INF + 1. + In the first case, to avoid infinite bouncing between different + minimums, and in the other case to avoid iterating millions of + times to reach -INF. Going to -INF + 1 also lets the following + iteration compute whether there will be any overflow, at the + expense of one additional iteration. */ + if (cmp_min < 0) + vr_result.min = lhs_vr->min; + else if (cmp_min > 0 + && !vrp_val_is_min (vr_result.min)) + vr_result.min + = int_const_binop (PLUS_EXPR, + vrp_val_min (TREE_TYPE (vr_result.min)), + build_int_cst (TREE_TYPE (vr_result.min), 1)); + + /* Similarly for the maximum value. */ + if (cmp_max > 0) + vr_result.max = lhs_vr->max; + else if (cmp_max < 0 + && !vrp_val_is_max (vr_result.max)) + vr_result.max + = int_const_binop (MINUS_EXPR, + vrp_val_max (TREE_TYPE (vr_result.min)), + build_int_cst (TREE_TYPE (vr_result.min), 1)); /* If we dropped either bound to +-INF then if this is a loop PHI node SCEV may known more about its value-range. */ diff --git a/gcc/tree.h b/gcc/tree.h index 57c952802a8..3e8e625ab9f 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1333,6 +1333,9 @@ extern void protected_set_expr_location (tree, location_t); #define OMP_CLAUSE_LINEAR_STEP(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 1) +#define OMP_CLAUSE_LINEAR_GIMPLE_SEQ(NODE) \ + (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init + #define OMP_CLAUSE_ALIGNED_ALIGNMENT(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALIGNED), 1) diff --git a/libffi/ChangeLog b/libffi/ChangeLog index aebe8553b90..75bfd8036a0 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,12 @@ +2014-04-22 Jakub Jelinek <jakub@redhat.com> + + 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. + 2014-03-12 Yufeng Zhang <yufeng.zhang@arm.com> * src/aarch64/sysv.S (ffi_closure_SYSV): Use x29 as the diff --git a/libffi/Makefile.in b/libffi/Makefile.in index 9ac95d49bdf..2a04e0b3bec 100644 --- a/libffi/Makefile.in +++ b/libffi/Makefile.in @@ -66,14 +66,11 @@ target_triplet = @target@ @PA_HPUX_TRUE@am__append_29 = src/pa/hpux32.S src/pa/ffi.c @TILE_TRUE@am__append_30 = src/tile/tile.S src/tile/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)/doc/stamp-vti \ - $(srcdir)/doc/version.texi $(srcdir)/fficonfig.h.in \ - $(top_srcdir)/configure ChangeLog mdate-sh +DIST_COMMON = README ChangeLog $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(srcdir)/fficonfig.h.in \ + $(srcdir)/../mkinstalldirs $(srcdir)/../depcomp mdate-sh \ + $(srcdir)/doc/version.texi $(srcdir)/doc/stamp-vti ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/asmcfi.m4 \ @@ -220,7 +217,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 = @@ -249,47 +245,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@ @@ -1462,185 +1421,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 - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-info - -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 $(INFO_DEPS) $(LTLIBRARIES) all-multi fficonfig.h \ @@ -1881,16 +1661,14 @@ uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ all all-am all-local all-multi am--refresh check check-am \ clean clean-aminfo clean-generic clean-libtool clean-multi \ clean-noinstLTLIBRARIES clean-toolexeclibLTLIBRARIES ctags \ - ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-info \ - 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 \ + ctags-recursive dist-info 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-aminfo maintainer-clean-generic \ diff --git a/libffi/configure.ac b/libffi/configure.ac index 438222775bc..a08feaa0381 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]) # See if makeinfo has been installed and is modern enough # that we can use it. diff --git a/libffi/include/Makefile.in b/libffi/include/Makefile.in index 2a42902d398..c923bf212e4 100644 --- a/libffi/include/Makefile.in +++ b/libffi/include/Makefile.in @@ -36,7 +36,7 @@ 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/acx.m4 \ @@ -56,7 +56,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/||"`;; \ @@ -82,7 +81,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@ @@ -333,37 +331,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) @@ -467,17 +434,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 b5ed121df3d..743e67b7d1b 100644 --- a/libffi/man/Makefile.in +++ b/libffi/man/Makefile.in @@ -35,7 +35,7 @@ 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/acx.m4 \ $(top_srcdir)/../config/asmcfi.m4 \ @@ -54,7 +54,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/||"`;; \ @@ -80,7 +79,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@ @@ -296,50 +294,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) @@ -443,16 +397,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/testsuite/Makefile.in b/libffi/testsuite/Makefile.in index 540ab66d48c..808d4cb2e5b 100644 --- a/libffi/testsuite/Makefile.in +++ b/libffi/testsuite/Makefile.in @@ -35,7 +35,7 @@ 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/acx.m4 \ $(top_srcdir)/../config/asmcfi.m4 \ @@ -54,10 +54,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@ @@ -351,37 +349,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 @@ -483,8 +450,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/libgcc/ChangeLog b/libgcc/ChangeLog index d128b08a8ad..e2b28ee2c4d 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2014-04-25 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * config/i386/crtfastmath.c [!__x86_64__ && __sun__ && __svr4__] + (sigill_caught, sigill_hdlr): Remove. + 2014-04-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * config/i386/crtfastmath.c (set_fast_math): Remove SSE execution diff --git a/libgcc/config/i386/crtfastmath.c b/libgcc/config/i386/crtfastmath.c index 24a08843286..67b37eea56f 100644 --- a/libgcc/config/i386/crtfastmath.c +++ b/libgcc/config/i386/crtfastmath.c @@ -31,26 +31,6 @@ #include "cpuid.h" #endif -#if !defined __x86_64__ && defined __sun__ && defined __svr4__ -#include <signal.h> -#include <ucontext.h> - -static volatile sig_atomic_t sigill_caught; - -static void -sigill_hdlr (int sig __attribute((unused)), - siginfo_t *sip __attribute__((unused)), - ucontext_t *ucp) -{ - sigill_caught = 1; - /* Set PC to the instruction after the faulting one to skip over it, - otherwise we enter an infinite loop. 3 is the size of the movaps - instruction. */ - ucp->uc_mcontext.gregs[EIP] += 3; - setcontext (ucp); -} -#endif - static void __attribute__((constructor)) #ifndef __x86_64__ /* The i386 ABI only requires 4-byte stack alignment, so this is necessary diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 0fb3ccddf7d..dc37a861f02 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,16 @@ +2014-04-26 Jerry DeLisle <jvdelisle@gcc.gnu> + + PR libfortran/52539 + * io/list_read.c: Add uchar typedef. (push_char4): New function + to save kind=4 character. (next_char_utf8): New function to read + a single UTF-8 encoded character value. (read_chracter): Update + to use the new functions for reading UTF-8 strings. + (list_formatted_read_scalar): Update to handle list directed + reads of UTF-8 strings. (nml_read_obj): Likewise update for + UTF-8 strings in namelists. + * io/write.c (nml_write_obj): Add kind=4 character support for + namelist writes. + 2014-04-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * configure.ac: Quote usage of ac_cv_func_clock_gettime in if test. diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c index 625ba0c8594..b052c06b557 100644 --- a/libgfortran/io/list_read.c +++ b/libgfortran/io/list_read.c @@ -32,6 +32,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include <stdlib.h> #include <ctype.h> +typedef unsigned char uchar; + /* List directed input. Several parsing subroutines are practically reimplemented from formatted input, the reason being that there are @@ -97,6 +99,37 @@ push_char (st_parameter_dt *dtp, char c) dtp->u.p.saved_string[dtp->u.p.saved_used++] = c; } +/* Save a KIND=4 character to a string buffer, enlarging the buffer + as necessary. */ + +static void +push_char4 (st_parameter_dt *dtp, gfc_char4_t c) +{ + gfc_char4_t *new, *p = (gfc_char4_t *) dtp->u.p.saved_string; + + if (p == NULL) + { + dtp->u.p.saved_string = xcalloc (SCRATCH_SIZE, sizeof (gfc_char4_t)); + dtp->u.p.saved_length = SCRATCH_SIZE; + dtp->u.p.saved_used = 0; + p = (gfc_char4_t *) dtp->u.p.saved_string; + } + + if (dtp->u.p.saved_used >= dtp->u.p.saved_length) + { + dtp->u.p.saved_length = 2 * dtp->u.p.saved_length; + new = realloc (p, dtp->u.p.saved_length); + if (new == NULL) + generate_error (&dtp->common, LIBERROR_OS, NULL); + p = new; + + memset (new + dtp->u.p.saved_used, 0, + dtp->u.p.saved_length - dtp->u.p.saved_used); + } + + p[dtp->u.p.saved_used++] = c; +} + /* Free the input buffer if necessary. */ @@ -247,6 +280,57 @@ done: } +static gfc_char4_t +next_char_utf8 (st_parameter_dt *dtp) +{ + static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 }; + static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + int i, nb; + gfc_char4_t c; + + c = next_char (dtp); + if (c < 0x80) + return c; + + /* The number of leading 1-bits in the first byte indicates how many + bytes follow. */ + for (nb = 2; nb < 7; nb++) + if ((c & ~masks[nb-1]) == patns[nb-1]) + goto found; + goto invalid; + + found: + c = (c & masks[nb-1]); + + /* Decode the bytes read. */ + for (i = 1; i < nb; i++) + { + gfc_char4_t n = next_char (dtp); + + if ((n & 0xC0) != 0x80) + goto invalid; + + c = ((c << 6) + (n & 0x3F)); + } + + /* Make sure the shortest possible encoding was used. */ + if (c <= 0x7F && nb > 1) goto invalid; + if (c <= 0x7FF && nb > 2) goto invalid; + if (c <= 0xFFFF && nb > 3) goto invalid; + if (c <= 0x1FFFFF && nb > 4) goto invalid; + if (c <= 0x3FFFFFF && nb > 5) goto invalid; + + /* Make sure the character is valid. */ + if (c > 0x7FFFFFFF || (c >= 0xD800 && c <= 0xDFFF)) + goto invalid; + + return c; + + invalid: + generate_error (&dtp->common, LIBERROR_READ_VALUE, "Invalid UTF-8 encoding"); + return (gfc_char4_t) '?'; +} + /* Push a character back onto the input. */ static void @@ -1087,50 +1171,97 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused))) } get_string: - for (;;) - { - if ((c = next_char (dtp)) == EOF) - goto done_eof; - switch (c) - { - case '"': - case '\'': - if (c != quote) - { - push_char (dtp, c); - break; - } - - /* See if we have a doubled quote character or the end of - the string. */ - - if ((c = next_char (dtp)) == EOF) - goto done_eof; - if (c == quote) - { - push_char (dtp, quote); - break; - } - - unget_char (dtp, c); - goto done; - - CASE_SEPARATORS: - if (quote == ' ') - { - unget_char (dtp, c); - goto done; - } - if (c != '\n' && c != '\r') + if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8) + for (;;) + { + if ((c = next_char_utf8 (dtp)) == EOF) + goto done_eof; + switch (c) + { + case '"': + case '\'': + if (c != quote) + { + push_char4 (dtp, c); + break; + } + + /* See if we have a doubled quote character or the end of + the string. */ + + if ((c = next_char_utf8 (dtp)) == EOF) + goto done_eof; + if (c == quote) + { + push_char4 (dtp, quote); + break; + } + + unget_char (dtp, c); + goto done; + + CASE_SEPARATORS: + if (quote == ' ') + { + unget_char (dtp, c); + goto done; + } + + if (c != '\n' && c != '\r') + push_char4 (dtp, c); + break; + + default: + push_char4 (dtp, c); + break; + } + } + else + for (;;) + { + if ((c = next_char (dtp)) == EOF) + goto done_eof; + switch (c) + { + case '"': + case '\'': + if (c != quote) + { + push_char (dtp, c); + break; + } + + /* See if we have a doubled quote character or the end of + the string. */ + + if ((c = next_char (dtp)) == EOF) + goto done_eof; + if (c == quote) + { + push_char (dtp, quote); + break; + } + + unget_char (dtp, c); + goto done; + + CASE_SEPARATORS: + if (quote == ' ') + { + unget_char (dtp, c); + goto done; + } + + if (c != '\n' && c != '\r') + push_char (dtp, c); + break; + + default: push_char (dtp, c); - break; - - default: - push_char (dtp, c); - break; - } - } + break; + } + } /* At this point, we have to have a separator, or else the string is invalid. */ @@ -1903,7 +2034,7 @@ static int list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p, int kind, size_t size) { - gfc_char4_t *q; + gfc_char4_t *q, *r; int c, i, m; int err = 0; @@ -2031,13 +2162,19 @@ list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p, { m = ((int) size < dtp->u.p.saved_used) ? (int) size : dtp->u.p.saved_used; - if (kind == 1) - memcpy (p, dtp->u.p.saved_string, m); + + q = (gfc_char4_t *) p; + r = (gfc_char4_t *) dtp->u.p.saved_string; + if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8) + for (i = 0; i < m; i++) + *q++ = *r++; else { - q = (gfc_char4_t *) p; - for (i = 0; i < m; i++) - q[i] = (unsigned char) dtp->u.p.saved_string[i]; + if (kind == 1) + memcpy (p, dtp->u.p.saved_string, m); + else + for (i = 0; i < m; i++) + *q++ = (unsigned char) dtp->u.p.saved_string[i]; } } else @@ -2771,10 +2908,27 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset, } else m = dtp->u.p.saved_used; - pdata = (void*)( pdata + clow - 1 ); - memcpy (pdata, dtp->u.p.saved_string, m); - if (m < dlen) - memset ((void*)( pdata + m ), ' ', dlen - m); + + if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8) + { + gfc_char4_t *q4, *p4 = pdata; + int i; + + q4 = (gfc_char4_t *) dtp->u.p.saved_string; + p4 += clow -1; + for (i = 0; i < m; i++) + *p4++ = *q4++; + if (m < dlen) + for (i = 0; i < dlen - m; i++) + *p4++ = (gfc_char4_t) ' '; + } + else + { + pdata = (void*)( pdata + clow - 1 ); + memcpy (pdata, dtp->u.p.saved_string, m); + if (m < dlen) + memset ((void*)( pdata + m ), ' ', dlen - m); + } break; default: diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c index eccbe7e2a20..e17a3d86203 100644 --- a/libgfortran/io/write.c +++ b/libgfortran/io/write.c @@ -1835,7 +1835,10 @@ nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset, break; case BT_CHARACTER: - write_character (dtp, p, 1, obj->string_length, DELIM); + if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8) + write_character (dtp, p, 4, obj->string_length, DELIM); + else + write_character (dtp, p, 1, obj->string_length, DELIM); break; case BT_REAL: diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c index fee493c1367..1b8ab791606 100644 --- a/libgo/runtime/mheap.c +++ b/libgo/runtime/mheap.c @@ -387,7 +387,7 @@ forcegchelper(void *vnote) static uintptr scavengelist(MSpan *list, uint64 now, uint64 limit) { - uintptr released, sumreleased; + uintptr released, sumreleased, start, end, pagesize; MSpan *s; if(runtime_MSpanList_IsEmpty(list)) @@ -400,7 +400,17 @@ scavengelist(MSpan *list, uint64 now, uint64 limit) mstats.heap_released += released; sumreleased += released; s->npreleased = s->npages; - runtime_SysUnused((void*)(s->start << PageShift), s->npages << PageShift); + + start = s->start << PageShift; + end = start + (s->npages << PageShift); + + // Round start up and end down to ensure we + // are acting on entire pages. + pagesize = getpagesize(); + start = ROUND(start, pagesize); + end &= ~(pagesize - 1); + if(end > start) + runtime_SysUnused((void*)start, end - start); } } return sumreleased; diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index c0f093ff458..0b26b9fdb4a 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,15 @@ +2014-04-24 Jakub Jelinek <jakub@redhat.com> + + * testsuite/libgomp.c++/atomic-14.C: Allow seq_cst and + atomic type clauses in any order and optional comma in between. + * testsuite/libgomp.c++/atomic-15.C: Likewise. + * testsuite/libgomp.c/atomic-17.c: Likewise. + + * testsuite/libgomp.c/simd-7.c: New test. + * testsuite/libgomp.c/simd-8.c: New test. + * testsuite/libgomp.c/simd-9.c: New test. + * testsuite/libgomp.c/loop-16.c: New test. + 2014-04-02 Richard Henderson <rth@redhat.com> * config/linux/futex.h (futex_wait): Get error value from errno. diff --git a/libgomp/testsuite/libgomp.c++/atomic-14.C b/libgomp/testsuite/libgomp.c++/atomic-14.C index 4cd9df812d3..dccea3acd80 100644 --- a/libgomp/testsuite/libgomp.c++/atomic-14.C +++ b/libgomp/testsuite/libgomp.c++/atomic-14.C @@ -13,13 +13,13 @@ main () v = x; if (v != 3) abort (); - #pragma omp atomic update seq_cst + #pragma omp atomic seq_cst update x = 3 * 2 * 1 + x; - #pragma omp atomic read seq_cst + #pragma omp atomic read, seq_cst v = x; if (v != 9) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst, capture v = x = x | 16; if (v != 25) abort (); @@ -27,15 +27,15 @@ main () v = x = x + 14 * 2 / 4; if (v != 32) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture v = x = 5 | x; if (v != 37) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture, seq_cst v = x = 40 + 12 - 2 - 7 - x; if (v != 6) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic seq_cst read v = x; if (v != 6) abort (); @@ -43,7 +43,7 @@ main () { v = x; x = 3 + x; } if (v != 6) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { v = x; x = -1 * -1 * -1 * -1 - x; } if (v != 9) abort (); @@ -51,11 +51,11 @@ main () v = x; if (v != -8) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture, seq_cst { x = 2 * 2 - x; v = x; } if (v != 12) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { x = 7 & x; v = x; } if (v != 4) abort (); @@ -63,7 +63,7 @@ main () { v = x; x = 6; } if (v != 4) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic read, seq_cst v = x; if (v != 6) abort (); @@ -71,11 +71,11 @@ main () { v = x; x = 7 * 8 + 23; } if (v != 6) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic seq_cst, read v = x; if (v != 79) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture , seq_cst { v = x; x = 23 + 6 * 4; } if (v != 79) abort (); @@ -83,7 +83,7 @@ main () v = x; if (v != 47) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { v = x; x = l ? 17 : 12; } if (v != 47) abort (); diff --git a/libgomp/testsuite/libgomp.c++/atomic-15.C b/libgomp/testsuite/libgomp.c++/atomic-15.C index 1eabce7dbd3..9abefb64688 100644 --- a/libgomp/testsuite/libgomp.c++/atomic-15.C +++ b/libgomp/testsuite/libgomp.c++/atomic-15.C @@ -14,13 +14,13 @@ foo () v = x; if (v != 3) abort (); - #pragma omp atomic update seq_cst + #pragma omp atomic seq_cst update x = 3 * 2 * 1 + x; - #pragma omp atomic read seq_cst + #pragma omp atomic read, seq_cst v = x; if (v != 9) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst, capture v = x = x | 16; if (v != 25) abort (); @@ -28,15 +28,15 @@ foo () v = x = x + 14 * 2 / 4; if (v != 32) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture v = x = 5 | x; if (v != 37) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture, seq_cst v = x = 40 + 12 - 2 - 7 - x; if (v != 6) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic seq_cst read v = x; if (v != 6) abort (); @@ -44,7 +44,7 @@ foo () { v = x; x = 3 + x; } if (v != 6) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { v = x; x = -1 * -1 * -1 * -1 - x; } if (v != 9) abort (); @@ -52,11 +52,11 @@ foo () v = x; if (v != -8) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture, seq_cst { x = 2 * 2 - x; v = x; } if (v != 12) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { x = 7 & x; v = x; } if (v != 4) abort (); @@ -64,7 +64,7 @@ foo () { v = x; x = 6; } if (v != 4) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic read, seq_cst v = x; if (v != 6) abort (); @@ -72,11 +72,11 @@ foo () { v = x; x = 7 * 8 + 23; } if (v != 6) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic seq_cst, read v = x; if (v != 79) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture , seq_cst { v = x; x = 23 + 6 * 4; } if (v != 79) abort (); @@ -84,7 +84,7 @@ foo () v = x; if (v != 47) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { v = x; x = l ? 17 : 12; } if (v != 47) abort (); diff --git a/libgomp/testsuite/libgomp.c/atomic-17.c b/libgomp/testsuite/libgomp.c/atomic-17.c index 2bd0e9b44dc..147ab26a953 100644 --- a/libgomp/testsuite/libgomp.c/atomic-17.c +++ b/libgomp/testsuite/libgomp.c/atomic-17.c @@ -13,13 +13,13 @@ main () v = x; if (v != 3) abort (); - #pragma omp atomic update seq_cst + #pragma omp atomic seq_cst update x = 3 * 2 * 1 + x; - #pragma omp atomic read seq_cst + #pragma omp atomic read, seq_cst v = x; if (v != 9) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst, capture v = x = x | 16; if (v != 25) abort (); @@ -27,15 +27,15 @@ main () v = x = x + 14 * 2 / 4; if (v != 32) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture v = x = 5 | x; if (v != 37) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture, seq_cst v = x = 40 + 12 - 2 - 7 - x; if (v != 6) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic seq_cst read v = x; if (v != 6) abort (); @@ -43,7 +43,7 @@ main () { v = x; x = 3 + x; } if (v != 6) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { v = x; x = -1 * -1 * -1 * -1 - x; } if (v != 9) abort (); @@ -51,11 +51,11 @@ main () v = x; if (v != -8) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture, seq_cst { x = 2 * 2 - x; v = x; } if (v != 12) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { x = 7 & x; v = x; } if (v != 4) abort (); @@ -63,7 +63,7 @@ main () { v = x; x = 6; } if (v != 4) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic read, seq_cst v = x; if (v != 6) abort (); @@ -71,11 +71,11 @@ main () { v = x; x = 7 * 8 + 23; } if (v != 6) abort (); - #pragma omp atomic read seq_cst + #pragma omp atomic seq_cst, read v = x; if (v != 79) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic capture , seq_cst { v = x; x = 23 + 6 * 4; } if (v != 79) abort (); @@ -83,7 +83,7 @@ main () v = x; if (v != 47) abort (); - #pragma omp atomic capture seq_cst + #pragma omp atomic seq_cst capture { v = x; x = l ? 17 : 12; } if (v != 47) abort (); diff --git a/libgomp/testsuite/libgomp.c/loop-16.c b/libgomp/testsuite/libgomp.c/loop-16.c new file mode 100644 index 00000000000..3ef2f6489bd --- /dev/null +++ b/libgomp/testsuite/libgomp.c/loop-16.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ + +extern void abort (void); + +volatile int count; +static int test (void) +{ + return ++count > 0; +} + +int i; + +int +main () +{ + #pragma omp for lastprivate (i) + for (i = 0; i < 10; ++i) + { + int *p = &i; + if (test ()) + continue; + abort (); + } + if (i != count) + abort (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/simd-7.c b/libgomp/testsuite/libgomp.c/simd-7.c new file mode 100644 index 00000000000..ab04fee82d7 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/simd-7.c @@ -0,0 +1,96 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-msse2" { target sse2_runtime } } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +extern void abort (); +int a[1024] __attribute__((aligned (32))) = { 1 }; +int b[1024] __attribute__((aligned (32))) = { 1 }; +int k, m; +struct U { int u; }; +struct V { int v; }; + +__attribute__((noinline, noclone)) int +foo (int *p) +{ + int i, s = 0; + struct U u; + struct V v; + #pragma omp simd aligned(a, p : 32) linear(k: m + 1) \ + linear(i) reduction(+:s) lastprivate(u, v) + for (i = 0; i < 1024; i++) + { + int *q = &i; + a[i] *= p[i]; + u.u = p[i] + k; + k += m + 1; + v.v = p[i] + k; + s += p[i] + k; + } + if (u.u != 36 + 4 + 3 * 1023 || v.v != 36 + 4 + 3 * 1024 || i != 1024) + abort (); + return s; +} + +__attribute__((noinline, noclone)) int +bar (int *p) +{ + int i, s = 0; + struct U u; + struct V v; + #pragma omp simd aligned(a, p : 32) linear(k: m + 1) \ + reduction(+:s) lastprivate(u, v) + for (i = 0; i < 1024; i++) + { + int *q = &i; + a[i] *= p[i]; + u.u = p[i] + k; + k += m + 1; + v.v = p[i] + k; + s += p[i] + k; + } + if (u.u != 36 + 4 + 3 * 1023 || v.v != 36 + 4 + 3 * 1024 || i != 1024) + abort (); + return s; +} + +int +main () +{ +#if __SIZEOF_INT__ >= 4 + int i; + k = 4; + m = 2; + for (i = 0; i < 1024; i++) + { + a[i] = i - 512; + b[i] = (i - 51) % 39; + } + int s = foo (b); + for (i = 0; i < 1024; i++) + { + if (b[i] != (i - 51) % 39 + || a[i] != (i - 512) * b[i]) + abort (); + } + if (k != 4 + 3 * 1024 || s != 1596127) + abort (); + k = 4; + m = 2; + for (i = 0; i < 1024; i++) + { + a[i] = i - 512; + b[i] = (i - 51) % 39; + } + s = bar (b); + for (i = 0; i < 1024; i++) + { + if (b[i] != (i - 51) % 39 + || a[i] != (i - 512) * b[i]) + abort (); + } + if (k != 4 + 3 * 1024 || s != 1596127) + abort (); +#endif + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/simd-8.c b/libgomp/testsuite/libgomp.c/simd-8.c new file mode 100644 index 00000000000..13f40d58362 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/simd-8.c @@ -0,0 +1,44 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-msse2" { target sse2_runtime } } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +extern void abort (); +int a[32][32] __attribute__((aligned (32))) = { { 1 } }; +struct S { int s; }; +#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s) +#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s) +#pragma omp declare reduction (foo:int:omp_out += omp_in) + +__attribute__((noinline, noclone)) int +foo (void) +{ + int i, j, u = 0; + struct S s, t; + s.s = 0; t.s = 0; + #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u) collapse(2) + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + { + int x = a[i][j]; + s.s += x; + t.s += x; + u += x; + } + if (t.s != s.s || u != s.s) + abort (); + return s.s; +} + +int +main () +{ + int i, j; + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + a[i][j] = j + (i / 4); + int s = foo (); + if (s != 19456) + abort (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c/simd-9.c b/libgomp/testsuite/libgomp.c/simd-9.c new file mode 100644 index 00000000000..b64dd252229 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/simd-9.c @@ -0,0 +1,70 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-msse2" { target sse2_runtime } } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +extern void abort (); +int a[32][32] __attribute__((aligned (32))) = { { 1 } }; +struct S { int s; }; +#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s) +#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s) +#pragma omp declare reduction (foo:int:omp_out += omp_in) + +__attribute__((noinline, noclone)) int +foo (void) +{ + int i, j, u = 0; + struct S s, t; + s.s = 0; t.s = 0; + #pragma omp simd aligned(a : 32) lastprivate (i, j) reduction(+:s) reduction(foo:t, u) collapse(2) + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + { + int *q = &i; + int *r = &j; + int x = a[i][j]; + s.s += x; + t.s += x; + u += x; + } + if (t.s != s.s || u != s.s || i != 32 || j != 32) + abort (); + return s.s; +} + +__attribute__((noinline, noclone)) int +bar (void) +{ + int i, j, u = 0; + struct S s, t; + s.s = 0; t.s = 0; + #pragma omp simd aligned(a:32)reduction(+:s)reduction(foo:t,u)collapse(2) + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + { + int *q = &i; + int *r = &j; + int x = a[i][j]; + s.s += x; + t.s += x; + u += x; + } + if (t.s != s.s || u != s.s || i != 32 || j != 32) + abort (); + return s.s; +} + +int +main () +{ + int i, j; + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + a[i][j] = j + (i / 4); + int s = foo (); + if (s != 19456) + abort (); + if (bar () != 19456) + abort (); + return 0; +} diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 83c10944a3b..6cc371c5d9d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,66 @@ +2014-04-27 Tim Shen <timshen91@gmail.com> + + * include/bits/regex_automaton.h (_NFA<>::_M_insert_repeat): + Add _S_opcode_repeat support to distingush a loop from + _S_opcode_alternative. + * include/bits/regex_automaton.tcc (_State_base::_M_print, + _State_base::_M_dot, _NFA<>::_M_eliminate_dummy, + _StateSeq<>::_M_clone): Likewise. + * include/bits/regex_compiler.tcc (_Compiler<>::_M_quantifier): + Likewise. + * include/bits/regex_executor.tcc (_Executor<>::_M_dfs): Likewise. + * include/bits/regex_scanner.tcc (_Scanner<>::_M_eat_escape_ecma): + Uglify local variable __i. + * include/bits/regex_compiler.h (_BracketMatcher<>::_M_make_cache): + Use size_t instead of int to compare with vector::size(). + +2014-04-27 Tim Shen <timshen91@gmail.com> + + * include/bits/regex_executor.h: Add _M_rep_count to track how + many times this repeat node are visited. + * include/bits/regex_executor.tcc (_Executor<>::_M_rep_once_more, + _Executor<>::_M_dfs): Use _M_rep_count to prevent entering + infinite loop. + +2014-04-27 Tim Shen <timshen91@gmail.com> + + * include/bits/regex.tcc (__regex_algo_impl<>): Remove + _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT and use + _GLIBCXX_REGEX_USE_THOMPSON_NFA instead. + * include/bits/regex_automaton.h: Remove quantifier counting variable. + * include/bits/regex_automaton.tcc (_State_base::_M_dot): + Adjust debug NFA dump. + +2014-04-25 Lars Gullik Bjønnes <larsbj@gullik.org> + + PR libstdc++/60710 + * include/experimental/optional (operator!=): Implement in terms of + operator==. + * testsuite/experimental/optional/relops/1.cc: Remove operator!=. + * testsuite/experimental/optional/relops/2.cc: Likewise. + * testsuite/experimental/optional/relops/3.cc: Likewise. + * testsuite/experimental/optional/relops/4.cc: Likewise. + * testsuite/experimental/optional/relops/5.cc: Likewise. + * testsuite/experimental/optional/relops/6.cc: Likewise. + +2014-04-25 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/60958 + * include/tr1/regex (regex_traits::isctype): Comment out broken code. + * testsuite/util/testsuite_regex.h (regex_match_debug): Improve + comment. + +2014-04-25 Marc Glisse <marc.glisse@inria.fr> + + * testsuite/util/testsuite_abi.cc (check_version): Update for + CXXABI_1.3.9. + +2014-04-24 Tim Shen <timshen91@gmail.com> + + * include/bits/regex_automaton.tcc (_StateSeq<>::_M_clone()): + Do _M_alt before _M_next. + * testsuite/28_regex/basic_regex/multiple_quantifiers.cc: Add testcases. + 2014-04-24 Marc Glisse <marc.glisse@inria.fr> PR libstdc++/43622 diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc index 5fa1f018b3d..0d737a0b74b 100644 --- a/libstdc++-v3/include/bits/regex.tcc +++ b/libstdc++-v3/include/bits/regex.tcc @@ -28,12 +28,12 @@ * Do not attempt to use it directly. @headername{regex} */ -// See below __regex_algo_impl to get what this is talking about. The default -// value 1 indicated a conservative optimization without giving up worst case -// performance. -#ifndef _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT -#define _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT 1 -#endif +// A non-standard switch to let the user pick the matching algorithm. +// If _GLIBCXX_REGEX_USE_THOMPSON_NFA is defined, the thompson NFA +// algorithm will be used. This algorithm is not enabled by default, +// and cannot be used if the regex contains back-references, but has better +// (polynomial instead of exponential) worst case performace. +// See __regex_algo_impl below. namespace std _GLIBCXX_VISIBILITY(default) { @@ -66,24 +66,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION for (auto& __it : __res) __it.matched = false; - // This function decide which executor to use under given circumstances. - // The _S_auto policy now is the following: if a NFA has no - // back-references and has more than _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT - // quantifiers (*, +, ?), the BFS executor will be used, other wise - // DFS executor. This is because DFS executor has a exponential upper - // bound, but better best-case performace. Meanwhile, BFS executor can - // effectively prevent from exponential-long time matching (which must - // contains many quantifiers), but it's slower in average. - // - // For simple regex, BFS executor could be 2 or more times slower than - // DFS executor. - // - // Of course, BFS executor cannot handle back-references. + // __policy is used by testsuites so that they can use Thompson NFA + // without defining a macro. Users should define + // _GLIBCXX_REGEX_USE_THOMPSON_NFA if they need to use this approach. bool __ret; if (!__re._M_automaton->_M_has_backref - && (__policy == _RegexExecutorPolicy::_S_alternate - || __re._M_automaton->_M_quant_count - > _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT)) +#ifndef _GLIBCXX_REGEX_USE_THOMPSON_NFA + && __policy == _RegexExecutorPolicy::_S_alternate +#endif + ) { _Executor<_BiIter, _Alloc, _TraitsT, false> __executor(__s, __e, __m, __re, __flags); diff --git a/libstdc++-v3/include/bits/regex_automaton.h b/libstdc++-v3/include/bits/regex_automaton.h index a442cfe21b7..1b0da1453e9 100644 --- a/libstdc++-v3/include/bits/regex_automaton.h +++ b/libstdc++-v3/include/bits/regex_automaton.h @@ -52,6 +52,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _S_opcode_unknown, _S_opcode_alternative, + _S_opcode_repeat, _S_opcode_backref, _S_opcode_line_begin_assertion, _S_opcode_line_end_assertion, @@ -74,9 +75,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_t _M_backref_index; // for _S_opcode_backref struct { - // for _S_opcode_alternative. - _StateIdT _M_quant_index; - // for _S_opcode_alternative or _S_opcode_subexpr_lookahead + // for _S_opcode_alternative, _S_opcode_repeat and + // _S_opcode_subexpr_lookahead _StateIdT _M_alt; // for _S_opcode_word_boundary or _S_opcode_subexpr_lookahead or // quantifiers (ungreedy if set true) @@ -120,7 +120,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION explicit _NFA_base(_FlagT __f) : _M_flags(__f), _M_start_state(0), _M_subexpr_count(0), - _M_quant_count(0), _M_has_backref(false) + _M_has_backref(false) { } _NFA_base(_NFA_base&&) = default; @@ -145,7 +145,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _FlagT _M_flags; _StateIdT _M_start_state; _SizeT _M_subexpr_count; - _SizeT _M_quant_count; bool _M_has_backref; }; @@ -175,7 +174,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _StateT __tmp(_S_opcode_alternative); // It labels every quantifier to make greedy comparison easier in BFS // approach. - __tmp._M_quant_index = this->_M_quant_count++; + __tmp._M_next = __next; + __tmp._M_alt = __alt; + return _M_insert_state(std::move(__tmp)); + } + + _StateIdT + _M_insert_repeat(_StateIdT __next, _StateIdT __alt, bool __neg) + { + _StateT __tmp(_S_opcode_repeat); + // It labels every quantifier to make greedy comparison easier in BFS + // approach. __tmp._M_next = __next; __tmp._M_alt = __alt; __tmp._M_neg = __neg; diff --git a/libstdc++-v3/include/bits/regex_automaton.tcc b/libstdc++-v3/include/bits/regex_automaton.tcc index 759b053c5ef..e0ac3f94ceb 100644 --- a/libstdc++-v3/include/bits/regex_automaton.tcc +++ b/libstdc++-v3/include/bits/regex_automaton.tcc @@ -41,6 +41,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION switch (_M_opcode) { case _S_opcode_alternative: + case _S_opcode_repeat: ostr << "alt next=" << _M_next << " alt=" << _M_alt; break; case _S_opcode_subexpr_begin: @@ -72,11 +73,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION switch (_M_opcode) { case _S_opcode_alternative: + case _S_opcode_repeat: __ostr << __id << " [label=\"" << __id << "\\nALT\"];\n" << __id << " -> " << _M_next - << " [label=\"epsilon\", tailport=\"s\"];\n" + << " [label=\"next\", tailport=\"s\"];\n" << __id << " -> " << _M_alt - << " [label=\"epsilon\", tailport=\"n\"];\n"; + << " [label=\"alt\", tailport=\"n\"];\n"; break; case _S_opcode_backref: __ostr << __id << " [label=\"" << __id << "\\nBACKREF " @@ -174,6 +176,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION == _S_opcode_dummy) __it._M_next = (*this)[__it._M_next]._M_next; if (__it._M_opcode == _S_opcode_alternative + || __it._M_opcode == _S_opcode_repeat || __it._M_opcode == _S_opcode_subexpr_lookahead) while (__it._M_alt >= 0 && (*this)[__it._M_alt]._M_opcode == _S_opcode_dummy) @@ -197,20 +200,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // _M_insert_state() never return -1 auto __id = _M_nfa._M_insert_state(__dup); __m[__u] = __id; - if (__u == _M_end) - continue; - if (__dup._M_next != _S_invalid_state_id && __m[__dup._M_next] == -1) - __stack.push(__dup._M_next); if (__dup._M_opcode == _S_opcode_alternative + || __dup._M_opcode == _S_opcode_repeat || __dup._M_opcode == _S_opcode_subexpr_lookahead) if (__dup._M_alt != _S_invalid_state_id && __m[__dup._M_alt] == -1) __stack.push(__dup._M_alt); + if (__u == _M_end) + continue; + if (__dup._M_next != _S_invalid_state_id && __m[__dup._M_next] == -1) + __stack.push(__dup._M_next); } - long __size = static_cast<long>(__m.size()); - for (long __k = 0; __k < __size; __k++) + for (auto __v : __m) { - long __v; - if ((__v = __m[__k]) == -1) + if (__v == -1) continue; auto& __ref = _M_nfa[__v]; if (__ref._M_next != _S_invalid_state_id) @@ -219,6 +221,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __ref._M_next = __m[__ref._M_next]; } if (__ref._M_opcode == _S_opcode_alternative + || __ref._M_opcode == _S_opcode_repeat || __ref._M_opcode == _S_opcode_subexpr_lookahead) if (__ref._M_alt != _S_invalid_state_id) { diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h index f5a198f65e9..d7e21624e37 100644 --- a/libstdc++-v3/include/bits/regex_compiler.h +++ b/libstdc++-v3/include/bits/regex_compiler.h @@ -421,7 +421,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_make_cache(true_type) { - for (int __i = 0; __i < _M_cache.size(); __i++) + for (size_t __i = 0; __i < _M_cache.size(); __i++) _M_cache[static_cast<_UnsignedCharT>(__i)] = _M_apply(__i, false_type()); } diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc index 128dac12bd7..3cf9e457ccd 100644 --- a/libstdc++-v3/include/bits/regex_compiler.tcc +++ b/libstdc++-v3/include/bits/regex_compiler.tcc @@ -188,8 +188,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __init(); auto __e = _M_pop(); - _StateSeqT __r(_M_nfa, _M_nfa._M_insert_alt(_S_invalid_state_id, - __e._M_start, __neg)); + _StateSeqT __r(_M_nfa, _M_nfa._M_insert_repeat(_S_invalid_state_id, + __e._M_start, __neg)); __e._M_append(__r); _M_stack.push(__r); } @@ -197,8 +197,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __init(); auto __e = _M_pop(); - __e._M_append(_M_nfa._M_insert_alt(_S_invalid_state_id, __e._M_start, - __neg)); + __e._M_append(_M_nfa._M_insert_repeat(_S_invalid_state_id, + __e._M_start, __neg)); _M_stack.push(__e); } else if (_M_match_token(_ScannerT::_S_token_opt)) @@ -206,8 +206,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __init(); auto __e = _M_pop(); auto __end = _M_nfa._M_insert_dummy(); - _StateSeqT __r(_M_nfa, _M_nfa._M_insert_alt(_S_invalid_state_id, - __e._M_start, __neg)); + _StateSeqT __r(_M_nfa, _M_nfa._M_insert_repeat(_S_invalid_state_id, + __e._M_start, __neg)); __e._M_append(__end); __r._M_append(__end); _M_stack.push(__r); @@ -244,8 +244,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { auto __tmp = __r._M_clone(); _StateSeqT __s(_M_nfa, - _M_nfa._M_insert_alt(_S_invalid_state_id, - __tmp._M_start, __neg)); + _M_nfa._M_insert_repeat(_S_invalid_state_id, + __tmp._M_start, __neg)); __tmp._M_append(__s); __e._M_append(__s); } @@ -261,8 +261,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION for (long __i = 0; __i < __n; ++__i) { auto __tmp = __r._M_clone(); - auto __alt = _M_nfa._M_insert_alt(__tmp._M_start, - __end, __neg); + auto __alt = _M_nfa._M_insert_repeat(__tmp._M_start, + __end, __neg); __stack.push(__alt); __e._M_append(_StateSeqT(_M_nfa, __alt, __tmp._M_end)); } diff --git a/libstdc++-v3/include/bits/regex_executor.h b/libstdc++-v3/include/bits/regex_executor.h index 708c78e2081..c110b88a3f4 100644 --- a/libstdc++-v3/include/bits/regex_executor.h +++ b/libstdc++-v3/include/bits/regex_executor.h @@ -73,6 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_results(__results), _M_match_queue(__dfs_mode ? nullptr : new vector<pair<_StateIdT, _ResultsVec>>()), + _M_rep_count(_M_nfa.size()), _M_visited(__dfs_mode ? nullptr : new vector<bool>(_M_nfa.size())), _M_flags((__flags & regex_constants::match_prev_avail) ? (__flags @@ -104,6 +105,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: template<bool __match_mode> void + _M_rep_once_more(_StateIdT); + + template<bool __match_mode> + void _M_dfs(_StateIdT __start); template<bool __match_mode> @@ -149,9 +154,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ResultsVec& _M_results; // Used in BFS, saving states that need to be considered for the next // character. - std::unique_ptr<vector<pair<_StateIdT, _ResultsVec>>> _M_match_queue; + unique_ptr<vector<pair<_StateIdT, _ResultsVec>>> _M_match_queue; // Used in BFS, indicating that which state is already visited. - std::unique_ptr<vector<bool>> _M_visited; + vector<pair<_BiIter, int>> _M_rep_count; + unique_ptr<vector<bool>> _M_visited; _FlagT _M_flags; // To record current solution. _StateIdT _M_start_state; diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc index 68a5e0490f9..7f8993382c8 100644 --- a/libstdc++-v3/include/bits/regex_executor.tcc +++ b/libstdc++-v3/include/bits/regex_executor.tcc @@ -161,7 +161,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return false; } - // TODO: Use a function vector to dispatch, instead of using switch-case. + // __rep_count records how many times (__rep_count.second) + // this node is visited under certain input iterator + // (__rep_count.first). This prevent the executor from entering + // infinite loop by refusing to continue when it's already been + // visited more than twice. It's `twice` instead of `once` because + // we need to spare one more time for potential group capture. + template<typename _BiIter, typename _Alloc, typename _TraitsT, + bool __dfs_mode> + template<bool __match_mode> + void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>:: + _M_rep_once_more(_StateIdT __i) + { + const auto& __state = _M_nfa[__i]; + auto& __rep_count = _M_rep_count[__i]; + if (__rep_count.second == 0 || __rep_count.first != _M_current) + { + auto __back = __rep_count; + __rep_count.first = _M_current; + __rep_count.second = 1; + _M_dfs<__match_mode>(__state._M_alt); + __rep_count = __back; + } + else + { + if (__rep_count.second < 2) + { + __rep_count.second++; + _M_dfs<__match_mode>(__state._M_alt); + __rep_count.second--; + } + } + }; + template<typename _BiIter, typename _Alloc, typename _TraitsT, bool __dfs_mode> template<bool __match_mode> @@ -184,69 +216,61 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // of this quantifier". Executing _M_next first or _M_alt first don't // mean the same thing, and we need to choose the correct order under // given greedy mode. - case _S_opcode_alternative: - // Greedy. - if (!__state._M_neg) - { - // "Once more" is preferred in greedy mode. - _M_dfs<__match_mode>(__state._M_alt); - // If it's DFS executor and already accepted, we're done. - if (!__dfs_mode || !_M_has_sol) - _M_dfs<__match_mode>(__state._M_next); - } - else // Non-greedy mode - { - if (__dfs_mode) - { - // vice-versa. + case _S_opcode_repeat: + { + // Greedy. + if (!__state._M_neg) + { + _M_rep_once_more<__match_mode>(__i); + // If it's DFS executor and already accepted, we're done. + if (!__dfs_mode || !_M_has_sol) _M_dfs<__match_mode>(__state._M_next); - if (!_M_has_sol) - _M_dfs<__match_mode>(__state._M_alt); - } - else - { - // DON'T attempt anything, because there's already another - // state with higher priority accepted. This state cannot be - // better by attempting its next node. - if (!_M_has_sol) - { - _M_dfs<__match_mode>(__state._M_next); - // DON'T attempt anything if it's already accepted. An - // accepted state *must* be better than a solution that - // matches a non-greedy quantifier one more time. - if (!_M_has_sol) - _M_dfs<__match_mode>(__state._M_alt); - } - } + } + else // Non-greedy mode + { + if (__dfs_mode) + { + // vice-versa. + _M_dfs<__match_mode>(__state._M_next); + if (!_M_has_sol) + _M_rep_once_more<__match_mode>(__i); + } + else + { + // DON'T attempt anything, because there's already another + // state with higher priority accepted. This state cannot be + // better by attempting its next node. + if (!_M_has_sol) + { + _M_dfs<__match_mode>(__state._M_next); + // DON'T attempt anything if it's already accepted. An + // accepted state *must* be better than a solution that + // matches a non-greedy quantifier one more time. + if (!_M_has_sol) + _M_rep_once_more<__match_mode>(__i); + } + } + } } break; case _S_opcode_subexpr_begin: - // If there's nothing changed since last visit, do NOT continue. - // This prevents the executor from get into infinite loop when using - // "()*" to match "". - if (!_M_cur_results[__state._M_subexpr].matched - || _M_cur_results[__state._M_subexpr].first != _M_current) - { - auto& __res = _M_cur_results[__state._M_subexpr]; - auto __back = __res.first; - __res.first = _M_current; - _M_dfs<__match_mode>(__state._M_next); - __res.first = __back; - } + { + auto& __res = _M_cur_results[__state._M_subexpr]; + auto __back = __res.first; + __res.first = _M_current; + _M_dfs<__match_mode>(__state._M_next); + __res.first = __back; + } break; case _S_opcode_subexpr_end: - if (_M_cur_results[__state._M_subexpr].second != _M_current - || _M_cur_results[__state._M_subexpr].matched != true) - { - auto& __res = _M_cur_results[__state._M_subexpr]; - auto __back = __res; - __res.second = _M_current; - __res.matched = true; - _M_dfs<__match_mode>(__state._M_next); - __res = __back; - } - else + { + auto& __res = _M_cur_results[__state._M_subexpr]; + auto __back = __res; + __res.second = _M_current; + __res.matched = true; _M_dfs<__match_mode>(__state._M_next); + __res = __back; + } break; case _S_opcode_line_begin_assertion: if (_M_at_begin()) @@ -339,6 +363,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } break; + case _S_opcode_alternative: + _M_dfs<__match_mode>(__state._M_alt); + if (!__dfs_mode || !_M_has_sol) + _M_dfs<__match_mode>(__state._M_next); + break; default: _GLIBCXX_DEBUG_ASSERT(false); } diff --git a/libstdc++-v3/include/bits/regex_scanner.tcc b/libstdc++-v3/include/bits/regex_scanner.tcc index 5332d2eff84..f501ff6c2cb 100644 --- a/libstdc++-v3/include/bits/regex_scanner.tcc +++ b/libstdc++-v3/include/bits/regex_scanner.tcc @@ -335,7 +335,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else if (__c == 'x' || __c == 'u') { _M_value.erase(); - for (int i = 0; i < (__c == 'x' ? 2 : 4); i++) + for (int __i = 0; __i < (__c == 'x' ? 2 : 4); __i++) { if (_M_current == _M_end || !_M_ctype.is(_CtypeT::xdigit, *_M_current)) diff --git a/libstdc++-v3/include/experimental/optional b/libstdc++-v3/include/experimental/optional index 5f2d93fb7f6..2a3f29dcd70 100644 --- a/libstdc++-v3/include/experimental/optional +++ b/libstdc++-v3/include/experimental/optional @@ -736,12 +736,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> constexpr bool operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs) - { return !__lhs || *__lhs != __rhs; } + { return !__lhs || !(*__lhs == __rhs); } template<typename _Tp> constexpr bool operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs) - { return !__rhs || __lhs != *__rhs; } + { return !__rhs || !(__lhs == *__rhs); } template<typename _Tp> constexpr bool diff --git a/libstdc++-v3/include/tr1/regex b/libstdc++-v3/include/tr1/regex index 3cff23a2656..0387472ddcc 100644 --- a/libstdc++-v3/include/tr1/regex +++ b/libstdc++-v3/include/tr1/regex @@ -678,7 +678,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__ctype.is(__c, __f)) return true; - +#if 0 // special case of underscore in [[:w:]] if (__c == __ctype.widen('_')) { @@ -698,7 +698,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__f | __bt) return true; } - +#endif return false; } diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc index 3fdbdadedbe..c33d1b61894 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc @@ -50,6 +50,7 @@ test01() const char s[] = ""; VERIFY( regex_match_debug(s, m, re) ); } + VERIFY(regex_match_debug("", regex("(?:)*"))); } int diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/multiple_quantifiers.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/multiple_quantifiers.cc index 5670cbb8e3b..8243eea930a 100644 --- a/libstdc++-v3/testsuite/28_regex/basic_regex/multiple_quantifiers.cc +++ b/libstdc++-v3/testsuite/28_regex/basic_regex/multiple_quantifiers.cc @@ -21,7 +21,10 @@ // Tests multiple consecutive quantifiers #include <regex> +#include <testsuite_hooks.h> +#include <testsuite_regex.h> +using namespace __gnu_test; using namespace std; int @@ -29,5 +32,6 @@ main() { regex re1("a++"); regex re2("(a+)+"); + VERIFY(regex_match_debug("aa", regex("(a)*{3}"))); return 0; } diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/1.cc b/libstdc++-v3/testsuite/experimental/optional/relops/1.cc index f1408805ac2..3f1ee9c4900 100644 --- a/libstdc++-v3/testsuite/experimental/optional/relops/1.cc +++ b/libstdc++-v3/testsuite/experimental/optional/relops/1.cc @@ -37,10 +37,6 @@ namespace ns { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } bool - operator!=(value_type const& lhs, value_type const& rhs) - { return !(lhs == rhs); } - - bool operator<(value_type const& lhs, value_type const& rhs) { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/2.cc b/libstdc++-v3/testsuite/experimental/optional/relops/2.cc index c7fc848deb0..6ee9cba768a 100644 --- a/libstdc++-v3/testsuite/experimental/optional/relops/2.cc +++ b/libstdc++-v3/testsuite/experimental/optional/relops/2.cc @@ -37,10 +37,6 @@ namespace ns { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } bool - operator!=(value_type const& lhs, value_type const& rhs) - { return !(lhs == rhs); } - - bool operator<(value_type const& lhs, value_type const& rhs) { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/3.cc b/libstdc++-v3/testsuite/experimental/optional/relops/3.cc index 9729000d5ca..581d0168fbc 100644 --- a/libstdc++-v3/testsuite/experimental/optional/relops/3.cc +++ b/libstdc++-v3/testsuite/experimental/optional/relops/3.cc @@ -37,10 +37,6 @@ namespace ns { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } bool - operator!=(value_type const& lhs, value_type const& rhs) - { return !(lhs == rhs); } - - bool operator<(value_type const& lhs, value_type const& rhs) { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/4.cc b/libstdc++-v3/testsuite/experimental/optional/relops/4.cc index 45378f688e4..ce16fcb92f5 100644 --- a/libstdc++-v3/testsuite/experimental/optional/relops/4.cc +++ b/libstdc++-v3/testsuite/experimental/optional/relops/4.cc @@ -37,10 +37,6 @@ namespace ns { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } bool - operator!=(value_type const& lhs, value_type const& rhs) - { return !(lhs == rhs); } - - bool operator<(value_type const& lhs, value_type const& rhs) { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/5.cc b/libstdc++-v3/testsuite/experimental/optional/relops/5.cc index 008409ef402..c01bba57a5e 100644 --- a/libstdc++-v3/testsuite/experimental/optional/relops/5.cc +++ b/libstdc++-v3/testsuite/experimental/optional/relops/5.cc @@ -37,10 +37,6 @@ namespace ns { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } bool - operator!=(value_type const& lhs, value_type const& rhs) - { return !(lhs == rhs); } - - bool operator<(value_type const& lhs, value_type const& rhs) { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/6.cc b/libstdc++-v3/testsuite/experimental/optional/relops/6.cc index b17914062ee..a24622b5f40 100644 --- a/libstdc++-v3/testsuite/experimental/optional/relops/6.cc +++ b/libstdc++-v3/testsuite/experimental/optional/relops/6.cc @@ -37,10 +37,6 @@ namespace ns { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); } bool - operator!=(value_type const& lhs, value_type const& rhs) - { return !(lhs == rhs); } - - bool operator<(value_type const& lhs, value_type const& rhs) { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); } diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc index 6b5299b8e7e..39635cb2fca 100644 --- a/libstdc++-v3/testsuite/util/testsuite_abi.cc +++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc @@ -210,6 +210,7 @@ check_version(symbol& test, bool added) known_versions.push_back("CXXABI_1.3.6"); known_versions.push_back("CXXABI_1.3.7"); known_versions.push_back("CXXABI_1.3.8"); + known_versions.push_back("CXXABI_1.3.9"); known_versions.push_back("CXXABI_TM_1"); } compat_list::iterator begin = known_versions.begin(); @@ -227,7 +228,7 @@ check_version(symbol& test, bool added) // Check that added symbols are added in the latest pre-release version. bool latestp = (test.version_name == "GLIBCXX_3.4.20" - || test.version_name == "CXXABI_1.3.8" + || test.version_name == "CXXABI_1.3.9" || test.version_name == "CXXABI_TM_1"); if (added && !latestp) test.version_status = symbol::incompatible; diff --git a/libstdc++-v3/testsuite/util/testsuite_regex.h b/libstdc++-v3/testsuite/util/testsuite_regex.h index 9460ed6ae31..c2031e90a23 100644 --- a/libstdc++-v3/testsuite/util/testsuite_regex.h +++ b/libstdc++-v3/testsuite/util/testsuite_regex.h @@ -131,7 +131,7 @@ namespace __gnu_test // regex_match_debug behaves like regex_match, but will run *two* executors // (if there's no back-reference) and check if their results agree. If not, - // an exception throws. One can use them just in the way of using regex_match. + // an exception is thrown. The arguments are the same as for regex_match. template<typename _Bi_iter, typename _Alloc, typename _Ch_type, typename _Rx_traits> bool @@ -153,7 +153,7 @@ namespace __gnu_test // __m is unspecified if return value is false. if (__res1 == __res2 && (!__res1 || __m == __mm)) return __res1; - throw(std::exception()); + throw std::exception(); } // No match_results version |